ようこそゲストさん

QdmailReceiver Multibyte mail decoder & POP Client

サンプルコード

受信サーバーに溜まっている件名をすべて表示する。
 $server = array(
    'protocol'=>'pop3',
    'host'=>'pop.example.com',
    'user'=>'userID',
    'pass'=>'password',
 );

qd_receive_mail( 'start' , $server ); 
$max = qd_receive_mail( 'count' );
echo "<pre>";
for($i = 1 ; $i <= $max ; $i++){
    echo 'Mail Number: '.qd_receive_mail( 'pointer' ).' subject: ';
    echo qd_receive_mail( 'header' , array('subject','name') );
    echo "\r\n";
    qd_receive_mail( 'next' );
}
echo "</pre>";
die();
本文を取得するつもりがないのであれば、ヘッダのみ取得するようにするには次の文を'start'の次に挿入します。これで本文を受信サーバーから取得しないので若干高速になります。
qd_receive_mail( 'popHigh' , 0 ); 

タイトルに「未承諾広告」があるメールをサーバーから削除する

qd_receive_mail( 'start' , $server ); 
qd_receive_mail( 'popHigh' , 0 ); 
$max = qd_receive_mail( 'count' );
$target = array();
for($i = 1 ; $i <= $max ; $i++){
    $subject = qd_receive_mail( 'header' , array('subject','name') );
    if( false !== mb_strpos( $subject , '未承諾広告' ) ){
        $target[] = qd_receive_mail( 'pointer' );
    }
    qd_receive_mail( 'next' );
}
foreach( $target as $del_id ){
    qd_receive_mail( 'delete' , $del_id );
}
    qd_receive_mail( 'done' );
この例では、いったん$target変数に、該当のメール番号を溜めて、後でまとめて削除しています。
このようにしなくても、最初のif文の部分で、deleteしても大丈夫ですが、必ず最後にdoneコマンドを実行することを忘れないようにしてください。

#  非公開コメント   
  • TB-URL  http://hal456.net/qdmail_rec/08/tb/

基本タイプ(OOPタイプ)

メールヘッダーの取得

メール差出人の名前部分
$receiver には、初期設定またはPOPモード初期設定にて設定した、QdmailReceiverオブジェクトが入っているものとします。
$receiver->header( array( 'from' , 'name' ) );
メール差出人のメールアドレス
$receiver->header( array('from','mail') );
メール差出人関係の情報を一括取得
$receiver->header( array('from') ) ;
または
$receiver->header( 'from' );
でも可能
配列形式で、fromヘッダーから解析された情報が返されます。

他のヘッダーについても、同様に取り出すことができます。
  • 注意点!
メールヘッダーの「名称」は、すべて「小文字」で指定してください。
Subjectは×。subjectは○です。
メール件名
$receiver->header( array('subject','name') );
メール件名関係の情報を一括取得
$receiver->header( array('subject') );
または
$receiver->header( 'subject' );
でも可能
ヘッダー情報を全部配列で取得
$receiver->header( 'ALL' );

メール本文の取得

$receiver->bodyAutoSelect();
これで、htmlメールの場合は、html部分を取得し、テキストメールの場合は、テキスト部分を取得します。
テキスト部分は以下の形でも取得できます。
$receiver->text();
この形式は、テキスト部分を取得します。htmlメールであっても、代替テキストを取得します。
代替テキストがないhtmlメールの場合は、nullとなります。

html部分の取得。
$receiver->html();
テキストメールの場合は、nullとなります。
一般的には'bodyAutoSelect'コマンドを使用したほうがいいでしょう。

添付ファイルの取得

