ようこそゲストさん

QdmailReceiver Multibyte mail decoder & POP Client

POP特有の処理(OOPタイプ)

初期設定は必ず行ってください。

OOPでいける方はそれなりにPHPに習熟した方と思いますので、例題の解説として進めます。
$receiver には、初期化されたQdmailReceiverオブジェクトが代入されているものとします。
ご自分の(安全な)受信サーバー(POPサーバー)を初期設定し以下を実行してみてください。
当然ですが、POPサーバーにメールが残っていなければなりません。テストする場合はあまりたくさんのメールが残っていると時間がかかりますので、数通にしておきましょう。
echo  "<pre>";
for($i = 1 ; $i <= $receiver->count() ; $i++){

    echo "Mail number: ".$receiver->pointer()."\r\n";
    echo htmlspecialchars(
        print_r(
           $receiver->header( array('subject','name') , 'none' )
        ,true)
    ,ENT_NOQUOTES);

    echo "\r\n";
    $receiver->next();
}

echo "</pre>";
メール件名一覧が表示されましたか?
順番に解説していきます。
$receiver->count()
で、POPサーバーに残っているメールの件数を取得します。
未読・既読の管理はPOPの機能ではできません(そもそもPOPプロトコルは未読・既読を行いません)
$receiver->pointer()
現在、どの順番のメールを読んでいるかを取得します。
この順番(pointer)はセッション毎(プロセス毎)に変わります。これをプロセスを超えて共有して使用すると意図しない結果となる場合がありますので、注意してください。
プロセスを超えて、メールを特定したい場合は、POP-UID機能を使ってください。
$receiver->header( array('subject','name') , 'none' )
いよいよ本題です。これで、件名を取得しています。
一般的には
$receiver->header( 取得するヘッダー名 , 存在しない場合の返り値(省略可) )
と書きます。
どのような配列で内部格納されているか知りたい方は、上記のコードを以下に修正して、表示させてみてください。
     $receiver->header( 'subject' , 'none' )
これで、subjectに関するデコードデータを配列の形で入手することができます。

同様にして、
     $receiver->header( 'from' , 'none' )
     $receiver->header( array('from',0,'name') , 'none' )
なども試してみましょう。
注意!
ヘッダー名は、すべて小文字で指定してください。
ループの最後はカレントポインタの移動です。
 $receiver->next();
これで、次のメールへと処理をうつします。現在のメール情報は消去されます。(QdmaiReceiverの内部的に消去されるだけであって、POPサーバーからは削除されません)

# [質問]non-objectエラー 『基本的な質問で失礼します。 上記参考にPHPスクリプト作ってみましたが、以下エラーとなってしまいます。 Fatal error:...』 (2011/01/31 15:19)

POP特有の処理(一般関数タイプ)

POP初期化の処理を前提とします。初期化(サーバー情報の設定)を行わないと、POPでメールを受信サーバーから取得することはできません。
今後、受信サーバーのことをPOPサーバーと記載します(この場合は同じものを示しています)。

メール件数の取得

echo qd_receive_mail( 'count' );
これで、POPサーバーに溜まっているメールの件数を取得します。

次のメールを処理する

何も指定しなければ、受信サーバーに溜まった最初のメールだけを処理します。
それ以降のメールの処理をするには、次のようにします。
qd_receive_mail( 'next' );

Directモード

Directモードは、引数にメール全文を与えることで、そのメールを解析するモードです。
一番ベーシックな働きをします。
POPモードやSTDINモードも、このDirectモードを呼び出して使っています。

使い方(一般関数タイプ)

qd_receive_mail( 'direct' , 'メールデータ全文' );
メールデータ全文は、本文だけなく、ヘッダーも含めた全文である必要があります。
SMTPに準拠した形式を受け付けます。

使い方(OOPタイプ)

QdmailReceiver::start( 'direct' , 'メールデータ全文' );
あとは共通の使い方と同じです。

モード共通の使用方法

QdmailReceiverは、2通りの使用方法があります。

一般関数タイプの初期設定

qd_receive_mail( モード , パラメータ , 文字コード );
stdinモードの例
qd_receive_mail( 'stdin' );

OOPタイプの初期設定

$receiver = QdmailReceiver::start( モード , パラメータ , 文字コード );
stdinモードの例
$receiver = QdmailReceiver::start( 'stdin' );

記事リスト

STDINモード

STDINモードとは

メールの受信サーバーから、パイプライン処理等で、PHPプログラムを直接起動し、標準入力(STDIN)経由でメールデータを受け渡しするモードです。
受信サーバーの種類によって設定が異なります。

使い方(一般関数タイプ)

標準入力から、メールの全文を入手するタイプですので、他のプログラムの標準出力をパイプにて受け渡しする必要があります。
また、受け取った側のPHPプログラムは、多くの場合、1行目に、動作元となるPHP本体プログラムを指定する必要があるでしょう。
指定は、ファイルの最初に #! と綴り、そのすぐ後からPHP本体へのパスを記述します。
下記の例は、さくらインターネットの場合です。-qは、quietモードであり、httpヘッダーを出力しない設定です。
#!/usr/local/php-5.2.6/bin/php-cgi -q
<?php

