【入門編】【中級者向け】受信メールのヘッダー情報を解析し、SPF/DKIM認証失敗メールを自動で隔離フォルダへ移動するセキュリティツール – Outlook VBA解析バイブル

スポンサーリンク
スポンサーリンク

【極限の知見】Outlook VBAで守る、あなたの受信トレイ:ヘッダー解析によるSPF/DKIM認証失敗メールの自動隔離術

こんにちは。自動化の深淵へようこそ。

「マクロの記録」ボタンを押して、記録されたコードを眺めて「ふむふむ、これで動くんだな」……。もしあなたが今、そんな段階にいるとしたら、おめでとうございます。あなたは自動化の第一歩を踏み出しました。

しかし、プロの世界、つまり「業務を劇的に変えるエンジニア」の領域へ足を踏み入れるには、もう一段階上の視点が必要です。マクロの記録は「表面的な操作」しか記録しません。しかし、真に強力なツールは、メールの表面(件名や本文)ではなく、メールの「背後にある真実(ヘッダー情報)」を読み解くことで完成します。

今日は、中級者への登竜門として、「メールのヘッダー情報を解析し、SPFやDKIMといった認証に失敗した『怪しいメール』を自動で隔離する」という、実戦的なセキュリティツールの構築方法を伝授します。

ここをクリアすれば、あなたは「操作を記録する人」から、「ロジックを設計する人」へと進化できるはずですよ。

1. なぜ「ヘッダー」を見る必要があるのか?

メールには、目に見える「本文」のほかに、目に見えない「ヘッダー」という情報層があります。これは例えるなら、メールの「パスポート」です。

誰が送り、どのサーバーを経由し、その送信者は本当に本人なのか? その答えはすべてヘッダーに刻まれています。

特に重要なのが以下の2つです。

  • SPF (Sender Policy Framework): 送信元サーバーが、そのドメインを名乗る許可を得ているか?
  • DKIM (DomainKeys Identified Mail): メールの内容が途中で改ざんされていないか?(電子署名)

一般的な迷惑メールフィルタもこれらを見ていますが、組織のポリシーとして「認証失敗(fail)したものは、即座に隔離フォルダへ隔離し、人間が確認する」というフローを作ることができれば、セキュリティ強度は飛躍的に高まります。

2. 武器を揃える:PropertyAccessor と 正規表現

このツールを作るために、私たちは2つの強力な武器を使いこなします。

① PropertyAccessor(プロパティ・アクセサ)

Outlookの標準的なオブジェクトモデル(`MailItem.Subject` など)では、ヘッダーの深層部にはアクセスできません。そこで使うのが `PropertyAccessor` です。これは、MAPI(Microsoftのメール管理プロトコル)の隠れたプロパティに直接アクセスするための「裏口」のようなものです。

② 正規表現 (RegExp)

ヘッダーは膨大な文字列の塊です。その中から「`spf=fail`」や「`dkim=fail`」という特定のパターンを見つけ出すには、正規表現という高度な文字列検索技術が不可欠です。

3. 実装:セキュリティ・ガード・マクロ

それでは、魂を込めたコードを見ていきましょう。このコードは、新しいメールを受信した瞬間に発動する `NewMailEx` イベントを利用します。

【準備】
1. OutlookのVBAエディタを開きます(`Alt + F11`)。
2. 左側のツリーから `Project1` > `Microsoft Outlook Objects` > `ThisOutlookSession` をダブルクリックします。
3. 以下のコードを貼り付けてください。

' =================================================================
' セキュリティ・ガード・マクロ
' 機能:受信メールのヘッダーを解析し、SPF/DKIM認証失敗を検知して隔離する
' =================================================================

Option Explicit

' MAPIプロパティの定数(ヘッダー情報を取得するための魔法のID)
Private Const PR_INTERNET_MESSAGE_HEADERS As String = "http://schemas.microsoft.com/mapi/proptag/0x007D001E"

''' <summary>
''' 新しいメールを受信したときに自動実行されるイベント
''' </summary>
''' <param name="EntryID">受信したアイテムの一意識別子</param>
Private Sub Application_NewMailEx(ByVal EntryID As String)
    Dim olItem As Outlook.MailItem
    Dim isSuspicious As Boolean
    
    On Error GoTo ErrorHandler

    ' 1. EntryIDからメールオブジェクトを取得
    ' ※ NewMailExはオブジェクトではなくIDを渡すため、GetItemFromIDを使うのがプロの作法です
    Set olItem = Application.Session.GetItemFromID(EntryID)
    
    ' メール以外のアイテム(会議出席依頼など)は無視する
    If olItem.Class <> olMail <> olMail Then Exit Sub

    ' 2. セキュリティチェックの実行
    isSuspicious = CheckEmailSecurity(olItem)

    ' 3. 判定結果に基づいたアクション
    If isSuspicious Then
        Debug.Print "【警告】認証失敗メールを検知: " & olItem.Subject
        MoveToIsolationFolder olItem
    End If

    Exit Sub

