質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

7674閲覧

PHPのメール送信で差出人名に空白を使いたいです

qwe001

総合スコア133

CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2016/10/07 04:23

PHP 5.6.22 です
今回メール送信機能をフレームワークなしでPHPで作ることになりました。
以下のようにメールを送信する機能の実装は完了しましたが。。。

php

1 2<?php 3mb_language("Japanese"); 4mb_internal_encoding("UTF-8"); 5 6$from_email = 'aa@example.com'; 7$from_name = 'あいうえお'; 8$headers = 'From: ' . mb_encode_mimeheader(mb_convert_encoding($from_name, 'ISO-2022-JP', 'AUTO')) . '<' . $from_email . '>'; 9 10$toUser = $_SESSION['email']; 11$subjectToUser = 'タイトル'; 12$messageToUser =<<<USER 13{$_SESSION['first_name']}14 15メール本文 16USER; 17 18if($_SESSION){ mb_send_mail($toUser, $subjectToUser, $messageToUser, $headers); } 19 20// メール内容 21// 差出人:あいうえお<aa@example.com> 22// 件名:タイトル 23// 本文:○○様...etc 24?> 25

差出人名に空白をつけると、ヘッダー情報が本文に流れ込んできます。
一体何が原因なのでしょうか。

php

1 2<?php 3mb_language("Japanese"); 4mb_internal_encoding("UTF-8"); 5 6$from_email = 'aa@example.com'; 7$from_name = 'あい うえお'; 8$headers = 'From: ' . mb_encode_mimeheader(mb_convert_encoding($from_name, 'ISO-2022-JP', 'AUTO')) . '<' . $from_email . '>'; 9 10$toUser = $_SESSION['email']; 11$subjectToUser = 'タイトル'; 12$messageToUser =<<<USER 13{$_SESSION['first_name']}14 15メール本文 16USER; 17 18if($_SESSION){ mb_send_mail($toUser, $subjectToUser, $messageToUser, $headers); } 19 20// メール内容 21// 差出人:あい うえ<> 22// 件名:タイトル 23// 本文:=?ISO-2022-JP?B?JUgbKEI=?=<aa@example.com>...etc 24?> 25

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

質問者さんのコードでは正しくヘッダ符号化できていません。この点はshi_ueさんのご回答のやりかたが正しいと思います。

PHP

1mb_internal_encoding('UTF-8'); 2$from_email = '……'; 3$from_name = '……'; 4$headers = 'From: ' . mb_encode_mimeheader($from_name, 'ISO-2022-JP') . ' <' . $from_email . '>';

次に、ご質問の点

差出人名に空白をつけると、ヘッダー情報が本文に流れ込んできます。

ですが、上のようにコードを直しても、$from_nameがだいたい20数文字を超えると再発するのではないかと思います。ひらがなの文字数を増やしてご確認ください (空白の有無は関係ないと思います)。

次のように変更するとどうでしょうか。

PHP

1mb_internal_encoding('UTF-8'); 2$from_email = '……'; 3$from_name = '……'; 4$headers = 'From: ' . mb_encode_mimeheader($from_name, 'ISO-2022-JP', 'B', "\n") . ' <' . $from_email . '>';

mb_encode_mimeheader()に4番めの引数として"\n"を与えています。

先日、既定値の"\r\n"が問題を起こしていたと思しい例を見かけましたので、それと同様かと。

投稿2016/10/08 04:17

編集2016/10/08 06:15
ikedas

総合スコア4229

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

mb_convert_encoding()mb_encode_mimeheader()の文字コード問題についてたいへんよくまとまっているページがありますのでご参照ください。
mb_encode_mimeheaderの都市伝説を検証する - CPA-LABテクニカル

重要なのは、mb_internal_encoding()で設定する(あるいはphp.iniで設定する)文字コードと、mb_encode_mimeheader()に渡す文字列の文字コードは一致していなくてはダメ、ということです。

なので、

php

1<?php 2 mb_language("Japanese"); 3 mb_internal_encoding("UTF-8"); //mb_internal_encodingにUTF-8を指定するんなら、 4 5 $from_email = 'nobody@example.com'; 6 $from_name = 'なんだかすごくすごく長いおまけにシフトジスが嫌いなツとか表とか入っているやらしいなまえでしかも長すぎて化けやすそうなアレがあれななまえのテスト'; 7 $from_encoded = mb_convert_encoding($from_name, 'UTF-8', 'AUTO'); // mb_encode_mimeheaderに渡す前にUTF-8に変換しなくてはダメ 8 var_dump($from_encoded); 9 $headers = 'From: ' . mb_encode_mimeheader($from_encoded) . '<' . $from_email . '>'; 10 11 var_dump($headers) ; 12?>