$attach = $receiver->attach();
以下の形で、添付ファイルの配列が$attachに格納されます。
(例)
array(
    0 => array(
         'value' => '添付ファイルの中身(デコード済みのバイナリ)',
         'finename' => 'ファイル名(日本語デコード済み)',
         'finename_safe' => 'urlencode済みのファイル名',
         'content-type' => 'image/jpg',
         'enc' => 'base64',
        ),
    1 => array(
         'value' => '添付ファイルの中身(デコード済みのバイナリ)',
         'finename' => 'ファイル名(日本語デコード済み)',
         'finename_safe' => 'urlencode済みのファイル名',
         'content-type' => 'image/jpg',
         'enc' => 'base64',
         'content-id' => '........',
    ),
);
'finename'は、マルチバイト(日本語)のファイル名にデコード済みですので、そのままwindowsなどで、そのファイル名で保存しようとすると不都合がでる場合もあります。その場合は、ご自分でsjisにエンコードしてからお使いください。
(もちろん、元のファイル名がアルファベットファイル名であれば、特段の問題はでないと思います。)
'finename_safe'は、ファイル名をurlencodeしていますので、このままファイル名として保存しても、大丈夫なようにしています(windows,unix,linux)。

添付ファイルを保存するサンプルコード
$attach = $receiver->attach();
foreach($attach as $att){
    $fp=fopen($att['filename_safe'],'w');
    fputs($fp,$att['value']);
    fclose($fp);
}

# テツ 2010年08月06日(金) 午後9時12分

添付ファイルですが、
メール本文がなく、添付ファイルがある場合、
$this->already_textプロパティがtrueにならないため、
[buildPart]メソッドがループし、同じ添付ファイルが複数追加されておりました。

# 太郎 2010年10月13日(水) 深夜1時15分

差出人のアドレス取得についてですが、display-name部分に@が入っていると動作がおかしくなります。
最近だとiPhoneのメールなんかで上記の形式の人が多いようです。

具体的には、Fromヘッダーが以下の場合、
From: "test123@example.com" <test@example.com>
$receiver->header(array('from','mail'))の動作として
test@example.com
を取得して欲しいのですが、実際には
"test123@example.com"
が返ってきます。
(後半の<>内を取得して欲しいのに前半の""内を取得してしまっている、かつダブルクォーテーションも返り値に含まれている)

対策として、750行目の正規表現を
'/<?([^<>\s]+@[^<>\s]+\.[^<>\s]+)>?/is'
から
'/<?([^<>\s]+@[^<>\s]+\.[^<>\s]+)>?[^<]*?$/is'
に変更することで、期待通りに動作しました。

# anon 2012年11月05日(月) 午後0時01分

大変おせわになっています。
iPhoneの標準のメーラーから画像を添付して送ると、
$att['filename']
$att['filename_safe']
が存在しません。あと、
$att['value']
で添付ファイルのデータを取得できないです。恐縮ですが、何かご助言を頂けないでしょうか...。

# hide 2017年04月28日(金) 午前11時05分

お世話になっております。
Gmail等で添付ファイルがあると本文ごとエンコードされてしまうため、本文取り出しができません(本文なし扱いとなる)。
本文も添付ファイルも取得する方法はありますでしょうか。


#  非公開コメント   
  • TB-URL  http://hal456.net/qdmail_rec/06/tb/

一般関数タイプ

メールヘッダーの取得

メール差出人の名前部分
echo qd_receive_mail( 'header' , array('from','name') );
メール差出人のメールアドレス
echo qd_receive_mail( 'header' , array('from','mail') );
メール差出人関係の情報を一括取得
$from = qd_receive_mail( 'header' , array('from') ) ;
または
$from = qd_receive_mail( 'header' , 'from' );
でも可能
$from には、配列形式で、fromヘッダーから解析された情報が代入されます。

他のヘッダーについても、同様に取り出すことができます。
  • 注意点!
メールヘッダーの「名称」は、すべて「小文字」で指定してください。
Subjectは×。subjectは○です。
メール件名
$subject = qd_receive_mail( 'header' , array('subject','name') );
メール件名関係の情報を一括取得
$subject = qd_receive_mail( 'header' , array('subject') );
または
$subject = qd_receive_mail( 'header' , 'subject' );
でも可能
ヘッダー情報を全部配列で取得
$header = qd_receive_mail( 'header' , 'ALL' );

メール本文の取得

