▼ 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系の定期実行デーモン
- TB-URL http://hal456.net/qdmail_rec/023/tb/
# SAMURAI 2008年11月08日(土) 午前6時01分
この度はお世話になります。
STDINモードで
メールの本文がとりだせないのですが・・
お助け頂けますと幸いです。
#!/usr/bin/php -q
<?php
require_once('qdmail_receiver.php');
$receiver = QdmailReceiver::start( 'stdin' );
$text = $receiver->bodyAutoSelect();
?>
↑上記ではかならず エラーになるようです。
$text = $receiver->bodyAutoSelect();
# spok 2008年11月09日(日) 午後8時03分
どんなエラーですか?
# SAM 2008年11月09日(日) 午後8時35分
お世話になります。
以下のようなかたちで、sendmailのaliasとして仕込んでいます。
(※function_sendMail.phpはメール送信部の自作関数です。)
$body = $receiver->bodyAutoSelect();
でメール本文を取り出そうとすると、
"554 5.3.0 unknown mailer error 255"
が戻って来ます。
そこで
$body = $receiver->bodyAutoSelect();
を注釈にしたり、
$body = "テスト用ダミーの本文です";
を活かすと問題なく返信が返って来ました。
すみませんがご教授頂けますと幸いです。
======================================
#!/usr/bin/php -q
<?php
//標準入力から読み込み
require_once('qdmail_receiver.php');
$receiver = QdmailReceiver::start( 'stdin' );
$from = $receiver->header( array('from','mail') , 'none' );
$subject = $receiver->header( array('subject','name') , "無題" );
$header = serialize ( $receiver->header( 'ALL' ) );
$now = strtotime( $receiver->header( 'date') );
$body = $receiver->bodyAutoSelect();
//$body = "テスト用ダミーの本文です";
$subject = "TEST";
$to = $from ;
//メール返信
require_once("function_sendMail.php");
sendAttachMail( "support@test.com", $to , $subject, $body , $img_files );
?>
======================================
# spok 2008年11月09日(日) 午後10時21分
stdin関係のスクリプトは原因が特定しにくいのですが、まずは以下のサイトを参考に、パーミッションを再確認してみてください。それでもダメなら再度ご連絡下さい。
http://q.hatena.ne.jp/1167279986
http://d.hatena.ne.jp/makotoworld/mobile?date=20071105
http://www.cpa-lab.com/tech/0143
# SAMURAI 2008年11月09日(日) 深夜0時59分
ご返信ありがとうございました。
パーミッションを確認しましたが、問題なさそうでした。
再度
//$body = $receiver->bodyAutoSelect();
$body = "テスト用ダミーの本文です";
でテストを行ったところ、やはり正しく返信がきました。
そこで両方の注釈をとり、
$body = $receiver->bodyAutoSelect();
$body = "テスト用ダミーの本文です";
で行いますと、これは
"554 5.3.0 unknown mailer error 255"
が戻って来ます。
$body = $receiver->text();
も試してみてはいたのですが、、、これも同様でした。
そこで
$body = $receiver->header( array('subject','name') , "none" );
で、件名を返信の本文として返させたところ、こちらは無事かえってきましたので、
本文の取り出しのみがうまくいっていないようでした。
すみませんがよろしくお願い致します。
# spok 2008年11月10日(月) 午前6時25分
>"554 5.3.0 unknown mailer error 255"
>が戻って来ます。
というのは、どう「戻って」来ますでしょうか
$bodyの中にそのメッセージが入っていますか?
# spok 2008年11月10日(月) 午前7時50分
なぜこれをお伺いするかというと、本来
>"554 5.3.0 unknown mailer error 255"
はSMTPサーバーが出すエラーであり、QdmailReceiverは直接関係のないエラーメッセージだからです。
バウンスのエラーメッセージを解析している可能性はないですか?
また、$body本文にそのエラーメッセージが入っているとして、他のメッセージは一切入っていないですか?
# spok 2008年11月10日(月) 午前8時00分
$all = $receiver->all();
とすると、$allには、ヘッダーも含めたメール全文が代入されます。
この$allのtext(orHTML)部分と$bodyが異なっていれば、QdmailRecieverに原因があり、そうでなければ、それ以前の標準入出力部分で何らかのトラブルがあることが考えられます。
# SAMU 2008年11月10日(月) 午後1時46分
お世話になります。
すみません、何度もお手数をおかけ致します。
$body = $receiver->all();
とし、メール”本文にこれはメール本文です(を5つ)”をいう内容
のメールをautoreplay@test.com に送信しました。
autoreplay@test.comにはメールのaliasで
①の”/var/www/html/autoreplay.php”が受信するように仕掛けておりまして、
②の内容の本文のメールが無事送信元に届きました。
これを拝見すると、$receiver->all()では送信した本文の内容、
(これはメール本文です が5つ)
こちらから何かヒントになる箇所はございますでしょうか?
念のため、下3行の
//メール返信
require_once("function_sendMail.php");
sendAttachMail( "support@test.com", $to , $subject, $body , $img_files );
を削除しても③のエラー返信がありますので、こちらの関数は直接関係は無いものと思われました。
お手数ですがよろしくお願い致します。
①”/var/www/html/autoreplay.php”(↓OKのパターン)
======================================
#!/usr/bin/php -q
<?php
//標準入力から読み込み
require_once('qdmail_receiver.php');
$receiver = QdmailReceiver::start( 'stdin' );
$from = $receiver->header( array('from','mail') , 'none' );
$body = $receiver->all();
//$body = $receiver->bodyAutoSelect();
$subject = "自動返信";
$to = $from ;
//メール返信
require_once("function_sendMail.php");
sendAttachMail( "support@test.com", $to , $subject, $body , $img_files );
?>
======================================
② ①で返信されたメール本文
===================================================================
From testuser@test.com Mon Nov 10 13:21:07 2008
Received: from TESTPC (xxx.ne.jp [xxx.xxx.xxx.xxx])
by www.test.com (8.13.1/8.13.1) with ESMTP id mAA4L7Oq006763
for <autoreplay@test.com>; Mon, 10 Nov 2008 13:21:07 +0900
From: "TEST USER" <testuser@test.com>
To: <autoreplay@test.com>
Subject: This is TEST mail !!!
Date: Mon, 10 Nov 2008 13:19:06 +0900
Message-ID: <003f01c942eb$7889bbd0$0301a8c0@TESTPC0>
MIME-Version: 1.0
Content-Type: text/plain;
charset="iso-2022-jp"
Content-Transfer-Encoding: 7bit
X-Mailer: Microsoft Office Outlook 11
X-MIMEOLE: Produced By Microsoft MimeOLE V6.00.2900.3350
Thread-Index: AclCg1MX1suE9IjiQRmtloTrbNPK8g==
これはメール本文です
これはメール本文です
これはメール本文です
これはメール本文です
これはメール本文です
===================================================================
③ ①で$body = $receiver->bodyAutoSelect();
を活かした際に送信元に返信されるエラーメール
======================================
The original message was received at Sun, 9 Nov 2008 20:25:56 +0900 from [xxx.xxx.xxx.xxx]
----- The following addresses had permanent fatal errors ----- "|/usr/bin/php -q /var/www/html/autoreplay.php"
(reason: 255)
(expanded from: <autoreplay@test.com>)
----- Transcript of session follows -----
554 5.3.0 unknown mailer error 255
======================================
# spok 2008年11月10日(月) 深夜0時13分
ようやくなさっていることがわかりました。
おそらく、本文解析の部分でPHPがエラーを出しているため、このバウンスメールが返ってきているのでしょう。
お使いのサーバーに合わせて
http://www.cpa-lab.com/tech/0143#k143p5
を参考にしていただき、デバッグしてみていただけると
PHPが出しているエラーメッセージがわかるかと思います。
お手数ですが、当該エラーメッセージをお知らせ下さい。
# SAMU 2008年11月10日(月) 深夜2時49分
お世話になります、
何度もすみませんでした。
頂きましたサイトを参考に cat でエラーを
はき出させたところ、下記がでまして、原因はmb_check_encoding()が使えないことだと判りました・・・
そこで、PHPのバージョンを調べたところ4.3.9 でした。
mb_check_encoding()は4.4.3からということで・・・大変お手数おかけしました。
今は②のように回避し、文字化け対策は別途メール送信の関数の方で、
$body = mb_convert_encoding($body, "ISO-2022-JP" , "sjis");
などとしています。
今の環境のPHPは5へUP予定なので、その後は問題もないと思います。
ご対応頂きまして大変ありがとうございました。
①エラー
=====================================
PHP Fatal error: Call to undefined function: mb_check_encoding() in /var/www/html/qdmail_receiver.php on line 605
Fatal error: Call to undefined function: mb_check_encoding() in <b>/var/www/html/qdmail_receiver.php
on line 605
=====================================
②qdmail_receiver.php 605行目あたりと、640行目付近
=====================================
if (function_exists('mb_check_encoding')) {
if( mb_check_encoding( $body , $charset ) ){
$body = mb_convert_encoding( $body , $this->target_charset , $charset );
}
}
if (function_exists('mb_check_encoding')) {
if( mb_check_encoding( $_filename , $org_charset ) ){
$_filename = mb_convert_encoding(
$_filename ,
$this->target_charset,
$org_charset
);
}
}
# spok 2008年11月11日(火) 午前7時54分
ご連絡ありがとうございました。
今後の更新時には、このエラー回避を組み込みたいと思います。
# SAMU 2008年11月11日(火) 午後2時07分
こちらこそありがとうございました。
またVerUPの際には差し替えて活用させて頂きたいとおもいますので、
どうぞよろしくお願い致します。
# SAMU 2009年02月06日(金) 深夜1時20分
前回はお世話になりました。SAMUと申します。
QdmailReceiverを利用させて頂き、gmailからのメールの処理をPHPで行おうとしたとろ、なぜか添付ファイルがうまく処理されないようでした・・
そこで、
$attach_files = $receiver->attach();
echo "--->attach_num:".count($attach)."\n";
などで添付ファイル数を表示させますと、”0”が表示され、
どうも添付ファイル自体を認識していないようでした。
もし、これを回避するためのアイディアやお気づきの点がありましたら教えて頂けますと幸いです
どうぞよろしくお願い致します。
# SAMU 2009年02月08日(日) 午後8時58分
お世話になります。自己レスです。
※前回の確認用スクリプトは一部記述が間違っておりました。
(正)
$attach_files = $receiver->attach();
echo "--->attach_num:".count($attach_files);
なぜ$attach_files のカウントが添付ファイル付きでも”0”になるのか?をちょっと調べておりましたが、原因はGmailのboundary= が、
ダブルクォーテーションで囲まれておらず、
Content-Type: multipart/mixed; boundary=00c09f90f7297b2103046242157f
になっているためと考えられました。
そこで、
qdmail_receiver.phpの461行目あたりを
preg_match( '/boundary\s*=\s*"*([^"]+)"*/is' , $this->header['content-type'] , $matches );
と変更し、ダブルクォーテーションで囲まれていない場合も認識するように改変を加えたところ無事にGmailからの添付ファイルも処理できました。
Gmailの仕様がなぜダブルクォーテーション無しなのかと、
RFC的(?)にはどうなのか?
って言う点がまだちょっと調べ切れてはおりませんが、これはまたちょっとおいおい調査してみます。
# Vert 2009年03月27日(金) 午後1時28分
こう書きましたが、本文はうまく取得できるのですが、タイトル部分がうまく取得できません。環境はcakePHP1.2、consoleから起動しております。
$DECODE = QdmailReceiver::start('stdin', 'utf-8' );
$from = $DECODE -> header(array('from','mail'));
$data['Diary']['title']=$DECODE->header(array('subject','name'));
$message=$DECODE->bodyAutoSelect();
# wataru 2010年12月15日(水) 午後5時43分
STDINモードで、添付画像が抽出できないものがあったので・・・
バージョンは、0.1.4aです
GMailの場合、boundaryが「"」で囲まれていなくて、preg_matchでマッチしていませんでした。
正規表現を
「'/boundary\s*=\s*"([^"]+)"/is'」→「'/boundary\s*=\s*"?([^"]+)"?/is'」
と変更してうまく取得できました。
一応報告まで・・・
ところで、アップデートされないんですかねぇ・・・
# wataru 2010年12月15日(水) 午後5時45分
あっ、既に報告がありました<(_ _)>
# mikan 2012年03月23日(金) 午前8時35分
wataruさん助かりました。
Gmailの本文も取得が出来なかったのですが、
上記対応で取得出来るようになりました。ありがとうございます。