ExcelのVBAによるOutlookメール自動送信はセキュリティに止められる場合がある。メール送信をOutlookのVBAで実行すれば、セキュリティの設定変更をせずに済む。
事象
ExcelのVBAを使ってOutlookにメール送信させようとすると、下図の警告が出て、いちいち「許可」を求められる。つまり自動化できない、ということ。
画像だけでなく文章でも書いておきます。
プログラムによって電子メールメッセージが送信されようとしています。これが予期しない動作である場合は[拒否]をクリックして、ウイルス対策ソフトウェアが最新の状態であることを確認してください。
解決方法
メール送信部分はOutlookのVBAにやらせる。
私の環境
Webスクレイピングしたデータを、定時にOutlookからメール送信させるExcelVBAを組んでいて、Office2016(32ビット)では問題なく稼働していましたが、Microsoft365(32ビット)に乗り換えたら前述の警告が出るようになりました。新旧ともにExchangeServerで、OSはWindows10(64ビット)です。
ネットで見つかる解決策
原因
この警告メッセージは、プログラムが Outlook クライアントにアクセスしてユーザーに代わって電子メール メッセージを送信しようとしたときに表示され、ウイルス対策ソフトウェアが非アクティブまたは古くなっていることが検出されました。
https://learn.microsoft.com/ja-jp/outlook/troubleshoot/security/a-program-is-trying-to-send-an-email-message-on-your-behalf
で、上記サイトで言われたとおり、Outlookのセキュリティセンター(トラストセンター)で「ウイルス対策ソフトウェアの状態」を確認すると「有効」になっていた。
その上段の「プログラムによるアクセスのセキュリティ」は管理者によりグレーアウトされていたが、挙動から言って「不審な動作に関する警告を常に表示する」だろう。引用先サイトによると、なんとかしたければレジストリを弄れだとさ。え~
糸口
レジストリを弄るのはなんか怖くて無理なので試行錯誤することに。
すると、ExcelVBAの「.send」を「.save」に書き換えると警告に邪魔されず動くことを発見。つまり、メールを送信せずにOutlookの「下書き」に送り込むことは可能ということ。
Outlook標準機能の模索
「送信トレイ」に送り込むこともできたので、Outlookの送受信の実行周期を設定すれば勝ちか、と思ったら送信されない。送信トレイでのメールの「送信日時」が「なし」になっているから?昔、別件でこの問題に出くわして解決できなかったので、この作戦はあまり深入りしないことにした。
仕分けルールで、下書きフォルダのメールを送信トレイに移すと「送信日時」に日時が入るが、それでも送信されない。ExcelVBAが送り込んだメールは何かが違うんでしょうかね。
仕分けルールで、特定の件名とかの条件でメール送信できるけど、仕分けルールを定時に自動実行する方法が見つからなかったので私の目的としてはアウト。
ExcelVBAでのメール作成時に「配信タイミング」も指定できるけど、これでも送信されず。
以上によりOutlookの標準機能でメール送信するのは諦めました。
OutlookVBA
OutlookVBAに堪能な方ならもう勝ち確でしょうが私は初学。いろいろ罠がありましたので、それも記録しておきます。
(罠1)唐突にマクロを禁じられる。
Outlookのリボン設定で「開発」にチェックを入れればコードを書く準備は完了。ネットで拾ったサンプルコードをコピペすれば、お~動く動く。
…と思ったのも束の間、突然、下の画像のとおり「このプロジェクトのマクロは無効に設定されています」と来た。その直前に何か別のダイアログが出たような気がするが見落とした。
この対策には証明書の設定が要ります。その名もズバリselfcert.exeを使えばサクッと証明書を作成できます。このselfcert.exeは環境によって格納場所が違うそうなので要検索。
selfcert.exeを実行し、任意の名前で証明書を作成する。どこに保存されたのかわからんが、VBEのツール>デジタル証明書 で先ほど命名した証明書が出てくる。
(罠2)証明書が定着?しない
証明書を設定したのに相変わらず「このプロジェクトのマクロは…」が出る。Outlookを再起動すると証明書が「なし」になってる!
証明書を設定し直して、VBEで上書き保存して、Outlookを閉じるときに出るダイアログでも保存を実行しても、再起動したら証明書が「なし」になる。
何度も上書きと再起動を繰り返していると以下のダイアログが出て、「この発行者のドキュメントをすべて信頼する」を選択すると、やっと証明書が「なし」にならなくなった。なんだこれ。
(罠3)連続的?な.sendは阻止される。
ExcelVBAでOutlookの下書きなどに送り込んだメールを、OutlookVBAでどう指定して送信するのか。他のメールが紛れる恐れがないなら、フォルダ内の全メールを送ってしまうのもアリ、というかまずはそれしか思い浮かばなかった。
しかし、特定のフォルダ内の全メールに対し、For Eachで.sendしようとすると、冒頭の警告が出て阻止される。あまりハデにやるとバレるということか。
下書きに送り込んだとして、For Eachを封じられているので、送り込んだそのメールを特定しなければならない。これが私には地味に難しかった。
で、結局
私はExcelVBAから、引数を渡しつつOutlookのマクロを起動するようにしました。それを定時に実行させます。宛先は常に同じなので、送りたいデータを引数として渡してメール本文としました。
OutlookVBAに引数を渡すところは、拾ってきたサンプルコードをワケもわからず使っているだけです。解説できません(苦笑)。
まとめ
ExcelVBAなら止められるメール送信の自動化も、OutlookVBAなら実行可能というお話でした。これがMicrosoftの意図した挙動なのかわかりませんが。お役に立てば幸いです。