$body = qd_receive_mail( 'body' );
これで、htmlメールの場合は、html部分を取得し、テキストメールの場合は、テキスト部分を取得します。
テキスト部分は以下の形でも取得できます。
$body = qd_receive_mail( 'text' );
この形式は、テキスト部分を取得します。htmlメールであっても、代替テキストを取得します。
代替テキストがないhtmlメールの場合は、nullとなります。

html部分の取得。
$body = qd_receive_mail( 'html' );
テキストメールの場合は、nullとなります。
一般的には'body'コマンドを使用したほうがいいでしょう。

添付ファイルの取得

$attach = qd_receive_mail( 'attach' );
以下の形で、添付ファイルの配列が$attachに格納されます。
(例)
array(
    0 => array(
         'value' => '添付ファイルの中身(デコード済みのバイナリ)',
         'finename' => 'ファイル名(日本語デコード済み)',
         'finename_safe' => 'urlencode済みのファイル名',
         'content-type' => 'image/jpg',
         'enc' => 'base64',
        ),
    1 => array(
         'value' => '添付ファイルの中身(デコード済みのバイナリ)',
         'finename' => 'ファイル名(日本語デコード済み)',
         'finename_safe' => 'urlencode済みのファイル名',
         'content-type' => 'image/jpg',
         'enc' => 'base64',
         'content-id' => '........',
    ),
);
'finename'は、マルチバイト(日本語)のファイル名にデコード済みですので、そのままwindowsなどで、そのファイル名で保存しようとすると不都合がでる場合もあります。その場合は、ご自分でsjisにエンコードしてからお使いください。
(もちろん、元のファイル名がアルファベットファイル名であれば、特段の問題はでないと思います。)
'finename_safe'は、ファイル名をurlencodeしていますので、このままファイル名として保存しても、大丈夫なようにしています(windows,unix,linux)。

添付ファイルを保存するサンプルコード
$attach = qd_receive_mail( 'attach' );
foreach($attach as $att){
    $fp=fopen($att['filename_safe'],'w');
    fputs($fp,$att['value']);
    fclose($fp);
}

記事リスト

# craran 2009年08月31日(月) 午後1時41分

iPhoneからのメールを処理してみたのですが、添付ファイルの取得が出来ないようです。

ヘッダーを見てみると添付ファイルのパートが「Content-Disposition: inline;」となっているのですが、ここら辺が原因なのでしょうか。。。

# msa.uccky 2009年11月17日(火) 午後5時30分

multipartのメールが解析できないケースがありました。
QdDecodeBase->decodeBody()の以下を修正して対応。

preg_match( '/boundary\s*=\s*([^"]+)/is' , $this->header['content-type'] , $matches );

preg_match( '/boundary\s*=\s*"?([^"]+)"?/is' , $this->header['content-type'] , $matches );

# pws 2010年11月26日(金) 午後5時06分

msa.uccky 氏の修正に関連してfunction buildPart() 内の正規表現も修正が必要なようです。

preg_match( '/boundary\s*=\s*"([^"]+)"/is' , $header['content-type'] , $matches );

preg_match( '/boundary\s*=\s*"?([^"]+)"?/is' , $header['content-type'] , $matches );

# ひでまん 2011年09月16日(金) 午後3時52分

ほんとですね。修正しないと添付ファイル取れないみたいです。

# ひでまん 2011年09月16日(金) 午後4時58分

添付ファイルの保存方法
foreach($attach as $att){
$fp = fopen($att['filename_safe'],'rb');
$contents = fread($fp, filesize($att['filename_safe']));
file_put_contents('/home/acount/www/dirdir/app/tmp/hoge3.jpg', $contents);
fclose($fp);
}

これでうまくいけました。

# ひでまん 2011年09月16日(金) 午後6時02分

何度もすいません。
foreach($attach as $v){
file_put_contents('/home/acount/www/hogera/app/tmp/'.time().'.jpg', $v['value']);
}

でいけます。
上記の添付ファイルの保存方法はうまくいかないかもしれません。

# mikan 2012年04月09日(月) 午前9時20分

文中の finename → filename が正しいですね

