IMAP のIDLEコマンドの通知タイミングについて調べるため、とりあえず生のIMAP4コマンドを使う必要があった。
imap コマンドを使ってGmailを読み出す。
gmail で IMAPが有効になってればす、ターミナルから、IMAPプロトコルを使って対話できる。
ログイン
? login takuya@exmaple.com **PASSWORD**
「?の意味」ここでは ? を使っているが、コマンド識別のための任意の文字列で何でも可能。ただし。*/+などはIMAPで意味を持つ記号なのでダメ
メールボックス一覧
?? LIST "" "*"
メールボックス内部のメール一覧
???? search all
ログアウト
?? logout
別解
IMAPは同じ目的を別のコマンドで実現することも出来る
メールの一覧(search all 代替)
? fetch 1:* uid
fetch コマンドですべてのメールを対象にすることで、search all と同じ振る舞いをさせられる。
実際にGmailのIMAPサーバーに接続して通信した例
以上を踏まえて、GmailとIMAPで通信した例が以下になります。
赤の太字が実際にターミナルから入力したコマンド
takuya@air:~/Desktop$ openssl s_client -connect imap.gmail.com:993 -crlf (中略) 0060 - b7 09 37 38 30 3b 70 c0-27 60 c7 b3 e1 2b 63 97 ..780;p.'`...+c. 0070 - 56 03 10 3c 5b a5 b8 48-b9 84 23 51 0e 24 1d 6a V..<[..H..#Q.$.j 0080 - 57 10 3b 2f 35 c0 f2 ff-38 69 4f e4 55 8a dd 10 W.;/5...8iO.U... 0090 - a9 e1 73 78 ..sx Start Time: 1352575032 Timeout : 300 (sec) Verify return code: 20 (unable to get local issuer certificate)
-
- -
imapではメールはフラグ単位で管理される。
imap はフラグ単位でメールを管理します。これが特徴で重要。なぜこんなフラグがあるかというと、IMAPは非同期マルチスレッドを意識したプロトコルだからだそうです。つまり複数クライアントから同時に複数人がアクセスすることを想定するからだそうです。iphoneでメールを読むと既読状態がipad にも連携される。そういうことですね
主なフラグ
- 未読(UNSEEN)
- 返信済み(ANSWERED)
- 削除(DELETED)
が挙げられます。他にも印をつけたマークなどもあるようです。
フラグの取得
1 fetch 1:* flags
* 1 FETCH (FLAGS (\Seen))
* 2 FETCH (FLAGS (\Seen))
* 3 FETCH (FLAGS (\Seen))
* 4 FETCH (FLAGS (\Seen))
* 5 FETCH (FLAGS (\Seen))
* 6 FETCH (FLAGS (\Seen))
* 7 FETCH (FLAGS (\Seen))
* 8 FETCH (FLAGS (\Seen))
* 9 FETCH (FLAGS (\Seen))
* 10 FETCH (FLAGS (\Seen))
* 11 FETCH (FLAGS (\Seen))
* 12 FETCH (FLAGS (\Seen))
(中略
* 54 FETCH (FLAGS (\Answered \Seen))
* 61 FETCH (FLAGS (\Seen))
* 62 FETCH (FLAGS (\Seen))
* 63 FETCH (FLAGS (\Seen))
* 64 FETCH (FLAGS ())
* 65 FETCH (FLAGS ())
1 OK Success
最後の2件に注目
* 65 FETCH (FLAGS ())
\seen (既読)フラグが付いていません。つまり未読です。
メールの件数とINBOXの表示について
GMAILのINBOXの件数と、"search all "の結果件数が合わないことがあります。それはスレッドにまとまっているからですね。スレッドを取得するにはthread コマンドを使うようなのですがGmailは未サポートでした。2012/11/11現在のところ、メールをスレッドで取得はどうやるかわかりませんでした。
IDLEについて
001 IDLE
001+ idling
* 64 EXISTS
* 65 EXISTS
* 66 EXISTS
IDLEを使うと、サーバーがメールボックスの変化を通知してくれます。
通知されるタイミングは、新着メールが来てから約2秒後ですね。体感でプッシュ通知よりも遅い感じでした。さらに体感ではXMPP(google talk)よりもIDLEによる通知が後からくる感じでした。
メールが来る度に、通知が一つ増えます。変化があるたびに通知されます。
メールボックスの削除・作成
メールクライアントソフト(MUA)でも作ってない限りお世話になることはまず無いので、割愛。
同じ理由でsubscribeも使うことはないと思います。Gmailの管理画面から似たようなことできるしね。
メールの既読化
メールに既読フラグを立てるときは、storeをつかう。
?? store 65 +flags \seen
* 65 FETCH (FLAGS (\Seen))
未読化
メールを未読にするときは、既読フラグを消す。
?? store 65 -flags \seen
* 65 FETCH (FLAGS ())
フラグ操作
フラグ | 意味 |
---|---|
FLAGS | 指定フラグに置換える |
+FLAGS | 指定フラグを追加する |
-FLAGS | 指定フラグを削除する |
フラグは、複数フラグをスペース区切りで並べてフラグリストにしてもいい
Gmailフォルダ(ラベル)を付ける
INBOXからAmazonGiftと書かれたラベルを付ける。ラベル付与はコピーをする。コピーをするとINBOXとAmazonGiftの両方のラベルがつく。
???? select inbox (中略 ?? copy 65 AmazonGift * 66 EXISTS ?? OK [COPYUID 57 27459 3677] (Success)
上記実行後にGmailにWEBにログインしてみると、INBOXとAmazonGiftの両方のラベルが付いてます。
メッセージの移動の場合。
INBOXのメッセージを別のラベルに移動するときは、コピー後にINBOXから消す(アーカイブする)
それには、コピー後に\deletedフラグ付与とExpungeを呼び出す。
?? copy 65 AmazonGift * 66 EXISTS ?? OK [COPYUID 57 27459 3677] (Success) ?? store 65 +flags \deleted * 65 FETCH (FLAGS (\Seen \Deleted)) ?? OK Success ?? expunge * 65 EXPUNGE * 65 EXISTS ?? OK Success
とする。これで合ってるんだけど、削除関係については自信がない。moveはなくて、Copy+deletedフラグのはずなんだけどRFC調べるの面倒でちゃんと読んでないです。とくにArchive(All Mail)とGmail側の削除とdeletedフラグの関係が謎すぎてよくわからないんですよ
以上
これだけサンプルがあれば、手作業でIMAPプロトコルを叩いて、ある程度イメージが掴めると思います。いまさらIMAPを直接使うことは無いとは思いますが。imap4ライブラリやパッケージでメソッドの順番がイマイチピンと来ないときなどやっぱりプロトコル直接叩いたほうがあっさり理解でるんではないでしょうか。
参考資料
寿限無: gmail の imap で append
http://isoya7.blogspot.jp/2011/01/imap-imap4.html
IMAPを利用すると何ができるのか?:モバイル環境に優しいメールプロトコルIMAP(1) - @IT
IMAP4をより使いやすくする拡張機能:モバイル環境に優しいメールプロトコルIMAP(2) - @IT
CyrusでIMAPサーバを構築する:モバイル環境に優しいメールプロトコルIMAP(3) - @IT
IMAPプロトコルの流れを学ぶ:モバイル環境に優しいメールプロトコルIMAP(4) - @IT
IMAP4(Internet Mail Access Protocol version 4)〜前編:インターネット・プロトコル詳説(8) - @IT
IMAP4のFETCHオプションの一覧
http://www.sk-jp.com/book/javamail/contents/javamail_appendix.html
GmailをIMAPで読む方法
IMAP: how to move a message from one folder to another - Stack Overflow
http://objectmix.com/imap/201901-imap-command-move-message.html
class Net::IMAP (Ruby 1.9.3)
http://www.python.jp/doc/release/library/imaplib.html