1. 導入
PHPでメールを受信・処理するシステムを構築する際、避けて通れないのが「マルチパートメール」の解析です。現代のメールの多くは、プレーンテキスト、HTML、画像添付などが混在するマルチパート形式で送られてきます。これを正しく読み解く能力は、メーラー機能や自動返信システムを開発するエンジニアにとって必須のスキルです。本稿では、マルチパートメールの構造を理解し、PHPで適切にデコードして中身を取り出す手法を解説します。
2. 基礎知識
マルチパートメールとは、1つのメールの中に複数のデータ型(テキストや画像など)を含める形式のことです。これを識別する鍵は、メールヘッダの「Content-Type」にあります。
Content-Type: multipart/mixed(またはalternativeなど)と記載があれば、それはマルチパートメールです。このとき、boundaryというパラメータが重要になります。これは各パートを区切るための「境界線」の役割を果たします。
また、メールの本文や添付ファイルは、ネットワークで安全に送信するために「quoted-printable」や「base64」でエンコードされていることが一般的です。これらは人間が読める形式ではないため、PHPの組み込み関数を使ってデコードする必要があります。
3. 実装/解決策
マルチパートメールを解析する基本的な手順は以下の通りです。
1. 境界線(boundary)の特定: ヘッダからboundaryの値を抽出します。
2. パートの分割: メール本文をboundaryで分割し、配列にします。
3. 各パートの解析: 各パートのヘッダを見て、Content-TypeやContent-Transfer-Encodingを確認します。
4. デコード処理: エンコーディング方式に合わせて、quoted_printable_decode()やbase64_decode()を実行します。
4. サンプルプログラム
以下は、メールのソース文字列から各パートを簡易的に分離し、デコードする概念コードです。
/
$rawEmail = “…”; // 受信したメールの全ソース
$boundary = “—-HIJKLMN”; // 実際にはヘッダから正規表現等で抽出します
// boundaryでメールを分割
$parts = explode(“–” . $boundary, $rawEmail);
foreach ($parts as $part) {
// ヘッダと本文を分離
if (strpos($part, “\r\n\r\n”) === false) continue;
list($header, $body) = explode(“\r\n\r\n”, $part, 2);
// quoted-printable形式のデコード判定
if (strpos($header, “Content-Transfer-Encoding: quoted-printable”) !== false) {
$decodedBody = quoted_printable_decode($body);
echo “デコード済み本文: ” . $decodedBody;
}
// base64形式(画像など)のデコード判定
if (strpos($header, “Content-Transfer-Encoding: base64”) !== false) {
$binaryData = base64_decode($body);
// 必要に応じてファイル保存: file_put_contents(‘image.jpg’, $binaryData);
}
}
?>
5. 応用・注意点
現場での開発において注意すべき点は以下の通りです。
文字化けの回避: 日本語メールでは「iso-2022-jp」や「UTF-8」が混在します。デコードした後に必ずmb_convert_encoding()を使用して、システムの文字コードに統一してください。
複雑なネスト構造: サンプルでは単純な分割を行っていますが、実際のメールはマルチパートの中にさらにマルチパートが含まれる「ネスト構造」になっていることがよくあります。本格的な開発では、自前で解析するよりも、PEARのMail_mimeDecodeや、よりモダンなライブラリであるphp-mime-mail-parserなどの実績あるライブラリを使用することを強く推奨します。
セキュリティ: 添付ファイルを取り扱う際は、ファイル名や拡張子をそのまま信用せず、必ずバリデーションを行ってください。特に画像ファイルを保存する際は、アップロードされたファイルに悪意あるスクリプトが含まれていないか注意が必要です。