メールデータ解析用クラスの作成
Mail::mimeDecodeを毎回そのまま使用するとコードが煩雑になりますのでMail::mimeDecodeをラップしたメールデータ解析用クラスを作成します。
今回必要なメールデータは送信元アドレス、件名、本文、添付ファイルになりますので、メールヘッダ、本文、添付ファイルをそれぞれ取得するためのメソッドを作成することになります。
コンストラクタで標準入力で取得したメールデータを渡し、Mail::mimeDecodeを使用して解析後、本文や添付ファイルを取得し、それぞれをget~の形式で返却できるメソッドを作成しておきます。
/**
* コンストラクタ
*/
function MailDecoder($source)
{
$params = array();
$params['include_bodies'] = true; // ボディを解析する
$params['decode_bodies'] = true; // ボディをコード変換する
$params['decode_headers'] = true; // ヘッダをコード変換する
$this->_decoder = new Mail_mimeDecode($source);
$this->_structure = $this->_decoder->decode($params);
// ボディ部分を解析
$this->getMailData($this->_structure);
}
# 省略
/**
* 添付ファイルを返却する
*/
function getAttach(){
return $this->attachments;
}
今回のサンプルではマルチパートのメールを解析しますので、メール本文の解析はマルチパート内にある各パートの解析を行うことになります。
$structure->partsの各パート内の要素を参照してそれが何のデータになるのか解析します。
添付ファイルの場合はパートの中に「disposition」という要素があり、「attachment」という値になっていますのでこの要素で判断します。
通常の携帯メール本文は「ctype_primary」「ctype_secondary」の要素を参照してそれぞれ「text」「plain」となるパートに入っています。
その他、htmlメールやマルチパートの中にマルチパートがある場合にも対応できるように汎用的なメソッドを作成します。
/**
* メール本文部分の処理
*/
function getMailData($structure){
static $i = 0;
// マルチパートの場合
if (strtolower($structure->ctype_primary) == "multipart") {
// 各パートを解析する
foreach ($structure->parts as $part) {
// 添付ファイルの場合
if (isset($part->disposition) && $part->disposition=="attachment") {
//添付ファイル
$this->attachments[$i]['type'] = strtolower($part->ctype_primary)."/".strtolower($part->ctype_secondary);
$this->attachments[$i]['name'] = $part->ctype_parameters['name'];
$this->attachments[$i]['binary'] = $part->body;
$i++;
} else {
switch (strtolower($part->ctype_primary)) {
case "text": // テキスト本文
if ($part->ctype_secondary=="plain") {
$this->body_text = trim(mb_convert_encoding($part->body, 'UTF-8', 'auto'));
} else { // HTML本文
$this->body_html = trim(mb_convert_encoding($part->body, 'UTF-8', 'auto'));
}
break;
case "image": // マルチパート内に画像がある場合
$this->attachments[$i]['type'] = strtolower($part->ctype_primary)."/".strtolower($part->ctype_secondary);
$this->attachments[$i]['name'] = $part->ctype_parameters['name'];
$this->attachments[$i]['binary'] = $part->body;
$i++;
break;
case "multipart": //マルチパートの中にマルチパートがある場合は再帰的に自分自身を呼び出します
$this->getMailData($part);
break;
}
}
}
//テキスト本文のみのメール
} elseif (strtolower($structure->ctype_primary) == "text") {
$this->body_text = trim(mb_convert_encoding($structure->body, 'UTF-8', 'auto'));
}
}
上記メソッドのメールデータ解析イメージ図は次のようになります。