は、ソースファイルの文字コードがUTF-8だろうがSHIFT-JISだろうが文字化けしませんが、

PHP

1<?php 2 mb_language("Japanese"); 3 mb_internal_encoding("UTF-8"); //mb_internal_encodingにUTF-8を指定するんなら、 4 5 $from_email = 'nobody@example.com'; 6 $from_name = 'なんだかすごくすごく長いおまけにシフトジスが嫌いなツとか表とか入っているやらしいなまえでしかも長すぎて化けやすそうなアレがあれななまえのテスト'; 7 $from_encoded = mb_convert_encoding($from_name, 'ISO-2022-JP', 'AUTO'); // mb_encode_mimeheaderに渡す前にUTF-8に変換しなくてはダメ 8 var_dump($from_encoded); 9 $headers = 'From: ' . mb_encode_mimeheader($from_encoded) . '<' . $from_email . '>'; 10 11 var_dump($headers) ; 12?>

だと文字化けしてしまいます。

#追記
上記のような長いFromだと、エンコードした際には複数行になってしまいます。
これは、RFC2822あたりの、「一行の長さは78文字以下であるべきである」に割と忠実で、これ自体が問題ではないです。
たとえば上記のコードであればエンコード後のFromは

From: =?ISO-2022-JP?B?GyRCJEokcyRAJCskOSQ0JC8kOSQ0JC9EOSQkJCokXiQxJEslNyVVGyhC?= =?ISO-2022-JP?B?GyRCJUglOCU5JCw3eSQkJEolRCRIJCtJPSRIJCtGfiRDJEYkJCRrGyhC?= =?ISO-2022-JP?B?GyRCJGQkaSQ3JCQkSiReJCgkRyQ3JCskYkQ5JDkkLiRGMj0kMSRkGyhC?= =?ISO-2022-JP?B?GyRCJDkkPSQmJEolIiVsJCwkIiRsJEokSiReJCgkTiVGJTklSBsoQg==?=<nobody@example.com>

のようになります。
このように長いヘッダーフィールドは、RFC2047の規定により、複数の 'encoded-word' を含むある特定のヘッダフィールドを表示する時は、隣接する 'encoded-word' を分離するあらゆる 'linear-white-space' は無視されることになっています。

ですので、通常であればこれは一つのFromヘッダとして認識されるべきです。

しかしながら、一部のUnix/Linux系のメールサーバ(MTA)では、行末改行コードにLFのみを期待していて、かつLFがきたらCR+LFに変換する、という大きなお世話をするものがあります。
(手元で調べてみたところqmail、postfixなどがそれにあたるようです)

もしそのような環境であれば、上記の複数行Fromは最初の行だけがヘッダとしてみなされ、次の行には空行が入ってしまうため、それ以降の行が本文として認識されるような事態になります。

これはとてもよろしくないので、もしそういう環境なら、
preg_replace()などで改行コードをLFにして渡すしかないでしょう(RFC違反っぽいのであんまり好ましくないけど)

投稿2016/10/07 07:28

編集2016/10/11 01:46
imutakaoru

総合スコア356

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

qwe001

2016/10/13 12:34

返信が遅くなり申し訳ありません。頂いておりますコードにて期待通りの結果を得ることができました! また、78文字を超えると問題が発生するということ、目から鱗でした。 そのような状況は全く想定していなかったですので、教えて頂くまで気づくことは一生涯なかったと思います。文字コードの違いもいまいちよくわかっておらず、とりあえずメールだしISO-2022-JP使っといたらいいんじゃないの? と思っていたのですが、そのような仕様があったとは…大変勉強になりました。非常にわかりやすく、詳細に書いていただいたこちらの回答をベストアンサーとさせて頂きます。皆様ありがとうございました。またよろしくお願いいたします。
guest

0

php

1$from_email = 'aa@example.com'; 2$from_name = 'あい うえお'; 3$headers = 'From: ' . mb_encode_mimeheader($from_name, 'ISO-2022-JP') . ' <' . $from_email . '>'; 4```これで検証しましたが、うまく行きました。 5 6`mb_encode_mimeheader`はinternal encodingから第二引数に指定された文字に変換しますので、 7`mb_convert_encoding`は不要です。

投稿2016/10/07 04:58

shi_ue

総合スコア4437

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問