メール全未読受信の失敗事例

最終更新日:1999.06.16


ある会議室で、次のような質問があがりました。
『ザウルスでメールの全未読受信をしている。 当日中は正しく未読メールのみを落としてくるのに、 翌日になると既に読んだものまで受信するようになってしまった。』

本来 POP3 サーバーには未読も既読も区別がないので、 全て読み込むのは当然の事だと思っていたのですが、 よくよく見ると、MI-610 以降の機種では Internetメールでも 全未読受信ができていたんですね。

それでは・・ということで、実験がてら調べてみました。

Internetメールの全未読受信は厄介

メールの未読だけを受信するなんて、別に難しくもないように思いますが、 実は少々厄介なのです。 Internetメールでは送信に SMTP, 受信に POP3 という別々のプロトコル (場合によっては別々のサーバー)を利用しているのですが、 困ったことに POP3 には未読か既読かの概念が無いのです!

POP3 でわかるのは、あなた宛てのメールが幾つサーバーに残っているか、 それらのサイズは幾らかといった情報だけで、読んだか読んでないかは一切 関知していないのですね。

それもあって、 『未読のみ受信なんてできないもの』と思い込んでいたのですが、 先に書いたように、MI-610 以降の機種では 全未読受信 か 選択受信 が できるようになっているとか。

どうやって実現しているか疑問に思いながらも、 まずは MI-610 を使って 2つのプロバイダのメールにつき試してみることにしました。

全未読受信を試してみる

【環境】

とりあえず現象を確認してみることにします。 用意したのはプロバイダA (NIFTY)と、プロバイダB (他)の2つ。 それぞれにメールアカウントを持ち、 ザウルス MI-610 で3日間ほど全未読受信を行ってみました。 当然、【受信したメールはサーバーに残す】の設定です。

【感想】

今まで選択受信ばかり使ってきたのですが、全未読受信って便利ですね〜。 もっと早く使ってれば良かったです(笑)。日付が変わる前後でも特に問題なく 未読の物だけを受信してくれますし、どちらのプロバイダでも全くもって正常です。

断定はできませんが『日付が変わると』という線は違うような気がしてきました。

ただ、気になった事が1つ。プロバイダBからプロバイダAへメールを送信した後、 (送信後に受信するの設定になっていたため)未読受信が始まったのですが、 その時、既読の物まで再度読み込んでしまったのです。

これは一体・・・

メール送信したら変になった?

今までうまく動いていたのに、最後の最後で現象が再現してしまいました。 再現した時の状況を細かく見てみると次のようになります。

  1. プロバイダBのアカウントでメールを作成。
  2. 宛先はプロバイダAのアカウント、BCC で自分(プロバイダB)にも送信。
  3. プロバイダBに接続して1通送信。
  4. 【送信後に自動で受信する】設定だったので、未読受信も実行。


それまで(正常に動作していた時)と大きく異なるのは、 メールを1通送信したということくらいですか。 Internetメールの送信は、SMTPサーバーとのやり取りだけですから、 POP3サーバーに影響は無いはずなのですが メール送信後におかしくなったのは事実です。

更に送信テストを行ってみたところ、 それまでは全く順調だったプロバイダBの全未読受信が全くだめ (= 毎回既読メールまで読み込む)になってしまい、もう何が何やら・・・。

整理して再チャレンジ

現象を整理すると、初めは順調だったのが、 ある時から未読も既読も関係なく 毎回全てが落とされるようになったという事。 ある時というのは、プロバイダBから送信されたメールが、 プロバイダBのメールボックスに入った時の事。

プロバイダA,B間のやり取りだけではどうにもらちがあかないので、 更にもう1つ別のプロバイダCを追加して 3つのアカウント間でテストしてみる事にしました。 プロバイダC用にはチェックの厳しいポスペを利用してみます。

さて、こうしてプロバイダA,B,C間でやり取りしてみたところ、 どうもプロバイダBからメールを送信した場合に問題が出るようです。

色々と試してみたところ、プロバイダBを受信側とした場合に、 自分自身から送られたメールで問題が起きていることが判りました。 プロバイダCからポスペで送った場合には、 正しく未読・既読の判定がなされているのに、 プロバイダBから送った場合には全部落としてくるのです。

これで再現率100%になったわけですが、一体これらの違いは何なのでしょう。

未読の判定方法

初めに書いたように、 POP3プロトコルには未読位置を調べるような物は存在しません。 前は LAST コマンドというものがありましたが、 これも最新の POP3では存在が抹消されている上、 もともと最後にアクセスした物の番号というだけなので、 未読ポインタ的な用途には使えません。

そうなるとどうやって未読判定を行っているかですが、 今回使ったメーラーの1つは、 受信したメールの情報をディスクに保存しておき、 それと比較することで未読のみの受信を行っているとのことです。

