画像が添付されたメールをPHPスクリプトで処理するメモ。
CakePHP(1.2.1.8004)のタスク機能にメール解析処理を実装してみます。
MIMEデータのデコードに、Zend Framework(1.7.5)のZend_Mime_Decodeを使います。
Index
すること、しないこと
- 画像が添付されたメールを解析し、画像をファイルに保存します。
- エンコード方式がBase64以外の添付ファイルは扱いません。
- 添付ファイルを保存するだけで、画像のフォーマットなどのチェックはしません。
サーバー環境
CentOS4で試しました。
SMTPサーバーはPostfixです。
PHPのバージョンは5。
PHPのSAPIはコマンドラインインターフェース(cli)です。
CakePHP コンソール :: CakePHPによる開発 :: マニュアル :: 1.2 Collection :: The Cookbookによると、
コンソールを使用する場合は、PHP のコマンドライン(CLI)版が利用可能な状態になっている必要があります。
とのことです。
準備
cake/console/cakeに記述されているphpを絶対パスに変更しました。
exec /usr/local/bin/php -q ${LIB}cake.php -working "${APP}" "$@"
メール受信スクリプト
実験的なものです。
いつもPEAR::Mail_mimeDecodeを使うのですが、Zend_Mime_Decodeを使ってみました。
(Zend_Mime_Decodeを正しく使用していないかも。)
SavePhotoMailタスクでは、どんなデータが取得できたかを見るためにログを出力しています。
-
<?php
-
class SavePhotoMailTask extends Shell
-
{
-
var $_saveDir;
-
-
function initialize()
-
{
-
Shell::initialize();
-
-
$this->_saveDir = TMP . 'image_files';
-
}
-
-
function execute()
-
{
-
-
$this->_makeSaveDir();
-
-
$message = '';
-
-
}
-
}
-
-
if (!$message) {
-
$this->log('メッセージを取得できませんでした');
-
return;
-
}
-
-
Zend_Mime_Decode::splitMessage($message,$headers,$body);
-
-
//$this->log($message);
-
$this->log($headers);
-
//$this->log($body);
-
-
$subject = mb_convert_encoding(mb_decode_mimeheader($headers['subject']),mb_internal_encoding(),mb_detect_order());
-
//$this->log($subject);
-
-
$content_type = Zend_Mime_Decode::splitHeaderField($headers['content-type']);
-
$this->log($content_type);
-
-
$struct = Zend_Mime_Decode::splitMessageStruct($message,$content_type['boundary']);
-
if ($struct) {
-
foreach ($struct as $s_index=>$content) {
-
continue;
-
}
-
-
$this->log('----------------------------------------------------------------');
-
$this->log($content['header']);
-
-
$is_attachment = false;
-
$cd = Zend_Mime_Decode::splitHeaderField($content['header']['content-disposition']);
-
$is_attachment = true;
-
}
-
}
-
-
$t = Zend_Mime_Decode::splitContentType($content['header']['content-type']);
-
$this->log('不明なcontent-type - ');
-
$this->log($content['header']);
-
continue;
-
}
-
-
// テキスト本文
-
if ($t['type'] == 'text/plain') {
-
$this->log($t['charset']);
-
}
-
else {
-
}
-
$this->log($body);
-
}
-
// 添付画像ファイル
-
$enc = 'base64';
-
if ($content['header']['content-transfer-encoding']) {
-
$e = Zend_Mime_Decode::splitHeaderField($content['header']['content-transfer-encoding']);
-
$enc = $e[0];
-
}
-
}
-
if ($enc == 'base64') {
-
$save_path = $this->_makeSavePath();
-
file_put_contents($save_path,$data);// ファイルを保存する。
-
$this->log('保存しました。' . $save_path);
-
-
// TODO: 画像ファイルをチェックする
-
}
-
else {
-
$this->log('保存ディレクトリが不正: ' . $this->_saveDir);
-
}
-
}
-
else {
-
$this->log('保存失敗.現在対応していないエンコード方式 - ');
-
$this->log($content['header']);
-
}
-
}
-
else if ($t['type'] == 'multipart/alternative') {
-
$this->log('現在対応していないcontent-type(htmlメール?) - ');
-
$this->log($content['header']);
-
}
-
else if ($t['type'] == 'application/octet-stream') {
-
$this->log('現在対応していないcontent-type - ');
-
$this->log($content['header']);
-
}
-
else {
-
$this->log('現在対応していないcontent-type - ');
-
$this->log($content['header']);
-
}
-
}
-
}
-
}
-
// テキスト本文(添付なし)
-
else if ($content_type[0] == 'text/plain') {
-
}
-
else {
-
}
-
$this->log($body);
-
}
-
else {
-
$this->log('不明なタイプ - ');
-
$this->log($headers);
-
$this->log($content_type);
-
$this->log('---------------');
-
}
-
}
-
-
function _makeSaveDir()
-
{
-
return true;
-
}
-
return false;
-
}
-
return true;
-
}
-
return false;
-
}
-
-
function _makeSavePath()
-
{
-
return false;
-
}
-
return $path;
-
}
-
}
Posftfix関連の設定
testusername@localhost.localdomain(※)というメールアドレス宛に画像を添付したメールを送信するとします。
testusername@localhost.localdomain宛のメールをCakePHPのタスク機能で処理するための記述を、/etc/aliasesに追加します。
testusername: "| /PATH/cake/console/cake -app /PATH/app photo_mail"
上の例では、cakeコマンドを絶対パスで指定しています。
また、「-app /PATH/app」のように、appディレクトリを絶対パスで指定しています。
/etc/aliasesを編集後、newaliasesコマンドを実行します。
以上で、メールに添付された画像をファイルに保存できました。
※testusername@localhost.localdomainは例で、存在しない仮のメールアドレスです。
リンク
- Linux/Postfixでバーチャルドメインを使う - Dream-Seed -wiki版-
- Postfix manual - aliases(5)
- おれ最前線ねっと - [Postfix]メール受信時にスクリプトを走らせる方法。
- ke-tai.org > Blog Archive > postfixで携帯メールを扱う際の注意点