【入門編】【中級者向け】送信ボタンをフックする:宛先が社外ドメインの場合に警告を出す安全対策 – Outlook VBA解析バイブル

スポンサーリンク

こんにちは!シニアアーキテクトの私です。
マクロの記録から一歩踏み出し、「実務で本当に使える自動化」を模索し始めたあなたへ。

ビジネスメールの誤送信、怖いですよね。「あ、社外の人に社内ニートの愚痴を送ってしまった…」「競合他社に見積書を誤爆した…」なんて想像するだけで冷や汗が出ます。

今回は、中級者へのステップアップとして、「送信ボタンを押された瞬間をOutlookに監視させ、社外アドレスが含まれていた場合に強制ストップをかける安全装置」の作り方を伝授します。

ここをクリアすれば、単なる「作業の自動化」から「リスクマネジメントのシステム構築」へと視座がグッと上がりますよ。さあ、一緒に極限の知見に触れていきましょう!

なぜ「送信ボタンのフック(ItemSend)」なのか?

多くの人がやりがちな失敗は、「メール作成画面にボタンを置いて、それを押したら送信する」という力技のマクロです。これだと、うっかり通常の「送信」ボタンを押されたときにスルーされてしまいます。

私たちが目指すべきは、ユーザーがどのルートで送信しようとも(ショートカットキーであっても)、Outlookが送信処理を行うまさにその瞬間(ItemSend)を捕らえて検問する仕組みです。

ライフサイクルを制する:`ThisOutlookSession` の秘密

通常の標準モジュール(Module1など)にマクロを書くだけでは、この「イベント」をキャッチできません。Outlook全体を監視するためには、`ThisOutlookSession` という特別なモジュールを使用します。

ここは、Outlookという巨大なアプリケーションの「心臓部」です。ここにコードを記述することで、メールの送信、受信、起動といったシステム全体のライフサイクルに割り込む(フックする)ことができるようになります。

実装コード:誤送信防止バリデーション

それでは、実際のコードを公開します。
以下のコードを、あなたのOutlookVBAエディタにある `ThisOutlookSession` にそのまま貼り付けてください。

Option Explicit

‘ =================================================================
‘ 概要: メール送信直前に宛先ドメインを走査し、社外アドレスへの
誤送信を検知してブロックするセキュリティバリデーション
‘ =================================================================
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)

On Error GoTo ErrorHandler

‘ 1. 対象がメールアイテムであるか厳密に判定(会議予定やタスクの誤作動を防ぐ)
If TypeName(Item) <> “MailItem” Then Exit Sub

Dim mail As Outlook.MailItem
Set mail = Item

‘ 2. 自社のドメイン定義(ここをご自身の環境に合わせて変更してください)
Const MY_DOMAIN As String = “your-company.co.jp”

Dim recipient As Outlook.Recipient
Dim recipientEmail As String
Dim externalCount As Long
Dim externalList As String
externalCount = 0
externalList = “”

‘ 3. 宛先(TO, CC, BCC)の全件スキャン
For Each recipient In mail.Recipients
‘ Exchangeの内部アドレス(EX)か、インターネットメール(SMTP)かを判別
recipientEmail = GetRecipientEmail(recipient)

‘ 自社ドメインが含まれていない、かつ空白でない場合を「社外」と判定
If recipientEmail <> “” Then
If InStr(1, recipientEmail, MY_DOMAIN, vbTextCompare) = 0 Then
externalCount = externalCount + 1
externalList = externalList & “・ ” & recipient.Name & ” (” & recipientEmail & “)” & vbCrLf
End If
End If
Next recipient

‘ 4. 社外宛先が存在する場合の警告とブロック処理
If externalCount > 0 Then
Dim msg As String
msg = “【警告】社外のアドレスが含まれています!” & vbCrLf & vbCrLf & _
“以下の ” & externalCount & ” 件の宛先は社外ドメインです。” & vbCrLf & _
externalList & vbCrLf & _
“本当にこのまま送信してもよろしいですか?”

‘ Yes/No の確認ダイアログを表示
If MsgBox(msg, vbExclamation + vbYesNo + vbDefaultButton2, “送信前セキュリティチェック”) = vbNo then
‘ Cancel = True にすることで、送信処理を完全にキャンセル(中断)する
Cancel = True
Exit Sub
End If
End If

