【PHP】mb_send_mail()で機種依存文字が文字化けする原因と対処法

PHPでメール送信機能を実装する際、mb_send_mail()関数を使っている方は多いのではないでしょうか。
しかし、お問い合わせフォームなどで「﨑」「㈱」「①」といった機種依存文字が入力されると、メール本文で「?」に文字化けしてしまうことがあります。
特に、氏名の入力欄で「﨑」や「髙」などが使われるケースは多いため、放置しておくと実務上のトラブルにつながります。
この記事では、mb_send_mail()で機種依存文字が文字化けする原因と、その対処法をわかりやすく解説していきます。
なぜmb_send_mail()で機種依存文字が文字化けするのか?
まず、文字化けが起きる原因を理解しておきましょう。
mb_send_mail()関数は、内部でメール本文をISO-2022-JP(JISコード)にエンコードして送信します。
ISO-2022-JPは日本語メールの標準的な文字コードですが、機種依存文字を含んでいないという制限があります。
ISO-2022-JPで表現できない文字の例:
﨑、髙、﨏、㈱、㈲、①②③、Ⅰ Ⅱ Ⅲ、㍻、㌔ など
そのため、これらの文字が含まれたテキストをmb_send_mail()で送信すると、変換できない文字が「?」に置き換わってしまうのです。
詳細は公式マニュアル(PHP: mb_send_mail – Manual)も確認すると安心です。
対処法:mail()関数でUTF-8のまま送信する
最もシンプルな対処法は、mb_send_mail()の代わりにmail()関数を使い、UTF-8エンコードのまま送信する方法です。
UTF-8は機種依存文字を含む幅広い文字をサポートしているため、文字化けを回避できます。
基本的な実装例
<?php
$to = "example@example.com";
$subject = "お問い合わせ";
$body = "山﨑様からのお問い合わせです。\n㈱サンプル商事\n金額:①②③";
// 件名をMIMEエンコード
$subject = "=?UTF-8?B?" . base64_encode($subject) . "?=";
// ヘッダーにUTF-8を指定
$headers = "Content-Type: text/plain; charset=UTF-8\r\n";
$headers .= "From: info@example.com\r\n";
mail($to, $subject, $body, $headers);
?>
ポイントは以下の2つです。
- ヘッダーで
Content-Type: text/plain; charset=UTF-8を指定し、メール本文がUTF-8であることを明示する - 件名は
base64_encode()を使ってMIMEエンコードする(日本語の件名が文字化けするのを防ぐため)
これで、「﨑」「㈱」「①」などの機種依存文字も文字化けせずに送信できるようになります。
mb_send_mail()とmail()の違い
mb_send_mail()とmail()の主な違いを整理しておきましょう。
| mb_send_mail() | mail() | |
|---|---|---|
| 文字コード変換 | 自動でISO-2022-JPに変換 | 変換しない(指定した文字コードのまま送信) |
| 機種依存文字 | 文字化けする可能性がある | UTF-8で送信すれば問題なし |
| ヘッダー設定 | 文字コード関連を自動で設定 | 自分で明示的に設定が必要 |
| 件名のエンコード | 自動でエンコード | 自分でMIMEエンコードが必要 |
mb_send_mail()は文字コードの変換やヘッダーの設定を自動でやってくれるので手軽ですが、その自動変換がISO-2022-JPを経由するために機種依存文字の文字化けが発生します。
一方、mail()関数は手動で設定する項目が増えますが、UTF-8のまま送信できるため機種依存文字にも対応できるのがメリットです。
それでも文字化けする場合の対処法
mail()関数に切り替えても、メール受信側の環境によってはまれに文字化けが起こる可能性があります。
そのような場合の対処法もいくつか紹介します。
機種依存文字を汎用的な文字に変換する
送信前に、機種依存文字を一般的な文字に置き換えてしまう方法です。
<?php
$text = "㈱サンプル商事 担当:山﨑";
// 機種依存文字を置き換え
$replace = [
"㈱" => "(株)",
"㈲" => "(有)",
"①" => "(1)",
"②" => "(2)",
"③" => "(3)",
];
$text = str_replace(array_keys($replace), array_values($replace), $text);
echo $text;
// 出力:(株)サンプル商事 担当:山﨑
?>
ただし、人名に含まれる「﨑」や「髙」などは安易に置き換えることができないので、この方法には限界があります。
メールライブラリを使用する
より確実にメール送信を行いたい場合は、PHPMailerなどのメールライブラリの利用がおすすめです。
<?php
use PHPMailer\PHPMailer\PHPMailer;
$mail = new PHPMailer(true);
$mail->CharSet = 'UTF-8';
$mail->Encoding = 'base64';
$mail->setFrom('info@example.com', '送信者名');
$mail->addAddress('example@example.com');
$mail->Subject = 'お問い合わせ';
$mail->Body = "山﨑様からのお問い合わせです。\n㈱サンプル商事";
$mail->send();
?>
PHPMailerを使えば、文字コードの指定やエンコード処理を簡潔に記述でき、SMTP経由での送信やHTML形式のメールにも対応できます。
mb_send_mail()で文字化けする主な機種依存文字の一覧
参考として、mb_send_mail()で文字化けしやすい代表的な機種依存文字をまとめておきます。
| カテゴリ | 文字化けする例 | 代替表記 |
|---|---|---|
| 人名漢字 | 﨑、髙、﨏、栁、濵 | 崎、高、隆、柳、浜(※人名では安易に置き換え不可) |
| 囲み文字 | ㈱、㈲、㈹ | (株)、(有)、(代) |
| 丸数字 | ①②③④⑤⑥⑦⑧⑨⑩ | (1)(2)(3)… |
| ローマ数字 | Ⅰ Ⅱ Ⅲ Ⅳ Ⅴ … Ⅹ | 1 2 3 4 5 … 10 |
| 単位記号 | ㍻、㌔、㌢、㍊ | 平成、キロ、センチ、ミリバール |
まとめ
今回は、mb_send_mail()で機種依存文字が文字化けする原因と対処法を紹介しました。
mb_send_mail()は内部でISO-2022-JPに変換するため、機種依存文字が「?」に文字化けする- 最もシンプルな対処法は、
mail()関数でUTF-8のまま送信すること - それでも解決しない場合は、機種依存文字を汎用文字に置き換えるか、PHPMailerなどのライブラリを活用する
特にお問い合わせフォームのように、ユーザーがどんな文字を入力するかわからない場面では、文字化け対策は必須です。
メール送信まわりの実装を見直す際に、ぜひ参考にしてみてください。






