# ひでまん 2012年06月08日(金) 午後1時20分

またはまったので修正版アップしておきました。
以下の物をそのまま使えばiphone でも画像を取得できますよ。
http://www.hideblog.net/nikkis/show/275/

# Ayase 2017年08月04日(金) 午後3時28分

<img>に直接base64で画像が埋め込まれている場合、挙動がおかしくなるようです。


#  非公開コメント   
  • TB-URL  http://hal456.net/qdmail_rec/04/tb/

ヘッダー情報の説明

ヘッダー情報は、以下のような形で内部保存されています。
$this->header = array(
    'ヘッダー名(e.g Cc)'=>array(
        0 => array(
             'mail' => 'mail_0@example.com',
             'name' => 'お名前0',
             'mime' => '=?iso2022-jp?B?......?=',
        ),
        1 => array(
             'mail' => 'mail_1@example.com',
             'name' => 'お名前1',
             'mime' => '=?iso2022-jp?B?......?=',
        ),

    'ヘッダー名(e.g. subject)'=>array(
          'name' => '件名',
          'mime' => '=?iso2022-jp?B?......?=',
    ),
);

#  非公開コメント   
  • TB-URL  http://hal456.net/qdmail_rec/05/tb/

既読・未読の管理とUID機能の解説

一般的に使われているPOPプロトコルには、既読・未読の管理機能はありません。
一般的にメーラー*1は、そのソフトウエア*2で独自に既読・未読管理を行っています。

QdmailReceiverで既読・未読管理を行うには?

POPサーバーの多くは、UIDという機能を有しています。
これは、「受信サーバーが付けたメール番号」です。
その形式は様々です。
例)
プロバイダorレンタルサーバー名UIDの形式
so-net数字5桁
ドリームネット数字n桁.数字n桁.サーバーNumber?
ロリポップ数字n桁.数字n桁.サーバーNumber.lolipop.jp
さくらインターネットUID数字n桁-数字n桁

このUIDは、セッション(プロセス)が異なっても、その受信サーバー内では一意に保たれているのが通常です*3

UIDは、QdmailReceiverの場合、「popuid」という名称のヘッダー情報として格納します*4
これをデータベースなり、ファイル、セッション変数等に格納することで、既読・未読の管理をすることができるでしょう。

Pointer number は既読・未読管理に不向き

QdmailReceiver (及びPOPの仕様)では$receiver->pointer();*5)機能で、メールの番号付けを行います。
これは、メールを受信順に1から番号付けしてくれるものですが、しかし、これは当該セッション(プロセス)内だけで有効なものです。
メールの取得や削除には、Pointer Numberを使いますが、そのPOPプロセス内*6だけ、ということは意識しておいてください。
継続性範囲サポート
PointerNumberPOPプロセス内そのサーバー内だけどのPOPサーバーもOK
UID(popuid)削除するまでは
一意に保たれる
そのサーバー内だけたまにサポートしてない
サーバーもあるようだ*7

UIDとPointerNumberの変換

UID → PointerNumber(ポインタは移動しません。)
$receiver -> uidToPointer( uid );
または、
qd_receive_mail( 'uidToPointer' , uid );
 PointerNumber → UID (ポインタが移動するので注意してください。)
$receiver -> pointer( PointerNumber );
$receiver -> header( 'popuid' );
または、

qd_receive_mail( 'pointer' , PointerNumber );
qd_receive_mail( 'popuid' );
とすることで、UIDとPOINTERの変換ができます。

*1 : OutlookExpressをはじめBecky!や秀丸メール、その他ほとんどすべてのメーラー

*2 : クライアント

*3 : メッセージ本文が全く同じ場合は、同じUIDになってしまうサーバーもあることはあるようだ。POPのプロトコル上は、メッセージが同じであれば同じUIDを返すことになっているけれども、多くのサーバーはそれを拡張し、同じメッセージであっても異なるUIDを返す場合が多いと思う

*4 : UIDをサポートしないサーバーのため、格納しないように設定することもできる。

