在Outlook中永久删除邮件

4

我正在尝试使用Outlook API删除邮件项。像下面这样:

Dim objMail
For each objMail in objFolder.Items
objMail.Delete
Next

很明显,立即删除项目太简单了。Outlook只是将其移动到“已删除的邮件”文件夹中,而不是永久删除。我尝试使用代码获取“已删除的邮件”文件夹。
OutlookNameSpace.GetDefaultFolder(olDeletedItems)

并且再次删除邮件,但是该代码执行的PST不是默认邮箱,并且返回的文件夹是错误的已删除项文件夹。如何永久删除此邮件?我尝试循环遍历当前存储中的所有文件夹,但无法判断哪个文件夹是已删除项文件夹,除非通过比较名称,但由于程序将用于多种语言,因此名称对于每个版本都不同。PS:我不能使用第三方dll :( 求助!
4个回答

4

你的代码的第一个问题是使用的循环不合适。如果你想删除(几乎任何VBA中的东西),你需要从最后一个元素到第一个元素循环你的集合。否则,你会改变集合的顺序-在你删除第一个元素之后,第二个元素被移动到第一位置并且不会被删除。

因此,这段代码应该删除你的DeltetedItems文件夹中的所有项目:

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

显然,您可以准备类似的代码来删除任何其他文件夹中的内容。您需要运行两个删除循环以确保删除项目。
以下是有关MSDN上MailItem.Delete Method的一些额外说明: 删除方法删除集合中的单个项。要删除文件夹中项目集合中的所有项目,必须从文件夹中的最后一个项目开始逐个删除每个项目。例如,在文件夹AllItems的项目集合中,如果文件夹中有n个项目,则从AllItems.Item(n)处开始删除项目,每次递减索引,直到删除AllItems.Item(1)为止。
由于OP的一些评论,进行了如下编辑。 即使您需要删除某些项目(而不是全部),也请记住使用我上面介绍的循环类型。 如果您需要参考其他存储中的任何其他DeletedItems文件夹,则可以通过以下方式找到此文件夹:
'with index reference
Application.GetNamespace("MAPI").Stores(2).getdefaultfolder(olFolderDeletedItems)
'with name reference
Application.GetNamespace("MAPI").Stores("Business Mail").getdefaultfolder(olFolderDeletedItems)

我不知道这是否适用于所有Outlook版本,但它可以在Outlook 2010上工作。


好的,首先,我不想删除文件夹中的所有项目。上述代码是一个更复杂的循环的示例,如果该项目符合指定条件,则我想要将其删除。其次,Application.GetNamespace("MAPI").GetDefaultFolder(olfolderDeletedItems)返回默认STORE的已删除项目。我要删除的项目不在默认存储中,而是在代码先前挂载的归档存储中,这就是为什么上述代码无法工作的原因。如何获取特定存储的已删除项目文件夹,而不是默认的文件夹? - Machinegon
1
然而,这在2010年之前的版本上不起作用,但是循环类型加1。我找到了一种方法来避免使用getDefaultFolder方法,我只需将项目的条目ID存储在变量中,循环遍历所有文件夹,直到找到具有我的ID的项目并获取项目文件夹并假定它是已删除项目文件夹。因为我只是调用了.Delete。 - Machinegon
@Machinegon,您是否使用EntryId属性来查找元素?如果是这样,您就不需要循环查找适当的文件夹。 - Kazimierz Jawor
不,我使用放置在ItemProprities集合中的自定义GUID,请参见下面的答案。 - Machinegon

3

为了参考,这里是永久删除一个项目的最终方法。

附注:迁移ID是之前存储的GUID,是一种无懈可击的方式来跟踪该项目。

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

1
在删除邮件项之前,您可以检查其EntryID属性以避免循环。接下来,在您删除它之后,您可以使用此方法Application.Session.GetItemFromID("...idhere...")找到该元素,并通过此方式找到其文件夹:Application.Session.GetItemFromID("...idhere...").parent - Kazimierz Jawor

1
此外,如果您需要从除默认存储之外的存储中获取已删除项目文件夹,请使用 Store.GetDefaultFolder 而不是 Namespace.GetDefaultFolder
如果您想完全绕过已删除项目文件夹,您将需要使用扩展 MAPI(仅限 C++ 或 Delphi - IMAPIFolder::DeleteMessages),或者使用 Redemption(我是其作者 - 任何语言 - 其RDOMail.Delete 方法允许永久删除消息或将其移动到已删除项目文件夹)。

这似乎在2010年以前的版本中无法正常工作,您知道一个可行的解决方法吗?我需要脚本能够跨2002、2003、2007、2010版本兼容。 - Machinegon
你可以尝试使用Namespace.Folders集合(返回每个存储的顶级文件夹)并通过名称访问文件夹,但这在本地化版本的Outlook中会出现问题。否则,您可以使用Extended MAPI(仅限C++或Delphi)或Redemption(支持所有版本的Outlook)。 - Dmitry Streblechenko

1
我曾遇到同样的问题 - 我的代码想要在同步时删除预约项目,但这却堵塞了已删除项目文件夹。但我意识到 - 当你删除一个对象时,它所做的一切只是将其移动到“已删除项目”。 所以只需要删除两次!不需要担心跟踪属性,或清空整个文件夹(可能过度杀伤力)。

编辑:不好意思,这种方法不可行。愚蠢的 Outlook。我尝试使用Move方法,然后从“已删除项目”中删除,但结果它把它放到了草稿文件夹中。

看起来有效的方法是先删除一个项目,然后再删除“已删除项目”中的最后一个项目。

以下是我的一段代码片段:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接