Plugin 作成の為の Blueberry HOT 技術情報 (1) 基本的な事 Plugin は、ヘッダファイル ihttpmail.h にあるクラス HTTPMAIL をオーバーライド して作成します。(ihttpmail.h はこのファイルの最後にあります) 開発ツールは VC6 を想定しています。 ソースプログラムのコンパイルにあたってはマルチスレッド仕様で構造体のアライン メントは8バイト、その他はデフォルトの状態にしてください。(ただしスタックサ イズは必要に応じて設定) ★ HTTPMAIL は次のように定義されています。 class HTTPMAIL { public: HTTPMAIL(){}; ~HTTPMAIL(){}; // virtual BOOL Initialize()=0; virtual void Release()=0; // virtual BOOL Login(LPSTR lpszUser,LPSTR lpszPass,BOOL bPOP)=0; virtual void Logout()=0; // virtual HMSGINFO *ListMessage(INT *result)=0; virtual INT GetMsgCount()=0; virtual BOOL Retr(HMSGINFO* pMsgInfo,LPSTR lpszFileName,INT cbSize,BOOL bSetRead,BOOL bTOP)=0; virtual BOOL Dele(HMSGINFO* pMsgInfo,BOOL bList)=0; virtual BOOL Send(LPSTR lpszFileName)=0; }; ★ オーバーライドの例 class HOTMAIL : public HTTPMAIL{ public: HOTMAIL(); ~HOTMAIL(); BOOL Initialize(); void Release(); BOOL Login(LPSTR,LPSTR,BOOL); void Logout(){}; HMSGINFO *ListMessage(INT*); INT GetMsgCount(); BOOL Retr(HMSGINFO*,LPSTR,INT,BOOL,BOOL); BOOL Dele(HMSGINFO*,BOOL); BOOL Send(LPSTR); private: . . . . }; (2) 関数のエクスポート DLL は次の三つの関数を作成してエクスポートしてください。 HTTPMAIL *WINAPI ClassFactory(CFINFO*); DWORD WINAPI GetThisVersion(); LPCSTR WINAPI GetServiceName(); .def ファイルは次にようになると思います。 LIBRARY HOTMAIL DESCRIPTION "Implements a hotmail." EXPORTS ClassFactory @1 GetThisVersion @2 GetServiceName @3 (a) HTTPMAIL *WINAPI ClassFactory(CFINFO*); この関数はクラス HTTPMAIL をオーバーライドして作成したクラスのインスタ ンスを返します。作成できなかった場合は NULL を返します。 POP3 セッションが開始されるたびに呼び出されますので、その度ごとに新し いインスタンスを作成して返してください。 この関数に渡される構造体 CFINFO は次のようになっています。なお、この構 造体の寿命は、この関数が終了するまでですので、必要に応じてコピーを作成 して利用します。 typedef struct tagCFINFO{ HANDLE hStopEvent; INT nHTTPTimeOut; BOOL bGenLog; BOOL bUseProxy; CHAR szProxyServer[128]; CHAR szServiceName[128]; } CFINFO; <メンバについて> ** hStopEvent これはイベントハンドルです。 Blueberry HOT が終了しようとする時にシ グナル状態になります。シグナル状態になったら、処理中の作業をを30秒 以内に終了してください。なお、このハンドルは開放しないでください。 ** nHTTPTimeOut これはユーザーが希望するタイムアウト時間です。単位はミリセコンド ** bGenLog ログ作成フラグで、TRUE の場合に通信ログを作成します。無視しても 構いません。 ** bUseProxy HTTP Proxy を通してリモートに接続する場合に TRUE になっています ** szProxyServer プロキシサーバの名前です。サーバ名:ポート番号になっています。 :ポート番号が無い場合はデフォルトのポート 80 です。 上の bUseProxy が TRUE の場合に有効です。 ** szServiceName これはサービス名で、例えばホットメールの場合は hotmail.com のようになります。 ★ 例 HTTPMAIL *WINAPI ClassFactory(CFINFO* lpINFO){ //CFINFO をコピー CopyMemory(&cfinfo,lpINFO,sizeof(CFINFO)); //インスタンス作成 return (HTTPMAIL*)new HOTMAIL(); } (b) DWORD WINAPI GetThisVersion(); バージョン情報を返します。バージョン情報は下3桁でマイナー バージョンを、上2桁でメジャーバージョンを現してください。 たとえば、バージョン 2.05 の場合は 2050 になります。 この値を DWORD の16進数で返します。 (c) LPCSTR WINAPI GetServiceName(); サポートするサービス名を返します。この関数は一番最初に呼び出されます。 サービス名は、例えばホットメールの場合は "hotmail.com" になります。つまり、 ウエブメールアドレスのドメインです。複数サポートする場合は ";" で区切って、 "hotmail.com;msdn.com" のようにします。 なお、このサービス名は DLL の中に定数として確保してください。 (2) クラス HTTPMAIL のオーバーライド HTTPMAIL のメンバ関数のオーバーライドは次の仕様に従ってください。 (a) BOOL Initialize(); 先に説明した関数 ClassFactory がインスタンスを正しく返して きたらすぐに呼び出されます。 必要な初期処理をおこなってください。初期化処理成功した場合は TRUE、失敗 した場合は FALSE を返します。 初期処理が必要ない場合は、もちろん、なにもしなくて構いません。 (b) void Release(); インスタンスが不要になった段階で呼び出されます。この関数の中で 自分自身を開放してください。 インスタンスの開放は delete ではなく、この Relesae で行いますので ここで必ず自分を解放してください。 ★ 例 void Release(){ delete this; } (c) BOOL Login(LPSTR lpszUser,LPSTR lpszPass,BOOL bPOP); ウエブメールにログインする為の関数です。成功した場合は TRUE、失敗した 場合は FALSE を返します。この関数はログインに成功するまで、複数回 呼び出される可能性があります。   引数の意味は次の通りです。決して値を破壊しないでください。 lpszUser : ユーザー名 lpszPass : パスワード bPOP は、受信用にログインする場合に TRUE、送信用にログインする場合は FALSE になっています。 (d) void Logout(); ウエブメールからログアウトする場合に呼び出されます。ログアウト処理 を行ってください。 (e) HMSGINFO *ListMessage(INT *result); 「受信箱」のメッセージをリストし、HMSGINFO 構造体のリストとして 返します。成功した場合は *result に1を、失敗した場合は0をセット して関数を終了します。 返された HMSGINFO 構造体のリストは呼び出し側では開放しませんので、 自分で開放してください。ただし Release が呼び出されるまでは開放しない でください。この関数は Release が呼びだれるまでに一度だけ呼びださ れます。       HMSGINFO 構造体は次のようになっています。なお、この構造体にセット       された値は Release が呼び出されるまで有効でなくていけません。              typedef struct tagHMSGINFO{ struct tagHMSGINFO *next; BOOL bDeleted; BOOL bRead; BOOL bError; INT nOctets; LPSTR lpszUIDL; LPSTR lpszLocation; LPSTR lpszSubject; } HMSGINFO; <メンバについて> ** next               次の HMSGINFO 構造体へのリンクです。              ** bDeleted               FALSE をセットします。              ** bRead               メッセージが既読の場合は TRUE そうでない場合は FALSE を        セットします。        ** bError        FALSE をセットします。 ** nOctets メッセージのサイズをバイト単位で設定します。それほどの 正確さは要求されていません。 ** lpszUIDL ユニークなメッセージIDの格納されてるアドレスを設定します。 (メールのMessage-Id とは違います)このIDは次にこの関数が 呼出された時も同じでなくてはいけません。 * ウエブメールの戻したIDを使うと良いでしょう。 ★ この値は呼出し側で必ず必要としています。       ** lpszLocation               メッセージ本体を示す URL の格納されているアドレスを設定しま        す。 ★ この値は呼出し側では必要としていませんので、自分の為に 設定してください。               ** lpszSubject               メッセージの件名の格納されているアドレスへのポインタです。        日本語の場合の文字コードはできるだけ ISO-2022-JP にしてく        ださい。 取得できない場合は NULL でも構いません。 (f) HMSGINFO *GetMsgCount(); 「受信箱」のメッセージ数を返します。       ★ この関数は ListMessage 関数より前に呼出される事はありません。 (g) BOOL Retr(HMSGINFO* pMsgInfo,LPSTR lpszFileName,INT cbSize,BOOL bSetRead,BOOL bTOP);        指定された一通のメッセージを取得しファイルに格納します。成功した場合は TRUE、 失敗した場合は FALSE を返します。ファイルに格納される内容は RFC2822 に従った フォーマットのテキストファイルにしてください。              ★ この関数は ListMessage 関数より前に呼出される事はありません。          引数の意味は次の通りです。 IN: pMsgInfo HMSGINFO 構造体へのポインタです。この構造体にセットされている値 は、先の ListMessage が返したものです。        OUT: lpszFilename                 メーセージを格納したファイルの名前をフルパスで設定して         返します。このファイルは呼出し側では削除しませんので、         自分で削除してください。ただし次の Retr が呼出されるまで         削除してはいけません。 IN: cbSize lpszFileName の為に確保されているメモリのサイズです。 単位はバイトです。 IN: bSetRead TRUE の場合は取り込んだメッセージを既読にします。 処理的、技術的に出来ない場合は無視しても構いません。 IN: bTOP POP3 の命令 "TOP" からこの関数が呼出された場合に TRUE になっています。それ以外の場合は "RETR" 命令から呼出されて います。 "TOP" は添付ファイルなどを必要としませんので、 必要に応じて処理してください。無視しても構いません。 (h) BOOL Dele(HMSGINFO* pMsgInfo,BOOL bList); 指定されたメッセージを削除します。この関数は POP3 の "QUIT" 命令 が発行された後に呼出されます。受信中に呼出される事はありません。   引数の意味は次の通りです。 IN: pMsgInfo HMSGINFO 構造体へのポインタです。この構造体にセットされている値 は、先の ListMessage が返したものです。 メッセージを削除する場合には HMSGINFO 構造体のメンバ bDeleted が TRUE の場合に削除します。 FALSE の場合は削除しないでください。 bDeleted の値は POP3 命令の "DELE" が発行された時にセットされて います。 IN: bList この値が TRUE の場合は、上の pMsgInfo のリンクを全てたどって bDeleted が TRUE の場合にメッセージを削除します。 そうでない場合は、先頭の一通だけが処理の対象になります。 (i) BOOL Send( LPSTR pszFileName) lpszFileName に格納されているファイルの内容を送信します。 送信をサポートしない場合は FALSE を返してください。 ファイルの内容は RFC2822 に従ってフォーマットされたテキスト ファイルです。 lpzFileName の内容は破壊しないでください。 なお、このファイルは呼び出し側で削除します。決してファイル を開いたままの状態で関数を終了しないでください。 (#) 補足 BBHOT.ZIP に格納された Plugin モジュールは DLL の中で WSAStartup を呼出して いませんので、これらのモジュールのテストを行いたい場合は DLL を呼出すプログ ラム側で WSAStartup を実行してください。 WinSock のバージョンは 1.01 を想定 しています。 また、これらのモジュールのライブラリファイルは提供しませんので、エクスポート されてる関数は GetProcAddress API を使って利用してください。 ま、しかし、簡単に作る為には WinSock を直接使うよりも WinInet API を利用 した方が良いかもしれませんが。 (*) 最後に プラグインを作成しようかと思われる方は、できるだけ、ここにある情報を 元に作成してください。質問メールをお送り頂いても対応できない場合が 多いです。 --- (付録) ihttpmai.h #ifndef _IHTTPMAILH_ #define _IHTTPMAILH_ typedef struct tagCFINFO{ HANDLE hStopEvent; INT nHTTPTimeOut; BOOL bGenLog; BOOL bUseProxy; CHAR szProxyServer[128]; CHAR szServiceName[128]; } CFINFO; typedef struct tagHMSGINFO{ struct tagHMSGINFO *next; BOOL bDeleted; BOOL bRead; BOOL bError; INT nOctets; LPSTR lpszUIDL; LPSTR lpszLocation; LPSTR lpszSubject; } HMSGINFO; class HTTPMAIL { public: HTTPMAIL(){}; ~HTTPMAIL(){}; // virtual BOOL Initialize()=0; virtual void Release()=0; // virtual BOOL Login(LPSTR lpszUser,LPSTR lpszPass,BOOL bPOP)=0; virtual void Logout()=0; // virtual HMSGINFO *ListMessage(INT *result)=0; virtual INT GetMsgCount()=0; virtual BOOL Retr(HMSGINFO* pMsgInfo,LPSTR lpszFileName,INT cbSize,BOOL bSetRead,BOOL bTOP)=0; virtual BOOL Dele(HMSGINFO* pMsgInfo,BOOL bList)=0; virtual BOOL Send(LPSTR lpszFileName)=0; }; extern "C"{ HTTPMAIL *WINAPI ClassFactory(CFINFO*); DWORD WINAPI GetThisVersion(); LPCSTR WINAPI GetServiceName(); }; typedef HTTPMAIL* (WINAPI* CLASSFACTORY)(CFINFO*); typedef DWORD (WINAPI* GETTHISVERSION)(); typedef LPCSTR (WINAPI* GETSERVICENAME)(); #endif -- 綾の明 2002/05/04