*5 : 又は、qd_receive_mail('pointer', ...

*6 : サーバーやPHPのプロセスではなく、POPのプロセス

*7 : お目にかかったことはないけれど。一応この機能はPOP3プロトコルのオプション扱い

# すいません。 2012年09月19日(水) 深夜4時51分

もう開発されてないようなのですが、お伺いしたい事があります。
ポインターの操作でuidToPointerという記述がありますが、
呼び出してみると、
PHP Fatal error: Call to undefined method QdPop::uidToPointer()
と言われます。
バージョンは0.1.4.alphaです。
何か分かれば教えて頂きたいのですが。。


#  非公開コメント   
  • TB-URL  http://hal456.net/qdmail_rec/07/tb/

POP初期設定

POPサーバー(受信サーバー)にアクセスするための初期設定が必要です。

一般関数タイプの例)


 include_once('qdmail_receiver.php');

 $server = array(
    'protocol'=>'pop3',
    'host'=>'pop.example.com',
    'user'=>'user-id',
    'pass'=>'password',
 );

 qd_receive_mail( 'start' , $server ); 

ご自分でお使いの受信サーバーを設定してください。
'protocol'=>'pop3',
はPOPモードにするためのおまじないですので、このまま、配列の一番最初に置いておいてください。
配列のキーは、大文字小文字を区別しませんが、将来のことを考えて小文字を推奨します。
qd_receive_mailが、一般関数タイプの関数です。オブジェクト指向ではありません。
以下のように使います。
qd_receive_mail( 'コマンド' , $server )
一度、
qd_receive_mail( 'start' , $server )
で初期化すると、QdmailReceiverは、POPと接続し、状態を覚えていますので、次回以降の操作で'start'コマンドを送ることはありません。
文字コードについて
QdmailReceiverは、返り値をすべてmb_internal_encoding()で設定された文字コードに変換して渡します。

返り値を特定の文字コードで受け取りたい場合は、次のように指定してください。
qd_receive_mail( 'start' , $server , '文字コード')
以下は、utf-8を指定した場合です。
 $server = array(
    'protocol'=>'pop3',
    'host'=>'pop.example.com',
    'user'=>'user-id',
    'pass'=>'password',
 );

 qd_receive_mail( 'start' , $server , 'utf-8' ); 

オブジェクト指向モードでの初期化

 $server = array(
    'protocol'=>'pop3',
    'host'=>'pop.example.com',
    'user'=>'user-id',
    'pass'=>'password',
 );

$receiver = QdmailReceiver::start( 'pop' , $server);

'pop'は、POPモードにするためのおまじないです。
$receiverにはQdmailReceiverのオブジェクトが代入されます。
newを使わずに、オブジェクトを取得します。このような取得の仕方がわからない方もいるかも知れませんが、& new するのと同じと思ってください。
newで、QdmailReceiverオブジェクトを取得することもできるのですが、3つのモードの振り分け処理を自分でしなくてはならないので、上記の方法をお薦めします。

#  非公開コメント   
  • TB-URL  http://hal456.net/qdmail_rec/03/tb/
  • 基本モード(OOPモード) QdmailReceiver Multibyte mail decoder & POP Client spok
    初期設定は必ず行ってください。OOPでいける方はそれなりにPHPに習熟した方と思いますので、例題の解説として進めます。$receiver には、初期化されたQdmailReceiverオブジェクトが代入されているものとします。ご自分の(安全な)受信サーバー...
  • POP特有の処理(OOPタイプ) QdmailReceiver Multibyte mail decoder & POP Client spok
    初期設定は必ず行ってください。OOPでいける方はそれなりにPHPに習熟した方と思いますので、例題の解説として進めます。$receiver には、初期化されたQdmailReceiverオブジェクトが代入されているものとします。ご自分の(安全な)受信サーバー...

POPモード

POPモードとは

POPモードは、メール受信サーバーにPOP接続し、サーバーに蓄積されているメールをダウンロードして解析するプログラムです。

#  非公開コメント   
  • TB-URL  http://hal456.net/qdmail_rec/09/tb/