コード

●メール転送
さくらサーバーの「.mailfilter」
/MailBox/メールアドレス/内、パーミッション600、文字コードEUC、改行LF
to "| /home/USERID/www/PHPプログラム名.php"
exit

PLESKサーバーのQMAIL
/var/qmail/mailnames/ドメイン名/メールアドレス/.qmail、文字コードEUC、改行LF
| /var/www/vhosts/ドメイン名/httpdocs/PHPプログラム名.php


●コンポーネント
<?php /* -*-java-*- */
//require_once('Mail/mimeDecode.php');
App::import('Vendor', 'mimeDecode', array('file' => 'Mail/mimeDecode.php'));

/****************
 * http://d.hatena.ne.jp/ya--mada/20080415/1208318475
 * http://www.hideblog.net/nikkis/show/123
 *****************/


/**
 * 受信メールのヘッダの値やマルチパートの本文、ファイルを取得するクラス
 *  
 * @author	k5959k+yamada@gmail.com
 * @create	2008-03-11
 * @package	ya--mada
 */
//class ReceiptMailDecoder {
class MailparseComponent extends Object {
	/**
	 * 本文
	 * 
	 * @var array array('text'=>{text}, 'html'=>{html} )
	 */
	var $body = array( 'text'=> null , 'html'=> null );

	/**
	 * 添付ファイル
	 * 
	 * @var array array[] = array('mime_type'=>{mime_type},
	 *                            'file_name'=>{file_name},
	 *                            'binary'=>{binary} )
	 */
	var $attachments = array();

	/**
	 * Mail_mimeDecode オブジェクト
	 * 
	 * @var object
	 */
	var $_decoder;

	/**
	 * constractor ReceiptMailDecoder class.
	 * 
	 * @param string $raw_mail 受信したそのままメール文字列
	 */
	//function ReceiptMailDecoder ( &$raw_mail )
	function ReceiptMailDecoder ()
	//function ReceiptMailDecoder ($source=null)
	{
		//if ( !is_null( $raw_mail ) ) {
		//	$this->_decode( $raw_mail );
		//}

		$source = file_get_contents("php://stdin");
		if (!is_null($source)) {
			$this->_decode($source);
			return 'parse';
		} else {
			return 'notparse';
		}
	}

	/**
	 * このクラスを使用する際の初期化
	 * 
	 * @access public
	 * @param  array
	 */
	function init() {

	}

	/**
	 * 生メールをデコードしてプロパティに代入する
	 * 
	 * @access public
	 * @param  string $raw_mail 受信したそのままメール文字列
	 */
	function _decode ( &$raw_mail ) {
		if ( is_null($raw_mail) ) {
			return false;
		}

		$params = array();
		$params['include_bodies'] = true;
		$params['decode_bodies']  = true;
		$params['decode_heders']  = true;
		//$params['input'] = $raw_mail."\n";

		/*
		 * Mail_mime::Decode をつかって分解解析する
		 * マルチパートの場合は、本文と添付に分けます。
		 */
		$this->_decoder =& new Mail_mimeDecode( $raw_mail."\n" );
		$this->_decoder = $this->_decoder->decode($params);

		$this->_decodeMultiPart($this->_decoder);
	}

	/**
	 * 指定ヘッダの取得
	 * 
	 * @access public
	 * @param  string  $header_name
	 * @return string
	 */
	function getRawHeader ( $header_name ) {
		return isset($this->_decoder->headers["$header_name"])
			? $this->_decoder->headers["$header_name"]
			: null;
	}

	/**
	 * ヘッダがmimeエンコードされている場合はデコードして取得する。
	 * 
	 * @todo   携帯絵文字には対応していない。
	 * @access public
	 * @param  string $header_name
	 * @return string
	 */
	function getDecodedHeader( $header_name ) {
		return mb_decode_mimeheader($this->getRawHeader( $header_name ));
	}

	/**
	 * 指定ヘッダ内のE-mailアドレスだけを抜き出して返す
	 * 
	 * @access public
	 * @param  string $header_name
	 * @return string
	 * @see extractionEmails()
	 */
	function getHeaderAddresses ( $header_name ) {
		return $this->extractionEmails($this->getRawHeader( $header_name ));
	}

	/**
	 * STATIC
	 * 文字列の中からemailアドレスっぽいものだけを抽出して返します。
	 * emailアドレスっぽいものの正規表現をあらためた
	 * see. http://red.ribbon.to/~php/memo_003.php
	 * 
	 * @access public
	 * @param  string $raw_string
	 * @return string $mail_addresses メールアドレスっぽいものを複数あれば,(カンマ)区切りで
	 */
	function extractionEmails( $raw_string ) {
		/*
		 * 旧emailアドレスっぽい正規表現
		 * see. http://www.tt.rim.or.jp/~canada/comp/cgi/tech/mailaddrmatch/
		 *
		$email_regex_pattern = "/[\x01-\x7F]+@(([-a-z0-9]+\.)*[a-z]+|\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\])/";
		*/

		/*
		 * 新emailアドレスっぽい正規表現
		 * see. http://red.ribbon.to/~php/memo_003.php
		 */
		$email_regex_pattern = '/(?:[^(\040)<>@,;:".\\\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\\\[\]\000-\037\x80-\xff])|"[^\\\\\x80-\xff\n\015"]*(?:\\\\[^\x80-\xff][^\\\\\x80-\xff\n\015"]*)*")(?:\.(?:[^(\040)<>@,;:".\\\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\\\[\]\000-\037\x80-\xff])|"[^\\\\\x80-\xff\n\015"]*(?:\\\\[^\x80-\xff][^\\\\\x80-\xff\n\015"]*)*"))*@(?:[^(\040)<>@,;:".\\\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\\\x80-\xff\n\015\[\]]|\\\\[^\x80-\xff])*\])(?:\.(?:[^(\040)<>@,;:".\\\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\\\x80-\xff\n\015\[\]]|\\\\[^\x80-\xff])*\]))*/';

		if ( preg_match_all( $email_regex_pattern, $raw_string, $matches, PREG_PATTERN_ORDER ) ) {
			if ( isset($matches[0]) ) {
				return implode( ",", $matches[0] );
			}
		}

		return null;
	}

