Outlook オブジェクト モデルによりメールを送信しようとしても、送信トレイに滞留してしまう現象について

RPA や Excel マクロなどで Outlook オブジェクト モデルを使用して MailItem の Send メソッドによりメールを送信した際に、メールが送信されずに送信トレイに滞留したままの状態となる場合があります。
これは以下のような条件で発生します。

  • メールを送信する際に Outlook が起動していない
  • インターネット アカウントを使用しているか、Exchange アカウントでキャッシュ モードを有効にしている
  • Send メソッドで送信した後、すぐに Outlook のオブジェクトを開放している
  • メールサイズが大きかったり、一度に複数のメールを送信するなど、送信処理に時間がかかる状況である

上記の条件でメールが送信されない場合があるのは、Outlook の送信処理が以下のような順序で行われるためです。

  1. Send メソッドが実行されると、メールが送信トレイに保存され、送信のためのバックグラウンド タスクが起動される
  2. バックグラウンド タスクにより送信が実行される
  3. 送信が完了すると送信トレイのメールが送信済みアイテムに移動される

上記の 1. の処理が完了すると、それ以降の処理が行われる前に呼び出し元に制御が戻ります。
そして、呼び出し元のアプリケーションなどが直後に Outlook のオブジェクトを開放すると、Outlook 上では誰も Outlook を利用していない状態になります。
この状態になると、Outlook はバックグラウンド タスクが完了次第終了するのですが、何らかの理由でメール送信のタスクが起動していなかったり、複数のタスクの合間で実行中のタスクがない状況になると送信前のメールがあっても Outlook は終了します。
その結果、マクロなどでの送信が完了しても実際にはメールが送信されず、次に Outlook が起動されたタイミングで送信が行われるということになります。
これを回避するには、Outlook でメールの送信が完了したことを確認するまで、Outlook のオブジェクトを参照し続ける必要があります。
メールの送信が完了したかどうか判断する方法としては、送信トレイのアイテム数が 0 になるのを待つというものが考えられるでしょう。
appOlk という変数に Outlook.Application オブジェクトが格納されている場合に送信完了を待つ Excel VBA のサンプル コードは以下の通りです。
なお、サーバーやネットワークの問題などにより送信処理がいつまでも完了しない場合を考慮し、60 秒待っても送信トレイのアイテム数が 0 にならなければエラー表示するようにしています。

    Dim fldOutbox As Object
    Dim dtStart As Date
    Dim bAbort As Boolean
    Set fldOutbox = appOlk.Session.GetDefaultFolder(4) ' 4 = olFolderOutbox
    dtStart = Now
    bAbort = False
    While fldOutbox.Items.Count > 0 And Not bAbort
        ' Send メソッド実行から 60 秒以上経過していたら待つのをやめる
        If DateDiff("s", dtStart, Now) > 60 Then
            bAbort = True
        End If
        ' 送信トレイにアイテムが残っていたら 5 秒待つ
        Application.Wait (Now + TimeValue("00:00:05"))
    Wend
    '
    If bAbort Then
        MsgBox "送信処理が完了しませんでした。Outlook を起動して送信トレイを確認してください。"
    End If

Recipient と AddressEntry

Outlook オブジェクト モデルには、受信者のプロパティを取得するために Recipient というオブジェクトがあり、これによりメールアドレスや表示名が取得可能です。
一方、Recipient の AddressEntry プロパティとして取得可能な AddressEntry オブジェクトでも、同様にメールアドレスや表示名が取得可能となっています。
今回はこの二つのオブジェクトの違いについて説明します。

Recipient オブジェクトは、その名の通りメールアイテムに設定されている受信者の情報を取得するものです。
そのため、このオブジェクトから取得可能な情報はメールアイテムに含まれている情報に限られます。

一方、AddressEntry オブジェクトはアドレス帳のエントリに対応するもので、アドレス帳から情報を取得します。
これにより、Exchange 環境においては、受信者の名前やアドレスだけでなく、会社名や所属部署などの詳細な情報を取得することが可能です。

したがって、単にメールアドレスや表示名などメールに含まれる情報だけを取得するのであれば Recipient のプロパティで十分ですが、アドレス帳から情報を取得する必要があるなら AddressEntry を使用すことになります。
ただ、Exchange キャッシュ モードがオフの場合、AddressEntry でプロパティを取得すると時間がかかる場合があり、例えば宛先に 100 人追加されているメールアイテムの受信者の情報を AddressEntry で取得しようとすると環境によっては数分かかることもあります。
そのため、こちらのオブジェクトの使用には注意が必要です。

