Your browser (Internet Explorer 6) is out of date. It has known security flaws and may not display all features of this and other websites. Learn how to update your browser.
X
Post

phpでHTMLメールを生成してみた

phpのネタです。


HTMLメールの送信機能を作る必要が出てきて、それを作ってました。
要件は次の通り。

・HTMLメール非対応のメールクライアントの場合はテキストメールに切り換える
・HTML中に画像を埋め込む

既存のライブラリ探せばよかったのかもしれないけど、
せっかくなので(?)自前で頑張ってみる事にしました。


まずは一つ目。

multipart/alternative ‐ 通信用語の基礎知識

調べたところ、形式としてmultipart/alternativeを指定すればよいらしい。

How do I send a multipart email (both HTML and plain text)? – PHP FAQ – Tek-Tips

ちょうどいいサンプルコードもありました。
ヘッダでコンテンツの種類にmultipart/alternativeを指定し、
本文はあらかじめ決められたバウンダリ文字列でパートを区切ればよいです。

これを元に日本語に対応するよう修正。
これで一つ目の条件はクリアしました。


続いて2つ目の条件。
最初は外部サーバにファイルを設置し、
imgタグでそれを呼び出せばいいのではないかと思いました。
それでうまくケースもありましたが、どうもドコモの携帯だとうまく表示されない。

デコメールタグ一覧 | サービス・機能 | NTTドコモ

確認してみたら、docomoだけimgタグでインターネット接続する事ができないらしい。
セキュリティ的には一理ある対応だし、
そもそもそういう仕様ならこちらにはどうにもできないので
メール中にファイルを埋め込む方法を模索してみる事にしました。

ウノウラボ by Zynga Japan: さくらインターネットで添付画像付きのマルチパートメールをPHPで送ってみる

探してみたら今度はこのようなサンプルが見つかりました。
こちらはmultipart/relatedを指定し、
添付ファイルをHTMLテキスト中で呼び出し可能なようにするようです。

これもこちらのサンプルコードをベースにする事でうまく実現する事ができました。

……が、今度はalternativeでプレーンテキストを入れる事ができなくなってしまいました。
何とかalternativeとrelatedを両立させる事ができないものか調べてみて……
また、実際のメールの構造をチェックなどして、ようやく答えが見つかりました。

multipart/related ‐ 通信用語の基礎知識

この2つはネストができるらしい。
それぞれのバウンダリ文字列を違うものにすれば区切り位置を正しく認識するようです。

まとめると、こういう書き方をすればいけるようでした。

// 画像ファイルのデータを取得
$img = file_get_contents(ファイルのパス);
$img_data = chunk_split(base64_encode($img));

// バウンダリ文字列を生成。実際はランダム生成する
$mime_boundary_alt = "(alternative用文字列)";
$mime_boundary_related = "(related用文字列)";
$mime_boundary_related_header = chr(34) . $mime_boundary_related . chr(34);

$headers = "From: " . $from . "\n" .
           "MIME-Version: 1.0\n" .
           "Content-Type: multipart/related;\n" .
           "boundary=" . $mime_boundary_related_header;

// 本文を生成する。
$body =<<<EOF
--{$mime_boundary_related}
Content-Type: multipart/alternative; boundary="{$mime_boundary}"

--{$mime_boundary}
Content-Type: text/plain; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit

(プレーンテキスト)

--{$mime_boundary}
Content-Type: text/html; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit

(HTMLテキスト。下の添付画像を取ってくる時は<img src="cid:id_1" />と書く)

--{$mime_boundary}--

--{$mime_boundary_related}
Content-Type: image/jpeg; name="images000.jpg"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="images000.jpg"
Content-ID: <id_1>

{$img_data}

--{$mime_boundary_related}--

EOF;

// メール送信
mb_send_mail($to, $subject, $body, $headers);


これにより、目的の形式でメールを送信する事ができました。
alternativeでプレーンテキストとHTMLテキストの判定が可能で、
画像の埋め込みにも成功しています。


こ、ここまでたどり着くのがめんどくさかった……
けどまあ、メールの仕様について勉強するいい機会になりました。

TrackBack URL :

Leave a comment  

name

email

website

Submit comment