I am looking for a way to permanently delete a MailMessage from Outlook 2000 with VBA code. I'd like to do this without having to do a second loop to empty the Deleted items.
Essentially, I am looking for a code equivalent to the UI method of clicking a message and hitting SHIFT+DELETE.
Is there such a thing?
Try moving it first then deleting it (works on some patchs in 2000) or use RDO or CDO to do the job for you (you will have to install them)
Set objDeletedItem = objDeletedItem.Move(DeletedFolder)
objDeletedItem.Delete
CDO way
Set objCDOSession = CreateObject("MAPI.Session")
objCDOSession.Logon "", "", False, False
Set objMail = objCDOSession.GetMessage(objItem.EntryID, objItem.Parent.StoreID)
objMail.Delete
RDO
set objRDOSession = CreateObject("Redemption.RDOSession")
objRDOSession.MAPIOBJECT = objItem.Session.MAPIOBJECT
set objMail = objRDOSession.GetMessageFromID(objItem.EntryID>)
objMail.Delete
You could also mark the message first before you delete it and the loop through the deleted items folder and find it an dthe call delete a second time. Mark it using a Userproperty.
objMail.UserProperties.Add "Deleted", olText
objMail.Save
objMail.Delete
loop through you deleted items look for that userprop
Set objDeletedFolder = myNameSpace.GetDefaultFolder(olFolderDeletedItems)
For Each objItem In objDeletedFolder.Items
Set objProperty = objItem.UserProperties.Find("Deleted")
If TypeName(objProperty) <> "Nothing" Then
objItem.Delete
End If
Next
Simplest solution of all, similar to the first way:
FindID = deleteme.EntryID
deleteme.Delete
set deleteme = NameSpace.GetItemFromID(FindID)
deleteme.Delete
Do it twice and it'll be gone for good, and no performance killing loop. (NameSpace can be a particular namespace variable, if not in the default store.) Note this only works if you don't delete across stores, which can change the EntryID or remove it entirely.
I know this is an old thread, but since I recently had cause to write a macro that does this, I thought I'd share. I found that the Remove method appears to be a permanent deletion. I'm using this snippet:
While oFilteredItems.Count > 0
Debug.Print " " & oFilteredItems.GetFirst.Subject
oFilteredItems.Remove 1
Wend
I begin with a list of items that have been filtered by some criteria. Then, I just delete one at a time until it's gone.
HTH
You can use the following approach, basically you delete all of your email messages as you are currently doing, then call this one line to empty the deleted items folder. The code is in jscript, but I can translate if you really need me to :)
var app = GetObject("", "Outlook.Application"); //use new ActiveXObject if fails
app.ActiveExplorer().CommandBars("Menu Bar").Controls("Tools").Controls('Empty "Deleted Items" Folder').Execute();
Recently I had to permamentnly delete all contacts. This worked for me (Outlook 2016). You have obtain new reference to the item in the trash folder, otherwise it says "already deleted" or something like that. Just go from the end and the recently moved items will be there. Then calling Delete achieves permanent deletion. This snippet can be used in a loop.
myContacts(i).Move (trashFolder)
trashCount = trashFolder.Items.Count
For j = trashCount To 1 Step -1
Set trashItem = trashFolder.Items(j)
If trashItem.MessageClass = "IPM.Contact" Then
trashItem.Delete
Else
Exit For
End If
Next
Related
I'm in a bit of a conundrum. A piece of code that worked before no longer works as I expect it to without an apparent reason.
The particular piece that doesn't work can be simplified down to this:
Sub addCC()
dim mail as Outlook.MailItem
dim recip as Recipient
set mail = Application.ActiveInspector.CurrentItem
set recip = mail.Recipients.Add("myself#mydomain.com")
recip.Type = olCC
End Sub
When I run this on the mail item, on the first run it adds the recipient in the To field not the CC field. On subsequent reruns of the sub on the same mail item, it keeps adding the email address in CC as expected. Only on the first run it adds a TO instead of CC.
I was using this piece of code before and it worked as expected. Now it doesn't and I don't know what's going awry.
I can reproduce the problem. The best course of action is to open a support case with MS (https://support.microsoft.com/en-us/assistedsupportproducts?wa=wsignin1.0) to ensure this problem gets fixed.
I made a script to auto forward messages (with custom response) and, from what i gathered, it has to be on a running Outlook for it to be working.
The issue is that if a couple of machines are running that script will it "go off" multiple times?
from specific sender
containing XYZ in subject
except when it contains ABC in subject
Public Sub FW(olItem As Outlook.MailItem)
Dim olForward As Outlook.MailItem
Set olForward = olItem.Forward
With olForward
'Stuff happens here that work properly
End With
End If
'// Clean up
Set olItem = Nothing
Set olForward = Nothing
End Sub
As #Barney comment is absolutely correct and multiple runs of the script will trigger multiple forward of the item, I would like to add what you should do to perform your action once.
In the script right after successful forward of the message you should add a custom property into the item. The property will just indicate that the message was already forwarded (may be parsed/touched by your script). Now make the condition for entire item handling and check this property exists. If it does, do not perform any actions. The following resource will help with custom properties: How To: Add a custom property to the UserProperties collection of an Outlook e-mail item
I routinely have to move a decent amount of email (150+) from a subfolder to another. There are many folders in the mailbox that I perform this task on. It seems like it would be an easy macro to write, but what I have is substantially slower than doing a Ctrl+A, drag to destination folder.
I have reviewed previous questions about moving Outlook emails and Microsoft's documentation, but I am unable to figure out how to accomplish moving the emails in a a fast and reliable manner. I would appreciate any information on where I am going wrong and if there is another solution besides VBA.
My current code is below. My end goal would be to loop through a list of folder names (instead of me selecting the folder).
Thanks in advance.
Sub MoveEmailsToDone()
On Error Resume Next
Dim ns As Outlook.NameSpace
Dim AnalystFolder As Outlook.MAPIFolder
Dim MoveToFolder As Outlook.MAPIFolder
Set ns = Application.GetNamespace("MAPI")
Set AnalystFolder = Application.ActiveExplorer.CurrentFolder
Set MoveToFolder = ns.Folders("username#domain.com").Folders(AnalystFolder.Name & "-DONE")
For i = AnalystFolder.Items.Count To 1 Step -1
AnalystFolder.Items(i).Move MoveToFolder
Next i
Set ns = Nothing
Set AnalystFolder = Nothing
Set MoveToFolder = Nothing
End Sub
From experience Move and Delete are slow.
http://computer-programming-forum.com/1-vba/17216b85e9c096d3.htm
07 Jul 2003
The following code loops through each mail item in a specified folder
and moves the item to another folder. For 1100 items, it takes more
than 5 min. It doesn't move that slow when I select all and move in
the user interface.
.
Outlook uses Extended MAPI to implement a move operation, namely
IMAPIFolder::CopyMessages() which takes a list of entryids, hence it does not
need to open each message. Store provider completes the whole operation on the
server without sending lots of data back and forth as apparently happens when
you run your code.
Dmitry Streblechenko
https://stackoverflow.com/users/332059/dmitry-streblechenko
DoEvents lets you use Outlook while the code runs.
For i = AnalystFolder.Items.Count To 1 Step -1
DoEvents
AnalystFolder.Items(i).Move MoveToFolder
Next i
MsgBox "MoveEmailsToDone is finally done."
I'm trying to delete a mailitem using the outlook API. Like the following,
Dim objMail
For each objMail in objFolder.Items
objMail.Delete
Next
Obviously, deleting an item straight away is to simple. Outlook just move it into the "Deleted Items" folder instead of deleting it. I tried to get the "Deleted Items" folder using
OutlookNameSpace.GetDefaultFolder(olDeletedItems)
and delete the mail again, but the PST the code is working on is not the default mailbox and the folder returned is the wrong deleted items folder. How can I permanently delete this mailitem?
I tried to loop through all folders in the current store, but there's no way of telling which folder is the deleted items folder except by comparing names, I can't do that since the programs will be used in multiple languages and the name is different for each version.
PS: I cannot use a third party dll :(
Help!
First problem of your code is not appropriate loop you use. If you want to delete (almost anything in VBA) you need to loop your collection from the last element to first. If not, you change the order of the collection- after you delete 1st element >> 2nd one is moved to 1st position and will not be deleted.
Therefore this code should delete all items from your DeltetedItems folder:
Sub Delete_all_from_dust_bin()
Dim myFolder As Outlook.Folder
Set myFolder = Application.GetNamespace("MAPI"). _
GetDefaultFolder(olFolderDeletedItems)
Dim i As Long
For i = myFolder.items.Count To 1 Step -1
myFolder.items(i).Delete
Next i
End Sub
Obviously, you could prepare similar code for deleting from any other folder. You will run both deletion loops to remove items for sure.
Some additional remarks for MailItem.Delete Method from MSDN:
The Delete mothod deletes a single item in a collection. To delete all
items in the Items collection of a folder, you must delete each item
starting with the last item in the folder. For example, in the items
collection of a folder, AllItems, if there are n number of items in
the folder, start deleting the item at AllItems.Item(n), decrementing
the index each time until you delete AllItems.Item(1).
Edit due to some comments from OP.
Even if you need to delete some items (not all) remember to use the loop type I presented above.
If you need to refer to any other DeletedItems folder in other stores you can find this folder in these ways:
'with index reference
Application.GetNamespace("MAPI").Stores(2).getdefaultfolder(olFolderDeletedItems)
'with name reference
Application.GetNamespace("MAPI").Stores("Business Mail").getdefaultfolder(olFolderDeletedItems)
I don't know if this works with all Outlook versions but it's working with Outlook 2010.
For reference purpose, here's the final method to permanently delete an item I found.
PS: The Migration ID is GUID previously stored for a bulletproof-way to track the item
Dim mailIndex
For mailIndex = objFolder.Items.Count To 1 Step - 1
Dim migrationProperty
Set migrationProperty = GetMigrationProperty(objFolder.Items(mailIndex).ItemProperties
if not migrationProperty is nothing Then
objFolder.Items(mailIndex).Delete
Call DeleteMailPermanently(migrationProperty.Value)
End if
Next
Function DeleteMailPermanently(strMailMigrationID)
Dim objDeletedMail, objDeletedMigrationProperty
Set m_objPSTDeletedItemsFolder
= GetDeletedItemsFolder(PSTStore, strMailMigrationID)
For Each objDeletedMail in m_objPSTDeletedItemsFolder.Items
Set objDeletedMigrationProperty
= GetMigrationProperty(objDeletedmail.ItemProperties)
if not objDeletedMigrationProperty is nothing
and objDeletedMigrationProperty.Value = strMailMigrationID then
objDeletedMail.Delete
Next
End Function
Function GetDeletedItemsFolder(objParentFolder, strMigrationID)
Dim objFolder, objMail
For each objMail in objFolder.Items
Dim migrationProperty
Set migrationProperty = GetMigrationProperty(objMail.ItemProperties)
If migrationProperty.Value = strMigrationID
Set GetDeletedItemsFolder = objFolder
Exit Function
End If
Next
if objFolder.Folders.Count >= 1 Then
Dim subFolder
Set subFolder = GetDeletedItemsFolder(objFolder, strMigrationID)
If not subFolder is Nothing Then
Set GetDeletedItemsFolder = subFolder
Exit Function
End If
Set GetDeletedItemsFolder = Nothing
End function
I had the same problem - my code wanted to delete appointment items as part of a sync, but this was clogging up the Deleted Items folder. But what I realised was - when you delete an object, all it's doing is moving it to Deleted Items. So just delete it twice! No need to worry about tracking properties, or clearing out the whole folder (which may be overkill).
EDIT: no, sorry, this doesn't work. Stupid Outlook. I tried using the Move method, and then deleting from Deleted Items, but it just puts it in the Drafts folder instead, bizarrely.
What seems to work is deleting an item, then deleting the last item in Deleted Items.
Here's a fragment of my code:
Set ns = Application.GetNamespace("MAPI")
Set delItemsFolder = ns.GetDefaultFolder(olFolderDeletedItems)
Set calItems = syncFolder.Items
For i = calItems.Count To 1 Step -1
calItems(i).Delete
delItemsFolder.Items.Item(delItemsFolder.Items.Count).Delete
Next
Also, if you need the Deleted Items folder from a store other than the default store. use Store.GetDefaultFolder instead of Namespace.GetDefaultFolder.
If you want to completely bypass the Deleted Items folder, you will need to either use Extended MAPI (C++ or Delphi only - IMAPIFolder::DeleteMessages) or Redemption (I am its author - any language - its RDOMail.Delete method allows to either permanently delete the message or move it to the Deleted Items folder).
I hope it's okay to ask this kind of question. Attempting to write the code myself is completely beyond me at the moment.
I need a macro for Outlook 2007 that will permanently delete all content of the Sent Items folder whenever anything arrives in it. Is it possible? How do I set everything up so that the user doesn't ever have to click anything to run it?
I know I'm asking for a fish, and I'm embarrassed, but I really need the thing...
edit:
I've pasted this into the VBA editor, into a new module:
Public Sub EmptySentEmailFolder()
Dim outApp As Outlook.Application
Dim sentFolder As Outlook.MAPIFolder
Dim item As Object
Dim entryID As String
Set outApp = CreateObject("outlook.application")
Set sentFolder = outApp.GetNamespace("MAPI").GetDefaultFolder(olFolderSentMail)
For i = sentFolder.Items.Count To 1 Step -1
sentFolder.Items(i).Delete '' Delete from mail folder
Next
Set item = Nothing
Set sentFolder = Nothing
Set outApp = Nothing
End Sub
It's just a slightly modified version of a piece of code I found somewhere on this site deleting Deleted Items. It does delete the Sent Items folder when I run it. Could you please help me modify it in such a way that it deletes Sent Items whenever anything appears in the folder, and in such a way that the user doesn't have to click anything to run it? I need it to be a completely automated process.
edit 2: Please if you think there's a better tool to achieve this than VBA, don't hesitate to edit the tags and comment.
edit 3: I did something that works sometimes, but sometimes it doesn't. And it's ridiculously complicated. I set a rule that ccs every sent email with an attachment to me. Another rule runs the following code, when an email from me arrives.
Sub Del(item As Outlook.MailItem)
Call EmptySentEmailFolder
End Sub
The thing has three behaviors, and I haven't been able to determine what triggers which behavior. Sometimes the thing does purge the Sent Items folder. Sometimes it does nothing. Sometimes the second rule gives the "operation failed" error message.
The idea of acting whenever something comes from my address is non-optimal for reasons that I'll omit for the sake of brevity. I tried to replace it with reports. I made a rule that sends a delivery report whenever I send an email. Then another rule runs the code upon receipt of the report. However, this has just one behavior: it never does anything.
Both ideas are so complicated that anything could go wrong really, and I'm having trouble debugging them. Both are non-optimal solutions too.
Would this be an acceptable solution? Sorry its late but my copy of Outlook was broken.
When you enter the Outlook VB Editor, the Project Explorer will be on the left. Click Ctrl+R if it isn't. It will look something like this:
+ Project1 (VbaProject.OTM)
or
- Project1 (VbaProject.OTM)
+ Microsoft Office Outlook Objects
+ Forms
+ Modules
"Forms" will be missing if you do not have any user forms. It is possible "Modules" is expanded. Click +s as necessary to get "Microsoft Office Outlook Objects" expanded:
- Project1 (VbaProject.OTM)
- Microsoft Office Outlook Objects
ThisOutlookSession
+ Forms
+ Modules
Click ThisOutlookSession. The module area will turn white unless you have already used this code area. This area is like a module but have additional privileges. Copy this code to that area:
Private Sub Application_MAPILogonComplete()
' This event routine is called automatically when a user has completed log in.
Dim sentFolder As Outlook.MAPIFolder
Dim entryID As String
Dim i As Long
Set sentFolder = CreateObject("Outlook.Application"). _
GetNamespace("MAPI").GetDefaultFolder(olFolderSentMail)
For i = sentFolder.Items.Count To 1 Step -1
sentFolder.Items(i).Delete ' Move to Deleted Items
Next
Set sentFolder = Nothing
End Sub
I have taken your code, tidied it up a little and placed it within an event routine. An event routine is automatically called when the appropriate event occurs. This routine is called when the user has completed their log in. This is not what you requested but it might be an acceptable compromise.
Suggestion 2
I have not tried an ItemAdd event routine on the Sent Items folder before although I have used it with the Inbox. According to my limited testing, deleting the sent item does not interfere with the sending.
This code belongs in "ThisOutlookSession".
Option Explicit
Public WithEvents MyNewItems As Outlook.Items
Private Sub Application_MAPILogonComplete()
Dim NS As NameSpace
Set NS = CreateObject("Outlook.Application").GetNamespace("MAPI")
With NS
Set MyNewItems = NS.GetDefaultFolder(olFolderSentMail).Items
End With
End Sub
Private Sub myNewItems_ItemAdd(ByVal Item As Object)
Debug.Print "--------------------"
Debug.Print "Item added to Sent folder"
Debug.Print "Subject: " & Item.Subject
Item.Delete ' Move to Deleted Items
Debug.Print "Moved to Deleted Items"
End Sub
The Debug.Print statements show you have limited access to the sent item. If you try to access more sensitive properties, you will trigger a warning to the user that a macro is assessing emails.