ErrorHandler:
    Debug.Print "Error in Application_NewMailEx: " & Err.Description
End Sub

''' <summary>
''' ヘッダー情報を解析して、SPF/DKIMの失敗を判定する
''' </summary>
Private Function CheckEmailSecurity(ByRef mailItem As Outlook.MailItem) As Boolean
    Dim headerText As String
    Dim regEx As Object
    Dim matches As Object
    
    ' 初期値は「安全」
    CheckEmailSecurity = False
    
    ' PropertyAccessorを使用してヘッダー文字列を丸ごと取得
    On Error Resume Next
    headerText = mailItem.PropertyAccessor.GetProperty(PR_INTERNET_MESSAGE_HEADERS)
    On Error GoTo 0
    
    If headerText = "" Then Exit Function

    ' 正規表現オブジェクトの生成 (VBScript.RegExp)
    Set regEx = CreateObject("VBScript.RegExp")
    With regEx
        .IgnoreCase = True
        .Global = True
        ' 検索パターン:spf=fail または dkim=fail を探す
        ' ※ 実際のヘッダー形式に合わせて調整が必要な場合があります
        .Pattern = "(spf|dkim)=fail"
    End With

    ' パターンに一致するか判定
    If regEx.Test(headerText) Then
        CheckEmailSecurity = True
    End If
End Function

''' <summary>
''' 指定したメールを「隔離フォルダ」へ移動する
''' </summary>
Private Sub MoveToIsolationFolder(ByRef mailItem As Outlook.MailItem)
    Dim targetFolder As Outlook.Folder
    Dim ns As Outlook.NameSpace
    Const TARGET_FOLDER_NAME As String = "隔離フォルダ" ' ← ここに作成したフォルダ名を指定

    Set ns = Application.GetNamespace("MAPI")
    
    ' 受信トレイの下に「隔離フォルダ」があるか探す
    On Error Resume Next
    Set targetFolder = ns.GetDefaultFolder(olFolderInbox).Folders(TARGET_FOLDER_NAME)
    On Error GoTo 0

    ' フォルダが存在しない場合は、エラーを防ぐために処理を中断
    If targetFolder Is Nothing Then
        MsgBox "エラー: '" & TARGET_FOLDER_NAME & "' が見つかりません。作成してください。", vbCritical
        Exit Sub
    End If

    ' 移動実行
    mailItem.Move targetFolder
End Sub

4. エンジニアの視点:ここが「プロ」の分かれ目

このコードを単にコピーして動かすだけでは、あなたはまだ「初級者」です。このコードの背後にある設計思想を理解してください。

なぜ `NewMailEx` を使うのか?

多くの初心者は `ItemAdd` イベントを使おうとします。しかし、`ItemAdd` は「フォルダにアイテムが増えたこと」を検知するものですが、`NewMailEx` は「メールが届いた瞬間」に、そのアイテムの `EntryID` を直接渡してくれます。
これにより、大量のメールが届いた際でも、どのメールを処理すべきかが明確になり、パフォーマンス低下を防ぐことができます。

エラーハンドリングの重要性

`PropertyAccessor` は、メールの種類によってはエラーを吐くことがあります(ヘッダーが存在しない場合など)。そこで、`On Error Resume Next` を局所的に使い、プログラム全体がクラッシュしてOutlookが止まってしまうのを防いでいます。「止まらないツール」こそが、最高のツールです。

正規表現の柔軟性

`.Pattern = “(spf|dkim)=fail”` という部分は非常に強力です。これにより、「SPFが失敗している」または「DKIMが失敗している」という2つの条件を、たった一行のロジックで判定しています。

5. 陥りやすいエラーと対策

実装時に、以下の壁にぶつかるかもしれません。

1. 「隔離フォルダが見つかりません」エラー

  • 原因: コード内の `TARGET_FOLDER_NAME` と、実際にOutlookで作ったフォルダ名が一致していません。
  • 対策: フォルダ名を正確に(全角・半角まで)一致させてください。

2. マクロが動かない

  • 原因: Outlookのセキュリティ設定で「マクロが無効」になっている可能性があります。
  • 対策: `ファイル > オプション > トラストセンター > トラストセンターの設定 > マクロの設定` から、開発用の設定に変更してください。

3. 誤判定(False Positive)

  • 原因: 正規表現のパターンが広すぎると、安全なメールまで隔離してしまいます。
  • 対策: 実運用では、まずは `Move` せずに `Debug.Print` でログを出すだけの「テストモード」で運用し、判定精度を確認するのが鉄則です。

最後に

いかがでしたか?
「マクロの記録」という魔法の杖を卒業し、プロパティを直接操作し、正規表現でデータを裁く。この感覚を掴めば、Outlook VBAはあなたの最強の武器になります。

自動化の道は奥が深いですが、一つ一つのロジックを「なぜこう書くのか?」と問いながら進んでいけば、必ず景色が変わります。

さあ、次はどんな仕組みを構築しましょうか? 挑戦を楽しんでください!

タイトルとURLをコピーしました