また、Outlook の連絡先アドレス帳から設定したあて先の AddressEntry では、Exchange のように連絡先の会社名や所属部署などの情報を取得することはできません。
連絡先アドレス帳に対応する連絡先の情報を取得するには、AddressEntry の GetContact メソッドにより対応する ContactItem を取得し、そのアイテムから必要な情報にアクセスします。

2023 年 10 月 10 日に Office 2016/2019 の Microsoft 365 への接続サポートが終了

Office 2016/2019 の Microsoft 365 への接続サポートの終了まで、あと約 1 カ月となりました。
では、サポートが終了するとどのようなことが発生するのでしょうか?

結論から言えば、「何が起こるかわからない」です。

マイクロソフトの Microsoft 365 サービスへの接続についての公開情報では、「古いバージョンの Office が Microsoft 365 サービスに接続するのをブロックするためのアクティブな対策は講じられません。」とあるので、2023 年 10 月 10 日になった途端に接続ができなくなるということはなさそうです。
しかし、サポートしないということはそのバージョンでの接続が事前に確認されないということなので、サービス側の何らかの変更で以下のような予期しない動作をする可能性があります。

  • サーバーの応答を解釈できずエラーで失敗する
  • サーバーから受信したデータが原因でクラッシュやハングが発生する
  • 不必要なエラー リトライが繰り返されクライアントのパフォーマンス低下やネットワークトラフィックの増大が発生する
  • Web アドインが動作しなくなる
  • 認証が失敗して接続ができなくなる

このうち、個人的に一番発生する可能性が高いと思われるのが、「認証が失敗して接続ができなくなる」です。
Office 2016 では認証に ADAL というライブラリが使用されますが、このライブラリでは Web ページを使用した認証に Internet Explorer のコンポーネントが使用されます。
しかし、Microsoft 365 や Azure などではすでに Internet Explorer のサポートは終了しており、いつ Internet Explorer で動作しない JavaScript の構文やメソッドが使用されるようになるかがわかりません。

実際、過去には Internet Explorer で使用できないメソッドが認証のページで使用されることにより、Outlook 2016 からの接続ができなくなるという障害も発生しています。
その際にはサービス側の修正が行われましたが、サポート終了後には同様の修正が行われる保証がありません。
そのため、ある日突然認証ができずに接続できなくなるというリスクがあるということです。
そうなってから慌てて Microsoft 365 Apps へのアップデートをするとなると、多数の端末から一斉にインストールを行うことになるので、ネットワーク トラフィックが飽和するといった二次災害も発生しかねません。

したがって、できる限りサポート終了前に Microsoft 365 Apps へのアップデートを済ませたほうが良いと考えられます。
間に合わないなら、とりあえず Outlook on the Web (Web 版の Outlook) を使用できるようにしておき、何か問題が発生したら Outlook on the Web を使うということを社内で周知しておく必要があるでしょう。

予定表で本文の一部が表示される

Outlook の既定の予定表の表示では、予定の件名と場所だけが表示されます。
しかし、何かの拍子に本文の一部まで表示されるようになってしまうことがあります。
この現象は、予定表のビューとして「プレビュー」もしくはこのビューをもとにして作成したビューを使用すると発生します。
タネを明かせば特に問題のない正常な動作なのですが、ビューの設定などを見ても本文の表示・非表示の切り替えを行うようなところはないのが厄介なところです。
通常表示されない本文が表示されることで、意図しない情報が公開されてしまっていると誤解される方もいるのですが、あくまでも本文が参照できる権限がない限りは「プレビュー」というビューを使用しても本文が表示されることはないのでご安心ください。

メールを確実に指定分数以上遅延して送信するマクロ

Outlook では送信ルールに「指定した時間分後に配信する」という処理があります。
これを使用すると、送信直後に誤りに気付いたような場合に、指定した時間以内であれば送信を取り消して修正を行うことが可能になります。
誤送信の防止に便利な機能なのですが、一つ落とし穴があります。
それは、すでに配信時刻が設定済みのメールについてはルールが適用されないというものです。
これは、ユーザーが遅い時間に配信時刻を設定して送信した際にルールで上書きされてしまうことを防ぐための動作ですが、これにより以下のような状況が発生します。
(5 分後に配信すると設定していた場合)

  1. ユーザーが配信時刻を設定せずに送信する
  2. ルールにより配信時刻が 5 分後に設定され、送信トレイにメールが滞留する
  3. ユーザーが配信時刻の前に送信トレイのメールを開き、変更を加えて再度送信する
  4. ルールによる配信時刻の設定がされないため、2 で設定した時刻に送信される

