PHPによるメール送信でつまづいたときの設定アレコレ

400px-PHP-logo.svg

こんにちは、永橋です。

今回は先週のPHPによるHTML解析に続き、PHPを使ってメールを送信する方法を紹介します。

今回の環境はPHP ver.5.2以上、Outbound Port25 Blockingがされていないことが条件です。Outbound Port25 Blockingは自宅サーバーなどの特殊な環境でなければ引っかかることは無いと思います。

PHPでは標準でメールを送信する機能、mail関数が備わっています。他にも、mb_send_mail関数というマルチバイトに対応したものや、PHPMailerなどのライブラリを使う手法もあります。今回は標準機能のmail関数を使用して行ってみようと思います。

今回参考にしたサイトはこちらです。

PHP で添付ファイル付きメールを送信する関数 パソコン鳥のブログ/ウェブリブログ

このサイトにある、send_attached_mail.incのテキストをコピーし、send_attached_mail.incというファイルを作成し、サーバーにアップロードします。これで一応メールを送ることができるようになります。

この時点でメールを送る場合には、PHPスクリプトを以下のように記述します。


<?php
require "send_attached_mail.inc";
SendAttachedMail( "from@example.com" , "to@example.com" , "題名はテスト" , "本文1行目\n本文2行目" , null );
?>

これでfrom@example.comからto@example.comへメールを送ることができます。

しかし、実はこのままの状態でタイトルに半角カナ文字などを入れて送信すると、????などの文字で置き換わってしまいます。また、nullとなっているところにファイルパスを記述するとファイルを添付することができるのですが、Webメールなど一部のメーラーでは正常に認識してくれません。

そこでsend_attached_mail.incを編集し、多少強引に画像添付、文字化けに対応させてみました。


<?php
function SendAttachedMail( $from , $to , $subject , $body , &$file ){
mb_language('ja');
mb_internal_encoding( 'ISO-2022-JP' );
$boundary = "__Boundary__" . uniqid( rand() , true ) . "__";
$mime = "image/";
$header = "";
$header .= "From: $from\n";
$header .= "MIME-Version: 1.0\n";
$header .= "Content-Type: Multipart/Mixed; boundary=\"$boundary\"\n";
$header .= "Content-Transfer-Encoding: 7bit";
$mbody = "--$boundary\n";
$mbody .= "Content-Type: text/plain;charset=ISO-2022-JP\n";
$mbody .= "Content-Transfer-Encoding: 7bit\n";
$mbody .= "\n";
$mbody .= mb_convert_encoding($body,"ISO-2022-JP");
$mbody .= "\n";
for( $i = 0 ; $i < count( $file ) ; $i++ ){
$filename = mb_encode_mimeheader( mb_convert_encoding( basename( $file[ $i ] ) ,  "ISO-2022-JP" , 'auto' ) );
$type=explode(".",$filename);
$mbody .= "--$boundary\n";
$mbody .= "Content-Type: $mime$type[1]; name=\"$filename\"\n";
$mbody .= "Content-Transfer-Encoding: base64\n";
$mbody .= "Content-Disposition: attachment; filename=\"$filename\"\n";
$mbody .= "\n";
$mbody .= chunk_split( base64_encode(file_get_contents( $file[ $i ] ) ) , 76 ,"\n" );
$mbody .= "\n";
}
$mbody .= "--$boundary--\n";
return mail( $to , mb_encode_mimeheader($subject, "ISO-2022-JP-MS"), $mbody , $header );
}
?>

mb_convert_encoding()の文字コードは各々の環境に合わせる必要があります。

このままコピペしただけでは正常に動作しない可能性がありますが、最後の

return mail( $to , mb_encode_mimeheader($subject, “ISO-2022-JP-MS”), $mbody , $header );

となっている部分のISO-2022-JP-MSは半角カナ対応のために使用しているため、少なくともここは変えてはいけません。また、このISO-2022-JP-MSはPHP5.2以上でないと使用できません。

添付ファイルは拡張子を読み取り、無理やりメールヘッダーに対応させています。

元のスクリプトだと、application/octet-streamという分類で送信されてしまい画像であることが認識されませんが、この変更では添付ファイルが画像であることを前提に動的に分類を変えることができています。

メールヘッダーや文字コードに馴染みが無いと理解するのが難しいですが、mb_send_mail()やPHPMailerでも同じようにメールヘッダー情報や文字コードをいじってやることで対応することができます。

PHPメール送信での文字化け対策はあまり情報が少ないため、記事にしてみました。

自分はこのスクリプトや前回のHTML解析の手法を使い、自動的にワードプレスへ投稿する機能を作ったり、匿名からの連絡ツールを作ったりしました。

アイデア次第でいろいろなことに使えると思うので、参考にしてみてください!