つまり、POP3サーバー側に未読ポインタが無いのならば、 何らかの情報をメーラーが覚えておくことで未読受信を行う・・・ これがPOP3での定番のようです。

さて、そうするとザウルスのメーラーが一体何で未読か既読かを 判定してるかが問題となります。 試してみたところ、 受信したメールを全て削除しても全未読受信は 正常に動作していますので、 メールボックスを見ているのではなさそうです。

プロバイダ毎に未読を覚えているところを見ると、 接続先ごとに何か個々のメールを区別できるような識別子を 保存しているのじゃないかと推測されます。

そこで POP3 関連の文書を調べてみると、 メールサーバー内の個々のメールを区別する短い識別子として、 UIDLコマンドで得られる識別子と、Message-ID がある事がわかりました。 きっと、これらの内のどれかを接続先ごとに記憶して使っているのでしょう。

しかし、それだとしたら何で未読判定がおかしくなったのか・・・。

Message-IDとメーラーの誤った実装

ここでちょっとザウルスの話からそれます。

Internetメールはその書式がRFCで規定されているのですが、 多少曖昧な部分もあり、メーラーの実装に細かな違いが見られます。 その最たる物として、Message-ID 問題があります。

規定では、Message-ID 項目は世界中で唯一の識別子になるように 作らねばならない事、メーラーが値を生成してつける事となっているのですが、 SMTPサーバーの有名どころ sendmail が 【Message-ID がついてなければ自動補完してくれる】 というのを良いことに、全く付けないメーラーが世の中に溢れています。

この結果、自動補完を行わない SMTPサーバー(これは正しい)と、 Message-ID をつけないメーラー(良くない)との組み合わせで発信された場合、 世界中で唯一を保証する値である Message-ID の欠けたものが流れてしまうのです。

個々のメールを識別するのに、UIDL か Message-ID が使えると 書きましたが、Message-ID が無かった場合には区別のしようがありません。 UIDLで得られるIDリストにしても、POP3サーバーによってはそのまま Message-IDリストを返してくるので、これは困った問題です。

後で判りましたが、実は今回テストに使ったWindows上のメーラー、 そして、ザウルス MI-610 のメーラー共に Message-ID をつけずに 送信していたのです。

・・・ということは!

原因究明

外部からポスペで送信した場合にはうまく未読のみ受信でき、 内部から別のメーラーで送信した場合には、未読・既読全てが読まれる。

そう、実はこれは Message-ID の有無に原因があったのです!

つまり、ザウルスで全未読受信を行った場合、 最後に読んだものの Message-ID を記憶しておき、 次回接続時にはこれを元にして読み込み位置を決めているようなのです。 従って、もしも Message-ID が欠けているメールが最後にあったとしたら、 Message-ID = NULL ・・・つまり、 何も読んでいないと覚えてしまうのです。

これを実証する為に、次の操作を行ってみました。
(実験前に、各プロバイダのメールボックスはクリア済)

操作内容今回の
受信数
メール
サーバ
内残数
ザウルスで全未読受信0 (正常)0
外部から1通送信(ID付き)-1
ザウルスで全未読受信1 (正常)1
ザウルスで全未読受信0 (正常)1
外部から1通送信(ID無し)-2
ザウルスで全未読受信1 (正常)2
ザウルスで全未読受信2 (異常)2
外部から1通送信(ID付き)-3
ザウルスで全未読受信3 (異常)3
ザウルスで全未読受信0 (正常)3


つまり、メールサーバー内の最後のメールに Message-ID があるか無いかで 全未読受信の結果がおかしくなっている事がわかります。 そしてその場合でも、まともなメールが1通入ってくれば、 次回からは正常に全未読受信ができることもわかります。

ただ困った事に、 ザウルスのメーラーも自分では Message-ID をつけない為、 【自分宛にも送信】している場合、 自分が送信したメールのせいで全未読受信に失敗するケースがありそうです。

そう、初めの方で送信後に失敗したというのは、 BCC で自分宛に送信していた事が原因だったのです。

まとめ

Message-ID はメールに必ずついてなければならない物で、 つけずに送信するメーラー側に問題があります。 ザウルスのメーラーもそうですが、 WindowsやMac用のメーラーでも この辺りの実装がいい加減です。 メーラーを作成する方々には、この辺りはしっかりと作って貰いたいものです。

なお、今回は Message-ID が無い事による全未読受信の失敗例を取り上げましたが、 例えば、Message-IDが唯一であると保証されない物だった場合など (これも送信側が悪い)にも失敗する可能性があります。

とりあえず、今回調べた範囲ではこれが原因だったのですが、 他にも色々な要因があることでしょう。 こちらで再現できるものであれば、機会を見て調べてみたいと思います。