ThunderbirdでSome messages could not be FETCHed (Failure)というエラーが出る
しばらくの間、Thunderbird(というか、Shredder)でGmail IMAPを使っていると、
Some messages could not be FETCHed (Failure)
というエラーが出るようになっていたんですが、いい加減、うざったくなってきたので、解決方法を探ってみました。
とりあえず、ググってみたんですが、解決方法がまとまっているところは無いようなので、まとめておきます。
Thunderbirdのプロトコルログを取る
最初に、そもそも、Thunderbirdがどのメッセージでつまずいているのかを知る必要があります。これには、Thunderbirdにプロトコルログを吐いてもらう必要があります。まとまっているところとしては、
があります。要は環境変数を設定してから起動しろと。バッチファイルを書いてねとありますが、コマンドプロンプトから直打ちでもかまいません。適当なディレクトリで、
C:\work> set NSPR_LOG_MODULES=imap:5 C:\work> set NSPR_LOG_FILE=C:\work\imap.log c:\work> "C:\Program Files\Mozilla Thunderbird\thunderbird.exe"
のようにやればいいです。Thunderbirdのパスは場合によっては修正が必要です。
ログがでかくなりすぎるのを防ぐために、エラーが出たら、さっさとThunderbirdは閉じてしまいましょう。
プロトコルログを調べる
さて、今作った、imap.logというプロトコルログですが、あっという間に数十MBとかになりまので、メモ帳だと微妙に荷が重いかもしれませんが、このファイルから、
Some messages could not be FETCHed (Failure)
を含む部分を検索します。エラーが一回しか出てなければ、引っかかる部分も一カ所しかないはずです。
僕の場合だと、
....<省略>.... 4492[e70e440]: e5cf000:imap.gmail.com:S-INBOX:SendData: 10 UID fetch 67394 (UID RFC822.SIZE FLAGS BODY.PEEK[HEADER.FIELDS (From To Cc Bcc Subject Date Message-ID Priority X-Priority References Newsgroups In-Reply-To Content-Type)]) 4492[e70e440]: ReadNextLine [stream=ea584c8 nb=52 needmore=0] 4492[e70e440]: e5cf000:imap.gmail.com:S-INBOX:CreateNewLineFromSocket: 10 NO Some messages could not be FETCHed (Failure) ....<省略>....
となっていました。IMAPは複数接続のプロトコルなので、エラーの前の行がエラーの原因とは限らないのですが、おおよそ、前の行がエラーの原因であると考えて良いでしょう。この部分のの前の行を見ると、
10 UID fetch 67394 (UID RFC822.SIZE FLAGS BODY.PEEK[HEADER.FIELDS (From To Cc Bcc Subject Date Message-ID Priority X-Priority References Newsgroups In-Reply-To Content-Type)])
というコマンドを発行しているのが分かります。これは、UID=67394のメールをくれというコマンドなので、結局、この、「UID=67394のメール」が悪さをしているらしいことが分かります。
ここでの目的は、とりあえず、この悪さをしているメールを削除することになります。
Python imaplib
さて、IMAPを駆使してメールを削除したいのですが、OpenSSLでセッションを張ってIMAPプロトコルを自由自在に操れる人なんて普通は居ませんから、なんかのライブラリとかプログラムを使わざるを得ないですが、ここでは、Pythonのimaplibを使うことにします。
Pythonは、
Download Python [www.python.org]
からダウンロードできますが、3.X系だと、imaplibがちゃんと動かないっぽいので、2.6をダウンロードして、インストールしてください。
そうすると、スタートメニューに「IDLE (Python GUI)」というのがインストールされるので、それを起動します。
このウィンドウに対して、次の行を入力していきます。
import imaplib s = imaplib.IMAP4_SSL('imap.gmail.com') s.login('アカウント名@gmail.com', 'パスワード')
ここで、ちゃんとログインできれば、
('OK', ['アカウント名@gmail.com authenticated (Success)'])
のように表示されているはずです。
さらに、INBOXに移動するために、次のように入力します。
s.select()
うまくいけば、次のように表示されます。OKの次にあるのはメールボックス内のメール総数です。
('OK', ['67469'])
メールの番号を調べる
さて、UID=67394のメールを消したいのですが、最初にこのメールが現在のメールボックス内で何番目のメールなのかを特定する必要があります。それには、次のように入力します。
s.search(None, 'UID', '67394')
うまく行けば、
('OK', ['55569 (UID 67394)'])
のように表示されます。これで、このメールのメールボックス内での番号が55569であることが特定できました。
じゃあ、ひと思いにこのメールを消してしまいたいところですが、このメールが何者なのか知ることが出来るなら知りたいものです。それには、
s.fetch('55569', '(BODY.PEEK[HEADER.FIELDS (From To Date Subject)])')
のようにやりますが、まぁ、おそらく、うまくいかないでしょう。Thunderbirdが同じようなコマンドを処理してうまくいかないわけですから。
ただ、このメールの前後のメール、ここでは、55568, 55570に関しては、情報が得られるでしょうから、それらについて、Dateなどを確認することによって、いつのメールが壊れたのかぐらいはうかがい知ることは出来ます。メールを消してしまうわけですから、覚悟のためにも、前後のメールぐらいは確認しておくべきでしょう。
さて、いよいよ、メールを削除しましょう。次のコマンドを入力してください。
s.store('55569', '+FLAGS', '\\Deleted')
うまくいけば、
('OK', ['55569 (FLAGS (\\Seen \\Deleted))'])
のように表示されます。このコマンドは、メールに\\Deletedというフラグを付与するだけです。実際に削除するには、この後に、
s.expunge()
というコマンドを実行します。うまくいけば、
('OK', ['55569'])
と表示されます。これで作業完了です。このままこのウィンドウを閉じてしまってもかまいませんが、我々のために働いてくれるGoogle様に失礼なので、
s.logout()
とやりましょう。