【问题标题】:Track email through the draft/send/sent process通过草稿/发送/发送过程跟踪电子邮件
【发布时间】:2020-12-27 23:34:14
【问题描述】:

我想跟踪电子邮件在其生命周期的各个阶段和文件夹中的状态,包括“草稿”、“发件箱”和“已发送”。

相关的兴趣是访问现有电子邮件以收集属性信息的能力,例如发送时间。

我从包含的代码块开始。 Do Loop 在发送电子邮件时失败,因为变量与电子邮件断开连接。

这会导致运行时错误

该项目已被移动或删除。

错误号(Err.Number)每次都不一样,不知设计目的是什么。

当邮件在草稿箱、发件箱和已发送邮件中移动时,我如何才能与它们保持联系?

我看到很多关于变量与邮件项断开连接的提及,但没有依赖对象层次结构并避免后期绑定来解决问题的解决方案。我想也许会有一个识别消息的 GUID 或 UUID,但如文档中所述,如果项目被移动,所有属性(如 EntryID)都可以更改,并且不应依赖此类属性。

通过更深入的检查,这是有道理的,因为电子邮件只是数据库表中的一条记录。如果您在表之间复制/删除记录,则信息可能相同或相似,但记录号可能不会。
此外,这也打击了其他钉子:同一封电子邮件可以发送多次,也可以复制/粘贴到不同的文件夹,甚至不同的帐户中。现在什么是独特的?

除了与电子邮件保持“连接”之外,还可以使用哪些属性或技术来识别电子邮件?

如果没有“正确”的方式来识别所描述的邮件项,那么我唯一能想到的就是使用现有或自定义字段(如 OCX 控件的“标签”属性)来插入 UUID。一些公司通过在主题行中添加呼叫/订单/支持号码来使用这种技术,以便更容易跟踪。

Dim outlobj As Outlook.Application
Dim mailobj As Outlook.MailItem
Set outlobj = Outlook.Application
Set mailobj = outlobj.CreateItem(olMailItem)
With mailobj
    .Recipients.Add "wonderwoman@hallofjustice.com"
    .Subject = "Invisible Jet Scheduled Maintenance Reminder"
    .Body = "Your invisible jet need to be polished."
    .Attachments.Add zipFilename
    .Display
    .Send
End With

Do
    'next line fails due to email moving through Drafts, Outbox, & Sent
    'notably, the VBA runtime Err.Num is different each time
    'how do i keep the variable connected to a moving target?
    If mailobj.Sent = False Then
        Sleep 100
    Else
        MsgBox "The email has been sent."
        'other code
        Exit Do
    End If
Loop

【问题讨论】:

  • 创建一个类并添加MailItem 作为该类的事件启用属性。处理诸如打开/写入/发送/保存等事件以对电子邮件生命周期进行自定义控制。 EntryID 是每个邮件项的唯一属性。

标签: vba email outlook


【解决方案1】:

创建一个类并将 MailItem 添加为该类的事件启用属性。处理诸如打开/写入/发送/保存等事件以对电子邮件生命周期进行自定义控制。 EntryID 是每个邮件项的唯一属性。


请注意,条目 ID 仅在第一次保存项目后生成,并且在用户手动在文件夹之间移动项目时隐式更改。


以下是帮助您入门的示例:

像这样添加一个类Class1

Option Explicit

Public WithEvents mItem As MailItem
Public id               As String

Private Sub mItem_Open(Cancel As Boolean)
    MsgBox "Mail item will be displayed."
    id = mItem.EntryID
End Sub

使用以下代码添加模块:

Option Explicit

Sub test()

    Dim cls As New Class1
    Dim id  As String

    Dim outlobj As Outlook.Application
    Dim mailobj As Outlook.MailItem
    Set outlobj = Outlook.Application
    Set mailobj = outlobj.CreateItem(olMailItem)

    Set cls.mItem = mailobj

    With mailobj
    .Recipients.Add "xx@yy.zz"
    .Subject = "Test"
    .Body = "Test Content of the e-mail."
    .Save
    .Display
    id = cls.id '/ Store ID for later use.
    Debug.Print id
    End With


  '/ Search that e-mail and display its body contents
  Call Retrieve(id)


End Sub


Sub Retrieve(sEntryId As String)
    Dim mailobj As Outlook.MailItem
    Dim ns As NameSpace

    Set ns = GetNamespace("MAPI")
    Set mailobj = ns.GetItemFromID(sEntryId)
    MsgBox mailobj.Body

End Sub

运行子test

【讨论】:

  • 不需要Dim outlobj As Outlook.Application 只需使用Set mailobj = Application.CreateItem(olMailItem)
  • Dim outlobj As Outlook.Application 是它尝试启动 Outlook 并引发“462:远程服务器不可用”等错误的原因。如果 Outlook 启动不够快..?我一直假设有一种方法可以在不启动 Outlook 的情况下创建/发送电子邮件,但我还没有研究过......
猜你喜欢
  • 2015-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-15
  • 2014-03-20
  • 1970-01-01
  • 2015-05-05
  • 2012-01-07
相关资源
最近更新 更多