1999年10月30日 とよしま
hotmailをweb以外から利用する場合、特殊な方法を用いる事で効率的にメールデータにアクセスできる。本稿はhotmailをPOP3対応の通常のメーラーから読むために開発予定のPOP3 to Web-Mail Gateway開発のために書かれた。また、この資料を作成するにあたり、Outlook Expressの通信内容を参考にした。
hotmailで使用されるプロトコルは、HTTP/1.1をベースに、若干独自拡張を施したものである。また、認証にはDigest認証を用いるので、これに対応していなければならない。独自拡張は主に、リクエストコマンドの追加と、レスポンスステータスの追加である。これらについては次に説明を示す。Digest認証についてはrfc-2617を参考の事。また、本来Digest認証はHTTP/1.1の元に実装されるべきであるが、HTTP/1.0上に実装してもhotmailを利用するにあたって問題は確認されていない。また、User-AgentはOutlook Expressを名乗る必要がある、ということに注意しなければならない。
コマンド |
解説 |
PROPFIND |
Login中のユーザーに属する、各種データにアクセスするためのURLと付随情報を調査する。どのデータに関して調査するかはcontentとして送信されるXMLに記述される。このコマンドは複数の要求を同時に発行することができるようになっている。 |
PROPPATCH |
Login中のユーザーに属する各データ固有の情報を変更する。主にメールの未読フラグの変更等に利用される。 |
MOVE |
階層化されている各データを別階層に移動する。主にメールをごみ箱へ移動させる等に利用される。 |
コード |
解説 |
207 Multi-Status |
PROPFINDに対する応答として返す。要求ごとのレスポンスとステータスを要求だけ列挙したものをXMLとして返答してくる。 |
hotmailへの入り口となるURLはhttp://services.msn.com/svcs/hotmail/httpmail.asp となっている。ただし、通常このアドレスは301/302等を返してくるので、Locationに従って再度別サーバーにアクセスすることになるはずである。移動後のアドレスは常に変更される可能性があるため、アクセス時には必ずこのアドレスから調べるべきである。
ログインを開始するためには上で示したURLへPROPFINDを送信する必要がある。正しいアドレスにアクセスすると、401を返してくる。この際要求される認証がDigest認証となっている。クライアントはユーザー名、パスワードに従いDigestを計算し、それらを含め、再度サーバーにPROPFINDとして送る。このレスポンスとして207が返って来たならログインは成功である。PROPFINDとして送るデータは取得したい情報をXMLで列挙したものである。次に代表的な送信内容の例を示す。
<?xml version="1.0"?> <D:propfind xmlns:D="DAV:" xmlns:h="http://schemas.microsoft.com/hotmail/" xmlns:hm="urn:schemas:httpmail:"> <D:prop> <h:adbar/> <hm:contacts/> <hm:inbox/> <hm:outbox/> <hm:sendmsg/> <hm:sentitems/> <hm:deleteditems/> <hm:drafts/> <hm:msgfolderroot/> <h:sig/> </D:prop> </D:propfind> |
D:propの内側にあるのが要求する情報の列挙となっている。レスポンスは以下の通り。
<?xml version="1.0" encoding="windows-1252"?> <D:multistatus xmlns:D="DAV:" xmlns:m="urn:schemas:mailheader:" xmlns:hm="urn:schemas:httpmail:" xmlns:c="urn:schemas:contacts:" xmlns:h="http://schemas.microsoft.com/hotmail/"> <D:response> <D:href>http://…/</D:href> <D:propstat> <D:prop> <hm:contacts>http://…/abdata/</hm:contacts> <hm:inbox>http://…/folders/ACTIVE/</hm:inbox> <hm:sendmsg>http://…/sendmsg/</hm:sendmsg> <hm:sentitems>http://…/folders/sAVeD/</hm:sentitems> <hm:deleteditems>http://…/folders/trAsH/</hm:deleteditems> <hm:msgfolderroot>http://…/folders/</hm:msgfolderroot> <h:sig>______________________________________________________ Get Your Private, Free Email at http://www.hotmail.com </h:sig> </D:prop> <D:status>HTTP/1.1 200 OK</D:status> </D:propstat> </D:response> </D:multistatus> |
要求に対応したURLを応答してくる。以下の操作はここで得た各URLに対してPROPFINDを送信することで行う。また、ログイン時にはリクエストヘッダに「Depth: 0」と「Brief: t」を付加しておく必要がある。
ログイン時に得たURLに対してPROPFINDを送信することで任意の階層のデータが取り出せる。
リクエストの例は次の通り。
<?xml
version="1.0"?> <D:propfind
xmlns:D="DAV:" xmlns:hm="urn:schemas:httpmail:"
xmlns:m="urn:schemas:mailheader:"> <D:prop> <D:isfolder/> <hm:read/> <m:hasattachment/> <m:to/> <m:from/> <m:subject/> <m:date/> <D:getcontentlength/> </D:prop> </D:propfind> |
レスポンスの例は次の通り。
<?xml
version="1.0" encoding="windows-1252"?> <D:multistatus
xmlns:D="DAV:" xmlns:m="urn:schemas:mailheader:"
xmlns:hm="urn:schemas:httpmail:"
xmlns:c="urn:schemas:contacts:"
xmlns:h="http://schemas.microsoft.com/hotmail/"> <D:response> <D:href>http://…/folders/ACTIVE/MSGxxxxxxxxx</D:href> <D:propstat> <D:prop> <hm:read>0</hm:read> <m:to></m:to> <m:from>=?iso-2022-jp?B?SG90bWFpbCAbJEIlQSE8JWAwbEYxGyhC?=</m:from> <m:subject>=?iso-2022-jp?B?SG90bWFpbCAbJEIkWCRoJCYkMyQ9GyhCIQ==?=</m:subject> <m:date>1999-10-30T03:14:25</m:date> <D:getcontentlength>233</D:getcontentlength> </D:prop> <D:status>HTTP/1.1
200 OK</D:status> </D:propstat> </D:response> </D:multistatus> |
この通信で、inboxには1つのメールがあったため、そのメールヘッダ情報がやりとりとされている。複数メールがある場合には、D:responseが複数列挙される事になる。また、フォルダ情報取得時にはヘッダに「Brief: t」と「Depth: 1,noroot」を付ける必要がある。
上記の手順でフォルダの情報を取得することで、各メールを取り出すためのURL(http://…/folders/ACTIVE/MSGxxxxxxxxx)が得られる。このアドレスに対してGETコマンドを送る事でメールを受信できる。また、このURLはユニークになっているので、そのままUIDLとして使用できる。次にGETのリクエストの例を示す。GETにはコンテントはないのでヘッダを掲載する。これはPROPFIND等を行うときも同様であり、合わせてサンプルとする。
GET
/cgi-bin/hmdata/folders/ACTIVE/MSGxxxxxxxxx HTTP/1.1 Accept: message/rfc822,
*/* Translate: f User-Agent: Outlook
Express/5.0 (MSIE 5.0; Windows 98; DigExt) Proxy-Connection:
Keep-Alive Pragma: no-cache Authorization: Digest
username="mai__kawasumi@hotmail.com",
realm="hotmail.com", qop="auth",
algorithm="MD5",
uri="/cgi-bin/hmdata/folders/ACTIVE/MSGxxxxxxxxx",
nonce="OTQxMjUzMzcxOjcyNDZiMTVlOTFiOGFlZTUyNGE0ODRkZDBlNmNjNzdl",
nc=00000004, cnonce="833a03c26c473879455249498ee51dbe",
response="7d2cf965ea54b028ffb6a076e16c3287" |
このリクエストに対するレスポンスの例は次の通り。
HTTP/1.1 200 OK Date: Sat, 30 Oct 1999
03:16:53 GMT Server: Apache/1.3.6
(Unix) mod_ssl/2.2.8 SSLeay/0.9.0b Cache-Control: no-cache Expires: Mon, 01 Jan
1999 00:00:00 GMT Pragma: no-cache Connection: close Content-Type: message/rfc822 From:
=?iso-2022-jp?B?SG90bWFpbCAbJEIlQSE8JWAwbEYxGyhC?= Subject:
=?iso-2022-jp?B?SG90bWFpbCAbJEIkWCRoJCYkMyQ9GyhCIQ==?= Date: Sat, 30 Oct 1999
03:14:25 +0000 Mime-Version: 1.0 Content-Type:
text/plain; charset=iso-2022-jp $B?7$7$$%f!<%6!<$N3'MM$X(J MSN Hotmail $B$X$h$&$3$=!#(JMSN
Hotmail $B$O!"%$%s%?!<%M%C%H$G:G$b5^B.$K@.D9$7$F$$$k%3%_%e%K%F%#$G$9!#(J $B%F%-%9%HI=<($N%V%i%&%6$G$O!"(JMSN
Hotmail $B$N0lIt$N5!G=$,MxMQ$G$-$^$;$s!#(JMSN Hotmail $B$r;H$&$H!"$[$+$N(J
Web $B%Z!<%8$X$N%j%s%/$d2hA|$J$I!"K-IY$JFbMF$r4^$`EE;R%a!<%k$r$d$j$H$j$9$k$3$H$,$G$-$^$9!#(J $B$<$R!"2hA|$KBP1~$7$?%V%i%&%6$G(J
MSN Hotmail $B$r$*3Z$7$_$/$@$5$$!#(J MSN Hotmail $B%9%?%C%U(J |
通常受けたばかりのメールは未読状態になっている。これを既読状態にするためにはメッセージに対応するURLに対して、PROPPATCHコマンドを送信する必要がある。この時ヘッダには「Brief: t」が必要であることに注意する。成功時には200が返る。
<?xml
version="1.0"?> <D:propertyupdate
xmlns:D="DAV:" xmlns:hm="urn:schemas:httpmail:"> <D:set> <D:prop> <hm:read>1</hm:read> </D:prop> </D:set> </D:propertyupdate> |
読み終わったメールをごみ箱へ移動するためには、メッセージに対応するURLに対して、MOVEコマンドを送信する必要がある。この時、フォルダ情報の問い合わせ時に返ってきたごみ箱のアドレスが必要になる。以下、MOVEコマンドで、特殊な部分を上げて解説する。
MOVE /…/folders/ACTIVE/MSGxxxxxxxxx HTTP/1.1 Destination: http://…/folders/trAsH/MSGxxxxxxxxx Allow-Rename: t Content-Length: 0 . . . |
Destinationには移動先でのURLを指定する必要がある。このURLはフォルダ情報の問い合わせ結果として得られたものに、メッセージの名前(MSGxxxxxxxxx)を加えたものである。また、「Allow-Rename」に「t」を指定しておけば、移動後の名前が衝突していても、自動的に最適な名前に変更してくれるものと思われる(未確認)。レスポンスとしては以下のようなものが返ってくる。
HTTP/1.1 201 Created Date: Sat, 30 Oct 1999
03:17:16 GMT Server: Apache/1.3.6
(Unix) mod_ssl/2.2.8 SSLeay/0.9.0b Cache-Control: no-cache Expires: Mon, 01 Jan
1999 00:00:00 GMT Pragma: no-cache Location: http://…/folders/trAsH/MSGxxxxxxxxx Connection: close Content-Type: text/html;
charset=shift_jis <!-- IP: xxx.xxx.xxx.xxx
--> <!-- V: 08.05.10.0008
--> <!-- D: Thu Oct 14
16:00:25 PDT 1999 --> |
ステータスは201で、Locationに移動後のURLが入っていることに注意する。
RFC1945 -- Hypertext Transfer Protocol – HTTP/1.0
RFC2616 -- Hypertext Transfer Protocol – HTTP/1.1
RFC1321 -- The MD5 Message-Digest Algorithm
RFC2617 -- HTTP authentication: Basic and Digest Access Authentication