残念ながらルールで配信する時に配信時刻を上書きするような設定はないので、再送の際には [配信タイミング] をクリックして [指定日時以降に配信] をオフにしてから送信する必要があります。

これはちょっと面倒なので、ルールの代わりに配信時刻を設定するマクロを作成しました。
このマクロでは配信時刻が設定されているメールでも、指定した時間より前に送信されるようであれば配信時刻を設定しなおす動作となっています。

'
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
     Const DEFER_TIME = 5 ' 遅延分数
     Dim dtSend As Date
     On Error Resume Next
     ' 遅延送信時間を算出
     dtSend = DateAdd("n", DEFER_TIME, Now)
     ' 配信日時が未設定か、遅延送信時間より前なら
     If Item.DeferredDeliveryTime = "4501/01/01" Or _
        Item.DeferredDeliveryTime < dtSend Then
         ' 遅延送信時間を設定
         Item.DeferredDeliveryTime = dtSend
     End If
End Sub

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

MFCMAPI とは

Microsoft のサポートページなどで、Outlook のトラブルシュートに MFCMAPI というツールが使用される場合があります。
公式ページで紹介されるようなツールなのですが、なぜか Microsoft のダウンロードページではなく、Github からダウンロードするようになっています。
では、このツールはいったいどのようなものなのでしょうか?

もともと、MFCMAPI とは「Microsoft Foundation Class (MFC) で MAPI を操作するアプリのサンプル」という位置づけで、Inside MAPI という書籍や Microsoft の SDK などに含まれていたものでした。
しかし、サンプルとして様々な MAPI の関数を直接呼び出すことが可能なことから、Outlook 自体では操作できないような MAPI オブジェクトの操作ができるため、サポートなどでトラブルシュートに使われるようになっていきました。

そして、Microsoft の Stephen Griffin 氏が単なるサンプルとしてではなく、より使いやすくなるような様々な機能を追加し、現在のような MFCMAPI がオープン ソースのプロジェクトとして Github で公開されています。

このように、MFCMAPI は公式なツールとは言い難いですが、Microsoft のサポートでも使用される便利で強力なものです。
MFCMAPI でできることを端的に表すと、以下のようなシンプルなものになります。

  • アイテムやフォルダーのプロパティの追加、変更、削除
  • Outlook で表示されないアイテムやフォルダーの表示

しかし、これを応用することで以下のような様々な処理が可能となります。

  • 破損したプロパティやアイテムを削除して Outlook が起動できるようにする
  • 文字化けしたメッセージのバイナリデータを確認し、適切な文字コードを設定して文字化けを直す
  • 想定外のサイズになっているアイテムやフォルダーのデータを確認し、肥大化の原因を特定する
  • キャッシュモードでログインできなくなったメールボックスを修復する
  • 代理人設定ができなくなったメールボックスを修復する

ただ、このツールは強力である一方、不用意にプロパティなどを変更・削除すると Outlook の動作に支障をきたす場合があるので、慎重に使用する必要があるでしょう。

Outlook と Microsoft Edge WebView2

以下のページで公開されている通り、Microsoft 365 Apps をインストールすると Microsoft Edge WebView2 というコンポーネントも既定でインストールされます。

Microsoft Edge WebView2 と Microsoft 365 Apps – Deploy Office | Microsoft Learn

ただし、あくまでも「既定」であり、このコンポーネントをインストールさせないということもできます。
実際、セキュリティが強化されている環境では、WebView2 がインストールされない場合もあるようです。

しかし、Version 2101 以降の Microsoft 365 Apps は WebView2 がインストールされていることが前提であり、これがないと様々な制限が発生する可能性があります。

そして、より問題なのは、WebView2 が使えない場合には代わりに Internet Explorer のコンポーネントである MSHTML が使用されるという点です。
WebView2 も MSHTML も、ブラウザの表示機能をアプリで実装するために使用されるコンポーネントです。
以前、Outlook と Internet Explorer という記事で説明した通り、Outlook は Web ページの表示に MSHTML を使用していましたが、Internet Explorer のサポートの終了もあり、WebView2 を使用するように更新されています。
しかし、WebView2 のインストールをブロックしてしまうと、WebView2 の代わりに MSHTML が使用され続けます。
つまり、サポートが終了している製品のコンポーネントがいつまでも使用されているということになります。
(MSHTML 自体はサポートは終了していないようですが。)
そのため、Web 表示を必要とする機能 (Web アドインやアクション可能なメッセージなど) で表示が正しくできなかったり、最悪の場合はクラッシュなどを引き起こす可能性があります。
実際に、WebView2 がない環境で Teams や Yammer、Viva などの通知に使用されるアクション可能なメッセージを開く際にクラッシュする場合があるという事例が確認されています。

