【入門編】Outlookの「アイテム」の送信日時と受信日時の差異を理解した正確なログ記録 – Outlook VBA解析バイブル

スポンサーリンク

こんにちは!Outlook VBAの automaty化の世界へようこそ。
マクロの記録機能がないOutlookの世界では、最初の一歩を踏み出すのに少し勇気が要りますよね。でも、大丈夫です。ここをクリアすれば、あなたのOutlook VBAの基本はバッチリですよ。

今回は、現場でシステム連携やログ記録ツールを作るときに必ずと言っていいほど直面する「日付の罠」について、プロの視点から優しく、そして深く解説していきます。

1. なぜ「送信日時」と「受信日時」でハマるのか?

Outlookでメールを扱うとき、私たちは何気なく「日付」を見ていますよね。しかし、プログラム(VBA)の世界からメールオブジェクトを覗き見ると、日付を表すプロパティには主に次の2つが存在します。

  • `SentOn` プロパティ:送信日時(そのメールが「送信者によって発信された」時刻)
  • `ReceivedTime` プロパティ:受信日時(そのメールが「あなたのメールボックスに到着した」時刻)

「あれ? 自分宛てのメールなんだから、同じじゃないの?」と思いますよね。
ここに、業務システム連携やログ管理における最大の落とし穴があります。

【図解】メールがたどるタイムラグとプロパティの正体

[送信者] ──(メール作成・送信)──> 【 SentOn 】 (送信完了のタイムスタンプ)

(ネットワーク遅延・サーバー滞留)

[あなた] <──(メールボックスに到着)── 【 ReceivedTime 】 (受信完了のタイムスタンプ) さらに話がややこしくなるのは、「自分が送信したメール(送信済みアイテム)」を扱うときです。

  • `SentOn` = あなたが送信ボタンを押した日時。入ります。
  • `ReceivedTime` = なんと、値が入りません(空 / Empty)!

そう、自分が送ったメールには「受信」という概念がないため、`ReceivedTime` をそのままデータベースに書き込もうとすると、「型が一致しません」というエラー(Runtime Error 13)でマクロが轟沈してしまうのです。

2. 現場で使える!正確なログ記録の設計思想

データベースやCSVにメールのログを綺麗に残すためには、次の原則を頭に叩き込んでおく必要があります。

1. 「受信トレイ」のメールを処理する場合
基本は `ReceivedTime`(受信日時)を使います。なぜなら、あなたが「そのメールをいつ認知したか」の正確な証拠になるからです。
2. 「送信済みアイテム」のメールを処理する場合
`SentOn`(送信日時)を使います。
3. どちらが来るか分からない(あるいは両方混ざっている)場合
VBA側で「オブジェクトが空(Empty / Null)ではないか」を判定するガード節(条件分岐)を必ず挟みます。

この一手間を入れるだけで、あなたの書いたVBAコードの信頼性はプロ基準へと一気に跳ね上がります。

3. 実践!安全かつ確実にログを採取するVBAコード

それでは、現在のフォルダ(または選択中のメール)から、送信日時と受信日時を安全に取得し、イミディエイトウィンドウに美しく出力する実用コードを見てみましょう。

開発タブのVisual Basicエディタを開き、標準モジュールにペーストして実行してみてください。

Sub RecordMailTimestamps_Safe()
Dim ns As Outlook.NameSpace
Dim currentMail As Outlook.MailItem
Dim logSentTime As String
Dim logReceivedTime As String

‘ オブジェクトの取得(NameSpace経由で安全にセッションを掴む)
Set ns = Application.Session

‘ 現在選択しているアイテムを取得
On Error Resume Next
Set currentMail = ns.Application.ActiveExplorer.Selection.Item(1)
On Error GoTo 0

‘ メールが選択されていない場合のガード
If currentMail Is Nothing Then
MsgBox “処理対象のメールが選択されていません。”, vbExclamation, “警告”
Exit Sub
End If

‘ 【重要】メールアイテムかどうかをチェック
If currentMail.Class = olMail Then

‘ 1. 送信日時の取得 (SentOnは通常常に値を持つ)
If IsDate(currentMail.SentOn) Then
‘ 協定世界時(UTC)からローカル時刻への補正が含まれるためFormatで整える
logSentTime = Format(currentMail.SentOn, “yyyy/mm/dd hh:nn:ss”)
Else
logSentTime = “なし”
End If

‘ 2. 受信日時の取得 (送信済みメール等の場合は空になるため判定が必須)
If IsDate(currentMail.ReceivedTime) Then
logReceivedTime = Format(currentMail.ReceivedTime, “yyyy/mm/dd hh:nn:ss”)
Else
logReceivedTime = “(受信日時なし:送信済みの可能性)”
End If

‘ 3. ログ出力(ここをDB書き込みやCSV出力に置き換えます)
Debug.Print “—————————————-”
Debug.Print “件名: ” & currentMail.Subject
Debug.Print “送信日時 (SentOn) : ” & logSentTime
Debug.Print “受信日時 (ReceivedTime): ” & logReceivedTime
Debug.Print “—————————————-”

MsgBox “ログの取得に成功しました!イミディエイトウィンドウを確認してください。”, vbInformation, “完了”

Else
MsgBox “メール以外のアイテム(会議予定や連絡先など)が選択されています。”, vbExclamation, “確認”
End If

‘ メモリの解放(アーキテクトのたしなみ)
Set currentMail = Nothing
Set ns = Nothing
End Sub

コードのここがポイント!

  • `IsDate()` 関数による型安全の担保:Outlookのプロパティはバリアント型(Variant)で返ってくることが多いため、いきなり文字列化やDB代入をせず、`IsDate`で日付データが入っているかをスマートに検証しています。
  • `currentMail.Class = olMail`:Outlookにはメールだけでなく、予定表やタスクも混ざり得ます。メール特有のプロパティを安全に叩くための必須防壁です。
  • オブジェクトの解放:処理の最後できちんと `Set ~ = Nothing` を行うことで、メモリリークを防ぎ、Outlook自体のフリーズリスクを劇的に減らします。

まとめ

今回は、Outlook VBAにおける「送信日時」と「受信日時」の決定的な違いと、エラーを回避しながら正確にログを管理するための極意をお伝えしました。

  • 受信メール = `ReceivedTime` を主軸に。
  • 送信メール = `SentOn` を主軸に。
  • 両者を扱うシステム = `IsDate` で空チェックのガードを必ず入れる。

この基本原則さえ押さえておけば、どれだけ大量のメールをデータベースに同期する巨大なマクロを作ることになっても、日付データの不整合で頭を抱えることはもうありません。

あなたのOutlook自動化ライフが、より堅牢でスマートなものになることを応援しています。それでは、次のステップへ進みましょう!

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