include_once('qdmail_receiver.php');

qd_receive_mail( 'stdin' );

?>
サーバーによって
#!/usr/local/php-5.2.6/bin/php-cgi -q
の部分は変更する必要があるでしょう。

よくわからない場合は、
#!/usr/bin/php
で、うまくいくことが多いとは思います*1
qd_receive_mail( 'stdin' );
と宣言すれば、後は他のモードの使い方と同じです。

使い方(OOPタイプ)

qd_receive_mail( 'stdin' );
の代わりに
QdmailReceiver::start( 'stdin' );
として下さい。

文字コードについて

QdmailReceiverは、すべての出力を、内部エンコーディングに変換して返します。
特定の文字コードにしたい場合は、以下のようにしてください。
utf-8で出力する場合の例)
qd_receive_mail( 'stdin' , 'utf-8' );
または
QdmailReceiver::start( 'stdin' , 'utf-8' );

*1 : 保証の限りでない

応用

Qdmailはメール受信サーバーを操作することができますが、次のようなことはどうでしょうか。
メールが到着したら、リアルタイムで処理する
メール到着をきっかけに、何らかのプログラムを走らせるわけですね。
これはPOPサーバーに定期的にアクセスするプログラムでは実現できません。
せいぜい、cron*2で、数分おきに実行させるのがやっとでしょう。

しかし、sendmail,qmail,PostFixなどのメールサーバーとQdmailReceiverを組み合わせることで実現することができます。
これが実現できれば、以下のようなサービスが簡単に提供できるでしょう。
  • 空メールによる簡単会員登録
  • ブログへのメール投稿
  • メール転送プログラム
  • 簡易メーリングリスト
  • リアルタイムSpamフィルター
  • WEBメール

*2 : unix系の定期実行デーモン

# SAMURAI 『この度はお世話になります。 STDINモードで メールの本文がとりだせないのですが・・ お助け頂けますと幸いです。 #!/us...』 (2008/11/08 6:01)

# spok 『 どんなエラーですか?』 (2008/11/09 20:03)

# SAM 『 お世話になります。 以下のようなかたちで、sendmailのaliasとして仕込んでいます。 (※function_sendM...』 (2008/11/09 20:35)

# spok 『 stdin関係のスクリプトは原因が特定しにくいのですが、まずは以下のサイトを参考に、パーミッションを再確認してみてください。そ...』 (2008/11/09 22:21)

# SAMURAI 『ご返信ありがとうございました。 パーミッションを確認しましたが、問題なさそうでした。 再度 //$body = $recei...』 (2008/11/09 24:59)

# spok 『>"554 5.3.0 unknown mailer error 255" >が戻って来ます。 というのは、どう「戻って」来ま...』 (2008/11/10 6:25)

# spok 『なぜこれをお伺いするかというと、本来 >"554 5.3.0 unknown mailer error 255" はSMTPサー...』 (2008/11/10 7:50)

# spok 『$all = $receiver->all(); とすると、$allには、ヘッダーも含めたメール全文が代入されます。 この$a...』 (2008/11/10 8:00)

# SAMU 『 お世話になります。 すみません、何度もお手数をおかけ致します。 $body = $receiver->all(); とし、...』 (2008/11/10 13:46)

# spok 『 ようやくなさっていることがわかりました。 おそらく、本文解析の部分でPHPがエラーを出しているため、このバウンスメールが返っ...』 (2008/11/10 24:13)

# SAMU 『 お世話になります、 何度もすみませんでした。 頂きましたサイトを参考に cat でエラーを はき出させたところ、下記がでまし...』 (2008/11/10 26:49)

# spok 『ご連絡ありがとうございました。 今後の更新時には、このエラー回避を組み込みたいと思います。』 (2008/11/11 7:54)

# SAMU 『こちらこそありがとうございました。 またVerUPの際には差し替えて活用させて頂きたいとおもいますので、 どうぞよろしくお願い致...』 (2008/11/11 14:07)

# SAMU 『前回はお世話になりました。SAMUと申します。 QdmailReceiverを利用させて頂き、gmailからのメールの処理をP...』 (2009/02/06 25:20)

# SAMU 『お世話になります。自己レスです。 ※前回の確認用スクリプトは一部記述が間違っておりました。 (正) $attach_files...』 (2009/02/08 20:58)

# Vert 『こう書きましたが、本文はうまく取得できるのですが、タイトル部分がうまく取得できません。環境はcakePHP1.2、console...』 (2009/03/27 13:28)

# wataru 『STDINモードで、添付画像が抽出できないものがあったので・・・ バージョンは、0.1.4aです GMailの場合、bound...』 (2010/12/15 17:43)

# wataru 『あっ、既に報告がありました<(_ _)>』 (2010/12/15 17:45)