要求是将附件上传到服务器。但是,我们只想上传那些出现在 Outlook 的“消息”行(见下图)的内容,而不是电子邮件正文中的其他内容。
由于 Outlook 本身知道应该在该行中显示哪个附件,因此必须有它用来在内部区分它们的信息。
那么,我怎样才能在我的 VBA 程序中做到这一点呢?我尝试使用MailItem.Attachments,但所有附件都在那里,我找不到它们的任何属性可以用来区分。
更新 原始标题“使用 Outlook VBA 区分嵌入的附件”有点误导。所以我改了标题。
展望截图:

要求是将附件上传到服务器。但是,我们只想上传那些出现在 Outlook 的“消息”行(见下图)的内容,而不是电子邮件正文中的其他内容。
由于 Outlook 本身知道应该在该行中显示哪个附件,因此必须有它用来在内部区分它们的信息。
那么,我怎样才能在我的 VBA 程序中做到这一点呢?我尝试使用MailItem.Attachments,但所有附件都在那里,我找不到它们的任何属性可以用来区分。
更新 原始标题“使用 Outlook VBA 区分嵌入的附件”有点误导。所以我改了标题。
展望截图:

到目前为止,我可以测试,嵌入的附件总是有一个 MIME 内容 ID,无论它是否出现在邮件正文中。所以解决方法是检查它是否有内容ID。
这是一个计算可见附件的示例代码:
Sub ShowVisibleAttachmentCount()
Const PR_ATTACH_CONTENT_ID As String = "http://schemas.microsoft.com/mapi/proptag/0x3712001F"
Const PR_ATTACHMENT_HIDDEN As String = "http://schemas.microsoft.com/mapi/proptag/0x7FFE000B"
Dim m As MailItem
Dim a As Attachment
Dim pa As PropertyAccessor
Dim c As Integer
Dim cid as String
Dim body As String
c = 0
Set m = Application.ActiveInspector.CurrentItem
body = m.HTMLBody
For Each a In m.Attachments
Set pa = a.PropertyAccessor
cid = pa.GetProperty(PR_ATTACH_CONTENT_ID)
If Len(cid) > 0 Then
If InStr(body, cid) Then
Else
'In case that PR_ATTACHMENT_HIDDEN does not exists,
'an error will occur. We simply ignore this error and
'treat it as false.
On Error Resume Next
If Not pa.GetProperty(PR_ATTACHMENT_HIDDEN) Then
c = c + 1
End If
On Error GoTo 0
End If
Else
c = c + 1
End If
Next a
MsgBox c
End Sub
当我浏览所有 Outlook 电子邮件时,它会在一行中提供相同数量的附件。
更新
感谢 Dmitry Streblechenko 的信息,我使用 Java 电子邮件库生成的电子邮件测试了 Outlook。结果显示,当电子邮件附件包含 CID 但未出现在电子邮件正文中时,它将出现在附件行中。
更新
看起来仍有一些情况表明这还不够好。我生成了以下 MIME 电子邮件正文:
Message-ID: <1044564324.2.1360638429705.JavaMail.joe@xxxx>
Subject: Test
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="----=_Part_0_1327112367.1360638429515"
Return-Path: xxxx@xxxx.xxx
X-OriginalArrivalTime: 12 Feb 2013 03:07:16.0096 (UTC) FILETIME=[0FC1B000:01CE08CE]
------=_Part_0_1327112367.1360638429515
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
TTT
------=_Part_0_1327112367.1360638429515
Content-Type: multipart/related;
boundary="----=_Part_1_1747887937.1360638429520"
------=_Part_1_1747887937.1360638429520
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html><head><meta http-equiv=3D'content-type' content=3D'text/html; charset=
=3DUTF-8'></head><title>TTT</title><body><img src=3D"cid:test1.png" alt=3D'=
=E6=81=AD=E8=B4=BA=E6=96=B0=E7=A6=A7' /><p>txt</p></body></html>
------=_Part_1_1747887937.1360638429520
Content-Type: image/png
Content-Transfer-Encoding: base64
Content-ID: <test.png>
iVBORw0KGgoAAAANSUhEUgAAAIIAAAAmCAYAAAAIjkMFAAABHUlEQVR42u3Z0Q7CIAyFYd//pafx
ckFoS9ELvz8aE9mQrIfTFh8PAAAAAPgp1+t1vT9i32fm6FzP6JrKb3aulRAGARm9Z9dUAhWZY7Wm
7Hr+IvhdD+s+PhLCLNBZQZ12HI7QlBqyQohctxM8bvAFIcx2eEYIo/vuY5WAi3BzWlhZ+if7zs7T
UWtE10Asgd3bUSxWHvrMobJOtXITQkjk5Z3gdaWaqBBWouYIhdy+E+TsPNHU0CUEbjDJ49GxE0KI
nBNUheAcYbPVy9QNmRaxUvVHd7Idf0gU2QDOduVqnkinoEb4QY1Q3V2RNrMqpB0h6BqKh0gZIWT/
AzjVycwcjSMcPI3buSebZiptaLbIBQAAAAAAAAAAAAAAAP6OJyO5jJ4bZa/gAAAAAElFTkSuQmCC
------=_Part_1_1747887937.1360638429520--
------=_Part_0_1327112367.1360638429515--
请注意,我更改了正文中的引用图像内容 ID,而实际图像的内容 ID 错误(因此未引用)。但是,图像不在电子邮件的主要部分(它在替代部分的分支中)。这使得它在前景中不可见。
所以为了检测我们必须确保附件出现在主要的 MIME 部分中......寻找这样做的方法。
更新
进一步挖掘我到达了这个链接,我又添加了一个测试 -PR_ATTACHMENT_HIDDEN属性。
另外值得一提的是,展望 2010 本身并不一致。我观察到,有时电子邮件列表会显示附件图标以指示附件的存在,但在检查器中打开它时没有出现任何内容。
参考:
某些附件始终具有 MIME 内容 ID ( PR_ATTACH_CONTENT_ID),特别是来自 Lotus Notes 的邮件始终具有该标题。
真正的测试是检查HTMLBody属性并查看 img 标签是否实际引用了任何附件。Redemption允许您使用RDOAttachment.Hidden属性来区分附件。
根据@Earth Engine 的回答,这里是一个函数,它在将mailitem (item.class = olMail) 作为参数传递时返回附件的实际数量:
Function CountVisibleAttachment(ByVal m As MailItem) As Integer
Const PR_ATTACH_CONTENT_ID As String = "http://schemas.microsoft.com/mapi/proptag/0x3712001F"
Const PR_ATTACHMENT_HIDDEN As String = "http://schemas.microsoft.com/mapi/proptag/0x7FFE000B"
Dim a As Attachment
Dim pa As propertyAccessor
Dim c As Integer
Dim cid As String
Dim body As String
c = 0
body = m.HTMLBody
For Each a In m.Attachments
Set pa = a.propertyAccessor
cid = pa.GetProperty(PR_ATTACH_CONTENT_ID)
If Len(cid) > 0 Then
If InStr(body, cid) Then
emb = emb + 1
Else
'In case that PR_ATTACHMENT_HIDDEN does not exists,
'an error will occur. We simply ignore this error and
'treat it as false.
On Error Resume Next
If Not pa.GetProperty(PR_ATTACHMENT_HIDDEN) Then
c = c + 1
End If
On Error GoTo 0
End If
Else
c = c + 1
End If
Next a
CountVisibleAttachment = c
End Function