WebView2 のインストールをブロックする背景としては、不要なソフトのインストールを行いたくないというものがあると思われます。
ただ、WebView2 は Office 製品にとって必要な機能であり、これをブロックすることでセキュリティに悪評がある Internet Explorer のコンポーネントを使用し続けるというリスクがあることを認識していただく必要があるでしょう。

Outlook の定期的な予定アイテムの仕組み

Outlook には定期的な予定というものがあります。
これは、例えば毎週月曜日の 10 時から 11 時までの会議というものを、繰り返しのパターンを定義することで作成するというものです。
このようなアイテムについては、繰り返す数だけアイテムが作成される、というわけではありません。
実際に作成されるアイテムは一つだけであり (これをマスター アイテムと呼びます)、そのアイテムに繰り返しパターンが保存されているため、Outlook の予定表ビューではそれが展開されて表示されるという仕組みになっています。

では、定期的な予定のうち、一つだけ時間や本文を変更した場合はどうなるのでしょうか?
この場合もアイテムの数は増えず、変更した日の情報がマスター アイテムに保存されるということになります。
具体的には、PidLidAppointmentRecur というプロパティに例外アイテムの概要が保存され、本文や例外のみに追加した添付ファイルなどはマスター アイテムの添付アイテムとして保存されます。
そのため、定期的な予定に毎回変更を加えるというような運用をすると、マスター アイテムの添付がどんどん増えていき、その繰り返しのアイテムを表示するのに時間がかかるだけでなく、通常の予定表表示も遅くなることがあります。
さらに、例外が多くなりすぎるとアイテムの破損が生じる可能性もあります。

したがって、定期的なアイテムの個々の回についてはなるべく変更は加えず、例えば議事録を保存したいというような場合は予定アイテム自体ではなく予定アイテムから OneNote にリンクを貼り、OneNote で管理するというような運用を行うとよいでしょう。

Outlook と Internet Explorer

Internet Explorer は 2022 年 6 月 15 日にサポートが終了されました。
これにより、Internet Explorer では動作しないという Web サイトが出てきています。

一方、バージョンにもよりますが、Outlook は以下のような機能で Internet Explorer を Web ページの表示に使用しています。

  • Outlook Today およびフォルダー ホームページ (すべてのバージョン)
  • 先進認証 (Outlook 2016 MSI)
  • Web アドイン (Outlook 2016 MSI、Office 2019 ボリューム ライセンス版)

そのため、上記の機能でアクセスされる Web サイトが Internet Explorer で対応していない JavaScript の機能を使ったり、明示的に Internet Explorer をブロックしているような場合、正常に機能しなくなります。
例えば、先進認証で使用しているサードパーティの認証サイトが Internet Explorer をブロックした場合、先進認証が使用できなくなり、Exchange サーバーへの接続に失敗するというようなことが発生します。

残念ながら、上記の機能で Internet Explorer ではなく他の Web ブラウザを使用させる設定は不可能なので、回避策としては Web サイトを Internet Explorer に対応させるか、Internet Explorer を使用しないバージョンにアップグレードするかのいずれかになります。

問題は、Outlook Today については最新のバージョンでも Internet Explorer を使うということですが、この機能で他の Web ブラウザを使用するようになる予定はなさそうなので、どうしても Outlook Today やフォルダー ホームページが使いたければ、Web サイトで対応する以外にはないでしょう。

スタート メニューの Outlook のショートカットを別のフォルダーに移動しても、元の位置にショートカットが作成される現象について

Office 製品をインストールすると、スタート メニューにそれぞれのプログラムへのショートカットが作成されますが、何らかの理由でこれを別のフォルダーに移動したいということがあるかもしれません。
しかし、Outlook のショートカットを移動すると、Outlook の起動時に元の場所にショートカットが復元される動作となります。
これは、不具合ではなく Outlook のデスクトップ通知を行うために必要な処理です。

Windows 8 以降の Windows では Outlook のデスクトップ通知が Windows の通知領域で行われるようになりました。
そして、Windows の通知機能では、通知を行うアプリケーションのショートカットがスタート メニューにない場合に通知が行われないという仕様があります。
このような仕様があるため、スタート メニューに Outlook のショートカットがなかった場合に、自動的にショートカットを作成します。
この動作を抑止する方法はないので、Outlook のショートカットは既定のまま放置しておくほうが良いでしょう。

参考リンク:

スタートメニューのショートカットが見つからない場合は通知なし – Outlook | Microsoft Learn
Toast notification overview (Windows Runtime apps) – Windows app development | Microsoft Learn