コメントで以下のような質問をいただきました。
Outlook2003で開封確認メッセージをありにしてメール送信し、返信された開封確認メールを次のVBAで受け取って内容をファイルに保存したいのですが、
Set myMsg = Application.Session.GetItemFromID(i)
の行で「型が不一致」になってしまいます。通常の受信メールはうまく受け取れます。
…略…
Dim myMsg As Object
に変更するとこの行は通りますが、myMsg.SenderNameやmyMsg.SenderEmailAddressが存在しないプロパティとなってしまいます。この方法では開封確認メールは受け取れないのでしょうか?
開封確認通知や配信確認通知のようなメッセージは、MailItem ではなく ReportItem というクラスのオブジェクトになります。これは、Outlook がこれらのメッセージについては通常のメッセージと異なる処理をが行うためです。
そして、ReportItem に関しては SenderName や SenderEmailAddress というプロパティがないため、このままでは差出人の情報は取得できません。しかし、メッセージのデータとしては存在します。Outlook 2007 では PropertyAccessor によりこれらの情報を取得することが可能なのですが、Outlook 2003 の Outlook Object Model では MAPI プロパティに直接アクセスする方法がないため、ちょっとした工夫が必要となります。
それは、MessageClass を “IPM.Note” にするというものです。MessageClass というプロパティはそのアイテムの種類をあらわすもので、通常のメッセージは “IPM.Note”、開封確認通知は “REPORT.IPM.Note.IPNRN”、配信確認通知は “REPORT.IPM.Note.DR” となっています。そして、このプロパティを変更することにより、アイテムの種類を変更することが可能です。したがって、配信確認通知だった場合には MessageClass を “IPM.Note” に変更することで、差出人の情報を取得することができるようになります。ただし、MessageClass を変更しても、ReportItem のオブジェクトが直ちに MailItem になるわけではないため、改めて EntryID を指定してメッセージのオブジェクトを取得する必要があります。
また、ReportItem の Body プロパティは実際の通知メッセージの本文ではなく、通知メッセージに含まれるプロパティなどによって動的に作成されるものであるため、通常のメッセージにしてしまうと Body が空になってしまいます。そこで、Body については “IPM.Note” を設定する前にあらかじめ取得しておき、”IPM.Note” に変更後に改めて Body に設定しなおす必要があります。
さらに、MessageClass を変更後、そのままにしてしまうと、Outlook が行なうはずの確認通知メッセージに対する処理が実行されなくなり、送信済みアイテムの [確認] タブで通知状態が追跡できなくなってしまいます。そのため、必要なプロパティの取得が終わったら、元の MessageClass に戻すという処理も必要です。
これらを踏まえて、コメントでいただいたソースコードを修正したものが以下の通りになります。
' ここをトリプルクリックでマクロ全体を選択できます。
'
Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
Dim myMsg As Object
Dim i As Integer
Dim arrEntryId As Variant
Dim bDelete As Boolean
Dim fdes As Integer
Dim strOrgMsgClass As String
Dim strBody As String
'
arrEntryId = Split(EntryIDCollection, ",")
For i = 0 To UBound(arrEntryId)
Set myMsg = Session.GetItemFromID(arrEntryId(i))
' アイテムが通知メッセージだったら
If TypeName(myMsg) = "ReportItem" Then
' 元のメッセージ クラスを退避
strOrgMsgClass = myMsg.MessageClass
' 元の本文を退避
strBody = myMsg.Body
' メッセージ クラスを "IPM.Note" に変更
myMsg.MessageClass = "IPM.Note"
myMsg.Save
' メッセージ クラスを変更したアイテムを取得しなおし
Set myMsg = Session.GetItemFromID(myMsg.EntryID)
' 退避した本文を取得したアイテムに設定
myMsg.Body = strBody
Else
strOrgMsgClass = ""
End If
fdes = FreeFile()
Open "c:\temp\受信メール_" & Format(Now, "YYYYMMDD_HHNNSS") & ".txt" For Output As #fdes
Write #fdes, myMsg.Subject
Write #fdes, myMsg.CreationTime
Write #fdes, myMsg.SenderName
Write #fdes, myMsg.SenderEmailAddress
Write #fdes, myMsg.Body
Close #fdes
If strOrgMsgClass <> "" Then
' 退避されたメッセージ クラスの文字列があるなら、メッセージ クラスを元に戻す
myMsg.MessageClass = strOrgMsgClass
myMsg.Save
End If
Next
End Sub
マクロの登録方法やメニューへの追加について