IMAPをコマンド操作する †
接続 †SSL使用しない場合 telnet imap.example.com 143 SSL通信する場合は openssl を使用する openssl s_client -connect imap.gmail.com:993 -crlf -quiet コマンド入力の基本 †コマンド入力時は、行の先頭に識別子を付加して行う。 識別子 コマンド 引数/オプション等 コマンドに対する結果は、コマンド実行時に入力した識別子が付加して返却される。 例) 識別子として test01 を指定して、メールボックス一覧を表示する場合 test01 list "" "*" # コマンド入力 * LIST (\HasNoChildren) "." "INBOX.Drafts" # ↓ 以降はレスポンス * LIST (\HasNoChildren) "." "INBOX.Trash" * LIST (\HasNoChildren) "." "INBOX.Sent" * LIST (\Unmarked \HasChildren) "." "INBOX" test01 OK LIST completed # レスポンスの最終行にも識別子が付加される ログイン †a01 login test@example.com mail_password a01 OK LOGIN Ok. メールボックスの一覧表示 †a02 list "" "*" * LIST (\HasNoChildren) "." "INBOX.Drafts" * LIST (\HasNoChildren) "." "INBOX.Trash" * LIST (\HasNoChildren) "." "INBOX.Sent" * LIST (\Unmarked \HasChildren) "." "INBOX" a02 OK LIST completed メールボックスの選択 †a03 select "INBOX" * FLAGS (\Draft \Answered \Flagged \Deleted \Seen \Recent) * OK [PERMANENTFLAGS (\* \Draft \Answered \Flagged \Deleted \Seen)] Limited * 9 EXISTS * 0 RECENT * OK [UIDVALIDITY 1483004963] Ok * OK [MYRIGHTS "acdilrsw"] ACL a03 OK [READ-WRITE] Ok ※ メールの検索 †a04 search all * SEARCH 1 2 3 4 5 6 7 8 9 a04 OK SEARCH done. メッセージ番号を指定してメールヘッダを取得する †a05 FETCH 2 RFC822.HEADER * 2 FETCH (RFC822.HEADER {1015} Return-Path: メッセージ番号を指定してメール内容を取得する †a06 FETCH 2 RFC822 * 2 FETCH (RFC822 {1434} Return-Path: メッセージ番号を指定してメールを削除する †メールの削除はDeletedフラグを設定後に、EXPUNGE(Deletedフラグの立っているメールを削除する) を実行する。 a10 COPY 2 \"INBOX.Trash" # 対象のメッセージ番号のメールをゴミ箱にコピーする a11 STORE 2 +FLAGS (\Deleted) # 対象のメッセージ番号のメールに Deleted フラグを立てる a12 EXPUNGE # Deleted フラグの立っているメールを削除する phpで ソケット通信する例 †接続/ログイン †$fp = fsockopen("imap.example.com", "143", $errno, $errstr); //SSL通信しない場合 // $fp = fsockopen("ssl://imap.gmail.com", "993", $errno, $errstr); // SSL通信する場合 fputs($fp,"A01 login {$username} {$password}\r\n"); while (true) { $line = fgets($fp); if (preg_match("/(NO |failed|Failure)/i", $line)) { // ログインエラー fclose($fp); } if (preg_match("/^A01 /", $line)) { // 最終行 break; } } 件名のデコード †Subject 等のヘッダは エンコードされた文字列から適切なデコード方法を判定できる。 PHPの例) public function decode_subject($line) { $subject = $line; if (preg_match_all("/=\?[a-zA-Z0-9\-_]+\?(B|Q)\?.+?\?=/", $subject, $ms)) { $matches = $ms[0]; $rep = []; foreach ($matches as $i => $str) { $charset = preg_replace("/[^a-zA-Z0-9\-_]/", "", preg_replace("/\?.+$/", "", preg_replace("/^=\?/", "", $str))); $subject_piece = $line; if (preg_match("/=\?".$charset."\?(B|Q)\?/i", $str, $ms)) { //$subject_piece = mb_decode_mimeheader($str); $subject_piece = preg_replace("/\?=/", "", preg_replace("/=\?".$charset."\?(B|Q)\?/i", "", $str)); if ($ms[1] == "B") { $subject_piece = mb_convert_encoding(base64_decode($subject_piece), "utf-8", $charset); } else { $subject_piece = mb_convert_encoding(quoted_printable_decode($subject_piece), "utf-8", $charset); } } $rep[$i] = $subject_piece; } $subject = preg_replace("/\?=( |\t|\r\n|\r|\n)+=\?/", "?==?", $subject); // パート間のスペースを削除 foreach ($matches as $i => $str) { $subject = str_replace($str, $rep[$i], $subject); $subject = str_replace($str, "", $subject); } } else { $subject = mb_convert_encoding($subject, "UTF-8", "auto"); } return $subject; } 以下に例/イメージを記載する。 デコード前 =?utf-8?B?TWFj44GL44KJ6YCB5L+h44GX44Gf44OG44Kt44K544OI44Oh44O8?= =?utf-8?B?44Or?= 分割( ?文字コード?(B|Q)? 〜 ?= を 1つの纏まりとして分割する ) =?utf-8?B?TWFj44GL44KJ6YCB5L+h44GX44Gf44OG44Kt44K544OI44Oh44O8?= =?utf-8?B?44Or?= デコード後 =?utf-8?B?TWFj44GL44KJ6YCB5L+h44GX44Gf44OG44Kt44K544OI44Oh44O8?= → Macから送信したテキストメー =?utf-8?B?44Or?= → ル 結合後 Macから送信したテキストメール 本文のデコード †Content-Type 及び Content-Transfer-Encoding の内容を参照してデコードを行う。 TODO:
添付ファイルの取得 †TODO:
multipart の取り扱いについて †TODO:
multipart/alternative なメールの取り扱い †TODO:
UIDを指定して各種操作を行うには †上記の例で使用しているメッセージ番号は、常に1〜連番で付番される為、メールの削除等を行うと変わってしまう。(不変の番号ではない) UIDを指定してコマンド実行を行うには、コマンドの前に "UID" を入力する。 例) # SEARCHの結果をUIDで表示する a04 UID SEARCH ALL * SEARCH 1 5 8 10 12 a04 OK SEARCH done. # UID=10 を指定してメールヘッダを取得する a05 UID FETCH 10 RFC822.HEADER * 10 FETCH (RFC822.HEADER {1015} Return-Path: 他にも、COPY、FETCH、STORE なども可能。 |