COLUMN — 保守・運用

問い合わせ通知メールで、ドイツ語のお名前が「?」だらけになったとき

問い合わせ通知メールに含まれていたドイツ語のお名前が、ü・ö・ßだけ「?」に置き換わって届きました。エラーは出ておらず、受信自体は成功しています。前回の記事は「メールが届かない」症状でしたが、今回は「届いてはいるが中身の一部が壊れている」という別の症状です。実際の変換前後のバイト列まで確認しました。

#保守・運用 約4分で読めます

メールは届いていました。中身が壊れていました

問い合わせ通知メールに、ドイツ語のお名前が含まれていました。届いたメールを開くと、次のようになっていました。

「Kirschbl?ten m?chten gr??ere」

もとの文字列は「Kirschblüten möchten größere」でした。ü・ö・ß が、すべて「?」に置き換わっていました。日本語の部分は正常でした。

前回の記事では、メールがそもそも届かない症状を扱いました。今回は届いてはいるが、中身の一部が壊れているという、別の症状です。エラーは出ていません。受信自体は成功しています。

まず疑ったのは、送信側の文字コードでした

自社のフォーム処理は、日本語をそのまま扱える「mb_send_mail」という関数でメールを送っています。この関数は、送信前に「mb_language」という設定で言語を指定できます。

自社の設定は「Japanese」でした。この値を疑いました。

「mb_language('Japanese')」を設定すると、「mb_send_mail」は本文と件名を ISO-2022-JP という文字コードに変換してから送信します。日本語のメールで昔からよく使われている符号化方式です。

ISO-2022-JP は、日本語と半角英数字は表現できますが、ドイツ語のウムラウト(ü・ö)やエスツェット(ß)は表現できません。表現できない文字が来たときにどうなるかを、実際に変換して確かめました。

変換前後のバイト列を比べました

PHP 8.5 で、実際に変換前後のバイト列を取り出しました。

変換前のUTF-8では、üの部分が16進数で c3 bc、öß の部分が c3 b6 c3 9f という並びでした。ISO-2022-JPへ変換したあとを見ると、ü の位置は 3f 一つに、öß の位置は 3f が二つ並ぶ形に変わっていました。3f は文字コードで疑問符を表す値です。

1文字が1文字の「?」に変換され、消えてなくなるわけでも、別の文字に化けるわけでもなく、きれいに「?」へ潰れていました。

これで、届かなかったのではなく、表現できない文字が変換の時点で失われていたと確定しました。

送信者宛の自動返信は、無傷でした

同じフォームから送っているメールが、もう1通あります。問い合わせをした方への自動返信です。こちらは化けていませんでした。

理由を確認すると、自動返信の送信処理は「mb_send_mail」を使っておらず、「mail」関数に自分でヘッダーを組み立てて渡していました。文字コードを指定するヘッダーを明示し、件名もUTF-8として符号化しています。「mb_language」の設定を経由しないため、影響を受けていませんでした。

同じフォームの同じ1回の送信で、片方は化け、片方は無傷という状態です。「メールが化けた」という報告を受けたときは、化けたのがどちらの経路かを先に特定する必要があります。ここを混同すると、直っていない経路を直った経路だと思い込みます。

直したのは、変換そのものをやめることでした

「mb_language('Japanese')」を「mb_language('uni')」に変更しました。この設定では UTF-8 のまま、Base64 という方式で符号化して送信します。ISO-2022-JP への変換自体が起きなくなるため、表現できない文字という状況そのものがなくなります。

該当箇所は2つありました。フォームからの通知メールと、別の通知経路にあるメール送信処理です。どちらも同じ設定を使っていました。

変更後、同じ文字列を含むメールで再確認し、ü・ö・ß がそのまま届くことを確認しました。日本語も従来どおり問題なく届きます。

この症状が起きる条件と、確認の順番

この症状が起きるのは、「mb_send_mail」を使い、かつ「mb_language」が「Japanese」になっている場合です。「mb_language」を明示的に設定していないフォームでは起きません。PHPの既定値によって挙動が変わるため、設定を明示していないフォームは、まずそこを確認する必要があります。

自分のフォームで同じ症状が疑われる場合、確認する順番があります。まず、化けているのが管理者宛の通知なのか、送信者宛の自動返信なのかを区別してください。次に、化けているメールの送信処理で「mb_send_mail」を使っているかを見ます。使っている場合は、「mb_language」の設定値を確認してください。

日本語だけの問い合わせでは、この症状は表面化しません。海外のお名前やドイツ語・フランス語などの入力が来て初めて気づきます。普段は問題なく動いているように見える設定が、特定の文字が来た瞬間だけ壊れるという点が、この症状のやっかいなところです。測っていなければ、ずっと気づかないままだったと思います。

FAQよくある質問

Q問い合わせメールの一部の文字だけが「?」になります。原因は何ですか。
Amb_send_mailという関数でメールを送っており、かつmb_languageの設定がJapaneseになっている場合に起こります。この設定は本文をISO-2022-JPという文字コードに変換して送信しますが、この文字コードは日本語と半角英数字しか表現できないため、それ以外の文字がすべて「?」に潰れます。
Q管理者宛の通知メールと、送信者宛の自動返信で結果が違うのはなぜですか。
A同じフォームでも、送信処理が別のプログラムで書かれていることがあるためです。自動返信のほうが文字コードを指定するヘッダーを自分で組み立てて送っていれば、mb_languageの設定を経由しないため影響を受けません。「メールが化けた」と聞いたら、どちらの経路の話かを先に区別する必要があります。
Qこの症状に、自分では気づきにくいのはなぜですか。
A日本語だけの問い合わせでは症状が表面化しないためです。海外のお名前やドイツ語・フランス語などの入力が来て初めて気づきます。普段は問題なく届いているように見える設定が、特定の文字が来た瞬間だけ壊れるため、実際に確かめるまで発見できません。
Q直すにはどうすればいいですか。
Amb_languageの設定をJapaneseからuniに変更してください。UTF-8のままBase64という方式で符号化して送信するようになり、ISO-2022-JPへの変換自体が起きなくなるため、表現できない文字という状況そのものがなくなります。

「うちの場合は?」に、お答えします。

見積もりは何度でも無料。
他社との比較用でも歓迎です。
しつこい営業はしません。

無料で見積もりを頼む

お返事について

1営業日以内に、
メールでお返事します。

受付 10:00〜18:00