メールにファイルを添付してサーバにアップロードするコード
最近、他の方が作ったモノの紹介とかの記事が多かったので、たまにはコードを交えた記事を書いてみる。
今回のネタは、メールに画像ファイルなどを添付して特定のメールアドレスに送ることで、サーバにファイルをアップロードする仕組みについてです。
今回使った環境は、Postfix&PHPですが、メールを受け取った時にスクリプトに渡す方法は、他のメールサーバでもあまり変わらないと思うので、流用はできるかと思います。
まず、メールを受け取るアドレスを用意する為、Unixのユーザを一つ作ります。
# useradd -m hoge # passwd hoge # su - hoge $ maildirmake Maildir $ vi .forward "| /usr/bin/php -q /home/hoge/mail.php >>/home/hoge/log 2>&1"
細かい事は色々省いてるので、環境に応じてPostfixの設定は適宜行って下さい。(バーチャルドメイン運用だったらローカルユーザに転送する設定とか、SMTP認証するなら認証パスワードの設定とか…。)<手抜き(^^;
ポイントは.forwardの設定で、これで届いたメールの内容がSTDINに入った状態でスクリプトに渡されるようになります。例の場合は、何かしらエラーがあった場合に後で確認できるように、logというファイルにリダイレクトしています。
で、メールの内容を渡される方のスクリプト(mail.php)を書いていきます。
<?php require_once 'Mail/mimeDecode.php'; // 受け取ったメール内容を変数に代入 if ( ($stdin=fopen("php://stdin",'r')) === true ){ while( !feof($stdin) ){ $mailtext .= fgets($stdin,4096); } } fclose($stdin); // デコード方法の指定 $params['include_bodies'] = true; $params['decode_bodies'] = true; $params['decode_headers'] = true; // デコード処理 $decoder = new Mail_mimeDecode($mailtext); // メールの構造を取得 $mail = $decoder->decode($params); // 添付ファイルの有無で処理を分岐 if ( count($mail->parts) > 1 ) { $body = $mail->parts[0]->body; $file = $mail->parts[1]->body; $filetype = $mail->parts[1]->ctype_secondary; //画像ファイルを所定の場所に保存 $id = md5(uniqid(rand(),1)); $image_filename = '/home/hoge/images/'.$id.'.'.$filetype; $fp = fopen($image_filename,"w"); fputs($fp,$file); fclose($fp); chmod($image_filename,0644); } else { // 添付ファイルが無い場合はbodyを取得するだけ $body = $mail->body; } // ヘッダ部分を取得して漢字コードを変換する $headers = $mail->headers; $from_text = mb_convert_encoding($headers['from'],'utf-8','ISO-2022-JP'); ereg("[0-9a-zA-Z_\.\-]+@[0-9a-zA-Z_\.\-]+",$from_text,$from); $from = $from[0]; $subject = mb_convert_encoding($headers['subject'],'utf-8','ISO-2022-JP'); $body = mb_convert_encoding($body,'utf-8','ISO-2022-JP'); // デバッグ出力 $output = ''; $output.= "差出人:".$from."\n"; $output.= "件名:".$subject."\n"; $output.= "保存先:".$image_filename."\n"; $output.= "本文:".$body."\n"; echo "$output"; ?>
これで、hogeというユーザ宛に添付ファイル付きのメールを送ると、images配下に適当にIDが振られたファイル名で保存されるはずです。
ここでは、受け取ったメールの内容に対して特に処理はせず、"デバッグ出力"のところで内容を出力してるだけですが、ヘッダの内容を使ってDBに格納するとか、折り返し送り元にメールを返信するとか処理を入れれば、色々とメールを使ったサービスが作れますね。(^-^)