	/**
	 * デコードした本文の取得
	 * 
	 * $this->body['text']; // テキスト形式の本文
	 * $this->body['html']; // html形式の本文
	 */

	/**
	 * 添付ファイルの取得
	 * 
	 * $this->attachments[$i]['mime_type']; // MimeType
	 * $this->attachments[$i]['file_name']; // ファイル名
	 * $this->attachments[$i]['binary'];    // ファイル本体
	 */

	/**
	 * メール本文部分の処理
	 * マルチパートの場合は、その処理もしますよ。
	 * 
	 * @access private
	 */
	function _decodeMultiPart(&$decoder) {

		// マルチパートの場合 それぞれがparts配列内に再配置されているので
		// 再帰的に処理をする。
		if ( !empty($decoder->parts) ) {
			foreach ( $decoder->parts as $part ) {
				$this->_decodeMultiPart($part);
			}
		} else {

			if ( !empty($decoder->body) ) {
				// 本文 (text or html )
				if ( 'text' === strToLower($decoder->ctype_primary) ) {
					if ( 'plain' === strToLower($decoder->ctype_secondary) ) {
						$this->body['text'] =& $decoder->body;
					}
					elseif ( 'html' === strToLower($decoder->ctype_secondary) ) {
						$this->body['html'] =& $decoder->body;
					}
					// その他のtext系マルチパート
					else {
						$this->attachments[] = array( 'mime_type'=>$decoder->ctype_primary.'/'.$decoder->ctype_secondary,'file_name'=>$decoder->ctype_parameters['name'],'binary'=>&$decoder->body);
					}
				}
				// その他
				else {
					$this->attachments[] = array( 'mime_type'=>$decoder->ctype_primary.'/'.$decoder->ctype_secondary,'file_name'=>$decoder->ctype_parameters['name'],'binary'=>&$decoder->body);
				}
			}
		}
	}

	/**
	 * メールが添付ファイルつきか調べる
	 * 
	 * @access private
	 * @return bool      添付付きなら true 無ければ false を返す
	 */
	function isMultiPart() {
		return (count($this->attachments) > 0) ? true : false;
	}

	/**
	 * 添付ファイルの数を数える
	 * 
	 * @access private
	 * @return int
	 */
	function getNumOfAttach() {
		return count($this->attachments);
	}

	/**
	 * Toヘッダからアドレスのみを取得する
	 * 
	 * @access public
	 * @return string toアドレス 複数あればカンマ区切りで返す
	 * @see getHeaderAddresses(), extractionEmails()
	 */
	function getToAddr() {
		return $this->getHeaderAddresses( 'to' );
	}

	/**
	 * Fromヘッダからアドレスのみを取得する
	 * 
	 * @access public
	 * @return string Fromアドレス 複数あればカンマ区切りで返す
	 * @see getHeaderAddresses(), extractionEmails()
	 */
	function getFromAddr () {
		return $this->getHeaderAddresses( 'from' );
	}

	/**
	 * 添付ファイルを保存する
	 * 
	 * @todo   Mail_mimeDecode はマルチパートのbase64decodeの面倒はみない?
	 * @access public
	 * @param  int
	 * @param  string $str_path
	 * @return bool  成功なら true 失敗なら false を返す
	 */
	function saveAttachFile ( $index, $str_path ) {
		if ( !file_exists($str_path) ) {
			if ( !is_writable(dirname($str_path)) ) {
				return false;
			}
		} else {
			if ( !is_writable($str_path) ) {
				return false;
			}
		}

		if ( !isset($this->attachments[$index]) ) {
			return false;
		}

		if ( $fp=fopen($str_path, "wb") ) {
			fwrite($fp, $this->attachments[$index]['binary'] );
			fclose($fp);
			return true;
		}

		return false;
	}

}
?>


●コントローラ
(略)
	var $components = array('Mailparse');

(略)
	mb_language('ja');
	mb_internal_encoding('sjis');

	$this->Mailparse->ReceiptMailDecoder();

	$from = '';
	$subject = '';
	$body = '';

	//$to = $this->Mailparse->getToAddr();
	$from = $this->Mailparse->getFromAddr();
	$subject = $this->__convert($this->Mailparse->getDecodedHeader('subject'));
	$body = $this->__convert($this->Mailparse->body['text']);

	$filecount = $this->Mailparse->getNumOfAttach();
	if($this->Mailparse->isMultiPart() && $filecount < 5) {
		$this->Mailparse->saveAttachFile(0, $fileup_dir.$filename);
	}
(略)

	function __convert($str) {
		if (function_exists('mb_convert_encoding')) {
			//return mb_convert_encoding($str, "UTF-8", "JIS,SJIS");
			return mb_convert_encoding($str, 'UTF-8', 'auto');
		}
		return true;
	}

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Wiki内検索

メニューバーA

ここは自由に編集できるエリアです。

管理人/副管理人のみ編集できます