Exit Sub

ErrorHandler:
‘ 予期せぬエラーで業務が止まらないためのフェイルセーフ
MsgBox “送信バリデーション実行中にエラーが発生しました。” & vbCrLf & Err.Description, vbCritical
Cancel = True
End Sub

‘ =================================================================
‘ 補助関数: Exchange環境特有のアドレス解決の闇を突破する
‘ =================================================================
Private Function GetRecipientEmail(ByVal recip As Outlook.Recipient) As String
On Error Resume Next
Dim addr As String
addr = “”

‘ 組織内のアドレス帳(GAL)経由の場合、そのままではSMTPアドレスが取れないためPropertyAccessorを使用
Const PR_SMTP_ADDRESS As String = “http://schemas.microsoft.com/mapi/proptag/0x39FE001E”

If Not recip.AddressEntry Is Nothing Then
If recip.AddressEntry.AddressCity = “EX” Or recip.AddressEntry.Type = “EX” Then
addr = recip.AddressEntry.PropertyAccessor.GetProperty(PR_SMTP_ADDRESS)
Else
addr = recip.Address.
End If
End If

GetRecipientEmail = addr
End Function

チーフアーキテクトが教える、コードの核心と「ハマりポイント」

初心者から一歩抜け出すために、このコードに隠された「プロの技術的こだわり」を解説します。

1. なぜ `TypeName(Item) “MailItem”` が必要なのか?

Outlookはメールだけでなく、「予定表(MeetingItem)」や「タスク(TaskItem)」も `ItemSend` の対象にします。もし予定表の送信時にこのマクロが走ると、宛先の構造が違うためにコードがクラッシュ(エラー停止)します。
「自分が処理できるオブジェクトの型を厳密に絞り込む」のは、バグを防ぐエンジニアの基本中の基本です。

2. Outlook最大の見えない罠:Exchange環境の「化け物アドレス」

社内メールでよくある `EX` タイプのアドレス(例: `/O=FIRST-ORG/OU=EXCHANGE…` というMAPI形式の文字列)。これのままだと `@your-company.co.jp` が含まれているか判定できません。
補助関数 `GetRecipientEmail` の中にある `PropertyAccessor` という機能は、「MAPIの深層から無理やり生のSMTPアドレス(メールアドレスの文字列)を引っぺがす」ための高度なテクニックです。ここを実装していないと、社内宛てなのに「社外だ!」と誤検知してしまいます。

3. `Cancel = True` の圧倒的なパワー

イベントプロシージャーの引数にある `ByRef Cancel As Boolean`。
ここに `True` を代入してプロシージャーを抜けると、Outlookは「送信動作そのものをなかったこと」にします。エラーを出して止まるのではなく、ユーザーが「あ、危ない!」と気づいて宛先を直せる猶予を与える、最高にエレガントな安全装置です。

導入手順とセキュリティ設定の注意点

1. Outlookを開き、`Alt + F11` キーを押してVBAエディタを起動します。
2. 左側のツリーから `Microsoft Outlook Objects``ThisOutlookSession` をダブルクリックします。
3. 上記のコードを貼り付け、`MY_DOMAIN` の部分をご自身の会社のドメインに書き換えます。
4. 【重要】 Outlookのマクロセキュリティ設定を「デジタル署名されたマクロのみ有効にする」または「すべてのマクロを有効にする(推奨しませんがテスト時はこれ)」に設定します。実務では自己署名証明書(SelfCert)を作成してコードに署名することを強くおすすめします。

まとめ:ここをクリアすれば、あなたはもう初心者ではない

いかがでしたでしょうか?
単に「動くコードを書く」だけでなく、「予期せぬエラーのハンドリング」「オブジェクトのライフサイクルの理解」「環境差異(Exchange)への対策」まで網羅したこのコードは、そのまま実際のビジネス現場で即戦力として機能します。

「送信ボタンを押す瞬間にシステムが介入して守ってくれる」――この手応えを感じられたなら、あなたのOutlook VBAのスキルは確実に中級者の領域に到達しています。

日々の業務を自動化するだけでなく、「ミスを防ぐ仕組み」を自分でデザインできるエンジニアになっていきましょう。次回の解説もお楽しみに!

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