Question

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!

Was it helpful?

Solution

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.

OTHER TIPS

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).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top