配信確認通知メッセージなどの差出人の情報を取得するマクロ


コメントで以下のような質問をいただきました。


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

 

マクロの登録方法やメニューへの追加について

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中