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

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

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

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

Q&A

解決済

2回答

11188閲覧

mb_convert_encoding で文字エンコーディングを変換したときに、メーラー側ではその一部分を指定された文字エンコーディングで表示するのですか?

7968

総合スコア253

PHP

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

0グッド

2クリップ

投稿2017/05/01 07:39

編集2017/05/01 11:51

現在、メールフォームの文字コードについて勉強しております。

入力、確認、送信と画面を遷移するメールフォームを作成しました。

送信画面のコードを末尾に記載致します。

mb_language('ja') を指定しております。

ja または Japanese の場合は、ISO-2022-JP/Base64 でエンコードされます。

ISO-2022-JP は、丸囲み文字の ①②㈱髙アイウエオ などの半角カナには対応しておりません。

そのため、mb_convert_encoding を使って ISO-2022-JP-MS に文字エンコーディングを変換しています。

作成したメールフォームから ①②㈱髙アイウエオ を入力して送信したら、問題なく表示されました。

Windows7 の環境で WindowsLive Mail 2012 と Thunderbird 45.8.0 のメーラーで問題なく表示されました。

受信したメールのソースを確認しましたが、Content-Type: text/plain; charset=ISO-2022-JP としか記載なく ISO-2022-JP-MS の表記がありません。

なぜ、メール本文の ①②㈱髙アイウエオ は正しく表示されるのでしょうか?

ご存じの方いれば、教えてください((_ _ (´ω` )ペコ

入力画面

php

1<?php 2// 他のサイトでインラインフレーム表示を禁止する(クリックジャッキング対策) 3header('X-FRAME-OPTIONS: SAMEORIGIN'); 4?> 5<!DOCTYPE html> 6<html lang="ja"> 7<head> 8<meta charset="UTF-8"> 9<title>入力画面</title> 10</head> 11<body> 12 13<h1>お問い合わせ(入力画面)</h1> 14 15<form method="post" action="confirm.php"> 16<table> 17 <tr> 18 <th>お名前(必須)</th> 19 <td><input type="text" name="name"></td> 20 </tr> 21 <tr> 22 <th>ふりがな(必須)</th> 23 <td><input type="text" name="ruby"></td> 24 </tr> 25 <tr> 26 <th>メールアドレス(必須)</th> 27 <td><input type="text" name="mail"></td> 28 </tr> 29 <tr> 30 <th>内容(必須)</th> 31 <td><textarea name="content"></textarea></td> 32 </tr> 33</table> 34<button>送信内容確認</button> 35</form> 36 37</body> 38</html>

確認画面

php

1<?php 2// 他のサイトでインラインフレーム表示を禁止する(クリックジャッキング対策) 3header('X-FRAME-OPTIONS: SAMEORIGIN'); 4 5// IEで発生するコンテンツタイプSniffing対策 6header('X-Content-Type-Options: nosniff'); 7 8// XSSフィルタの設定 9header('X-XSS-Protection:1; mode=block'); 10 11// HttpOnly属性 の指定 12ini_set('session.cookie_httponly', 1); 13 14// セッション開始 15session_start(); 16 17// HTML特殊文字をエスケープする関数 18function h($str) { 19 return htmlspecialchars($str,ENT_QUOTES,'UTF-8'); 20} 21 22/* -------------------------------------------------- 23 トークンの作成(CSRF対策) 24 25 ※使用しているPHPのバージョン・環境にあわせて 26 トークンを選んでね。不要なトークは削除してね。 27-------------------------------------------------- */ 28 29// PHP 7.0 以降 30//if(!isset($_SESSION['token'])) { 31// $_SESSION['token'] = bin2hex(random_bytes(32)); 32//} 33 34// PHP 5.3 ~ 5.x ※OPENSSL導入済 35if(!isset($_SESSION['token'])) { 36 $_SESSION['token'] = bin2hex(openssl_random_pseudo_bytes(32)); 37} 38 39// PHP 5.3 未満 40//if(!isset($_SESSION['token'])) { 41// $_SESSION['token'] = hash('sha256', session_id()); 42//} 43 44// トークンを代入 45$token = $_SESSION['token']; 46 47?> 48<!DOCTYPE html> 49<html lang="ja"> 50<head> 51<meta charset="UTF-8"> 52<title>確認画面</title> 53</head> 54<body> 55 56<h1>お問い合わせ(確認画面)</h1> 57 58<?php 59 60// POSTされたデータを変数に代入(magic_quotes_gpc = On + NULLバイト 対策) 61foreach (array('name','ruby','mail','content') as $v) { 62 $$v = filter_input(INPUT_POST, $v, FILTER_DEFAULT, FILTER_FLAG_STRIP_LOW); 63} 64 65$error_flag = 0; 66 67// 必須項目は未入力をチェック 68if ($name === '' || $name === NULL) { 69 echo '<p>お名前をご入力してください。</p>'; 70 $error_flag = 1; 71} elseif (mb_strlen($name) > 50) { 72 echo '<p>お名前は 50 文字以内で入力してください。</p>'; 73 $error_flag = 1; 74} 75 76if ($ruby === '' || $ruby === NULL) { 77 echo '<p>ふりがなをご入力してください。</p>'; 78 $error_flag = 1; 79} elseif (mb_strlen($ruby) > 50) { 80 echo '<p>ふりがなは 50 文字以内で入力してください。</p>'; 81 $error_flag = 1; 82} 83 84if ($mail === '' || $mail === NULL) { 85 echo '<p>メールアドレスをご入力してください。</p>'; 86 $error_flag = 1; 87} elseif (mb_strlen($mail) > 100) { 88 echo '<p>メールアドレスは 100 文字以内で入力してください。</p>'; 89 $error_flag = 1; 90} elseif (!filter_var($mail, FILTER_VALIDATE_EMAIL)) { 91 echo '<p>メールアドレスの形式が正しくありません。</p>'; 92 $error_flag = 1; 93} 94 95if ($content === '' || $content === NULL) { 96 echo '<p>内容をご入力してください。</p>'; 97 $error_flag = 1; 98} elseif (mb_strlen($content) > 500) { 99 echo '<p>内容は 500 文字以内で入力してください。</p>'; 100 $error_flag = 1; 101} 102 103// エラーがある場合は、戻るボタンを表示し、エラーがない場合は、確認画面を表示 104if ($error_flag === 1) { 105 echo '<button onClick="history.back(); return false;">戻る</button>'; 106} else { 107 // セッション変数に代入 108 $_SESSION['name'] = $name; 109 $_SESSION['ruby'] = $ruby; 110 $_SESSION['mail'] = $mail; 111 $_SESSION['content'] = $content; 112 113 // 確認用画面の表示 114 ?> 115 116 <form method="post" action="send.php"> 117 <table> 118 <tr> 119 <th>お名前</th> 120 <td><?php echo h($name); ?></td> 121 </tr> 122 <tr> 123 <th>ふりがな</th> 124 <td><?php echo h($ruby); ?></td> 125 </tr> 126 <tr> 127 <th>メールアドレス</th> 128 <td><?php echo h($mail); ?></td> 129 </tr> 130 <tr> 131 <th>内容</th> 132 <td><?php echo nl2br(h($content)); ?></td> 133 </tr> 134 </table> 135 <input type="hidden" name="token" value="<?php echo h($token); ?>"> 136 <button>送信</button> 137 </form> 138 139 <?php 140} 141 142?> 143 144 145</body> 146</html>

送信画面

php

1<?php 2// 他のサイトでインラインフレーム表示を禁止する(クリックジャッキング対策) 3header('X-FRAME-OPTIONS: SAMEORIGIN'); 4 5// IEで発生するコンテンツタイプSniffing対策 6header('X-Content-Type-Options: nosniff'); 7 8// XSSフィルタの設定 9header('X-XSS-Protection:1; mode=block'); 10 11// HttpOnly属性 の指定 12ini_set('session.cookie_httponly', 1); 13 14// セッション開始 15session_start(); 16 17// mb_send_mail のエンコーディング 18mb_language('ja'); 19 20// 内部文字エンコーディングを設定 21mb_internal_encoding('UTF-8'); 22?> 23<!DOCTYPE html> 24<html lang="ja"> 25<head> 26<meta charset="UTF-8"> 27<title>送信画面</title> 28</head> 29<body> 30 31<h1>お問い合わせ(送信画面)</h1> 32 33<?php 34 35// token セッション変数がセットされ、NULLまたは空文字 36if(isset($_SESSION['token']) && !empty($_SESSION['token'])) { 37 38 // POST['token']の値をtoken変数に代入 39 $token = filter_input(INPUT_POST, 'token', FILTER_DEFAULT, FILTER_FLAG_STRIP_LOW); 40 41 // 各セッション変数を各変数に代入 42 $name = isset($_SESSION['name']) && is_string($_SESSION['name']) ? mb_convert_encoding($_SESSION['name'], 'ISO-2022-JP-MS', 'ASCII,JIS,UTF-8,eucJP-win,SJIS-win') : ''; 43 $ruby = isset($_SESSION['ruby']) && is_string($_SESSION['ruby']) ? mb_convert_encoding($_SESSION['ruby'], 'ISO-2022-JP-MS', 'ASCII,JIS,UTF-8,eucJP-win,SJIS-win') : ''; 44 $mail = isset($_SESSION['mail']) && is_string($_SESSION['mail']) ? mb_convert_encoding($_SESSION['mail'], 'ISO-2022-JP-MS', 'ASCII,JIS,UTF-8,eucJP-win,SJIS-win') : ''; 45 $content = isset($_SESSION['content']) && is_string($_SESSION['content']) ? mb_convert_encoding($_SESSION['content'], 'ISO-2022-JP-MS', 'ASCII,JIS,UTF-8,eucJP-win,SJIS-win') : ''; 46 47 // トークンの値が一致しない場合は、エラー文を表示し、一致する場合は送信する 48 if($token !== $_SESSION['token']) { 49 50 echo '<p>送信後に再度アクセスされたか、お問い合わせの手順に誤りがあります。<br>お手数ですが、最初の画面からご入力ください。<p>'; 51 52 } else { 53 54 /* 運営側へ送信するメールの設定 */ 55 56 // 送信先のメールアドレス 57 $to = '□□□□□@□□□□□□□'; 58 // 件名 59 $subject = 'お問い合わせからの送信'; 60 // 本文 61 $message = "◆お名前\n$name\n\n◆フリガナ\n$ruby\n\n◆メールアドレス\n$mail\n\n◆内容\n$content"; 62 // オプション 63 $option = '-f'. $to; 64 65 66 /* 問い合わせされた方へ自動返信するメールの設定 */ 67 68 // 件名 69 $auto_subject = 'お問い合わせを承りました'; 70 // 送信元のメールアドレス 71 $auto_from = 'From:' . $to; 72 // 本文 73 $auto_message = 74"※このメールは自動返信によるものです。 75 76$name77 78このたびは、お問合せいただき、誠にありがとうございました。 79 80お送りいただきました内容を確認の上、担当者より折り返しご連絡させていただきます。 81"; 82 83 /* セーフモードがONの場合は、mb_send_mailの第5引数が使えないため、処理を分岐して送信 */ 84 if(ini_get('safe_mode')) { 85 86 /* 運営側と自動返信のメールの送信が完了したら、送信完了の文章を表示する */ 87 if(mb_send_mail($to, $subject, $message, "From:$mail") && mb_send_mail($mail, $auto_subject, $auto_message, $auto_from)) { 88 echo '<p>このたびは、お問合せいただき、誠にありがとうございました。<br>お送りいただきました内容を確認の上、担当者より折り返しご連絡させていただきます。</p>'; 89 } else { 90 echo '<p>大変申し訳ございませんが、メールの送信に失敗しました。<br>お手数ですが最初からやり直してください。</p>'; 91 } 92 93 } else { 94 95 /* 運営側と自動返信のメールの送信が完了したら、送信完了の文章を表示する */ 96 if(mb_send_mail($to, $subject, $message, "From:$mail", $option) && mb_send_mail($mail, $auto_subject, $auto_message, $auto_from, $option)) { 97 echo '<p>このたびは、お問合せいただき、誠にありがとうございました。<br>お送りいただきました内容を確認の上、担当者より折り返しご連絡させていただきます。</p>'; 98 } else { 99 echo '<p>大変申し訳ございませんが、メールの送信に失敗しました。<br>お手数ですが最初からやり直してください。</p>'; 100 } 101 102 } 103 104 } 105 106 // セッションの破棄 107 $_SESSION = array(); 108 session_destroy(); 109 110} else { 111 echo '<p>送信後に再度アクセスされたか、お問い合わせの手順に誤りがあります。<br>お手数ですが、最初の画面からご入力ください。</p>'; 112} 113 114?> 115 116</body> 117</html>

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

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

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

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

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

guest

回答2

0

直接的な回答ではないですが…

WEB上で内容確認画面を出しているわけですから、実際に送信されるものが確認画面と同じであることをユーザーは当然期待します

故に、確認画面の文字コードとメールの文字コードはUTF-8に合わせるのが良いかと

古い携帯などでUTF-8のメールに対応していないものもありますが、今どきは無視していいのでは
あるいは、送信時に自分あてメールの文字コード指定できるようにするかですね

投稿2017/05/01 23:59

takaboo

総合スコア195

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

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

7968

2017/05/02 09:01

回答ありがとうございます。 少し調べてみましたが、仰る通り、PCとスマホだけで受け取る場合ならUTF-8でも問題なさそうな気がしました。 参考にしたサイト ・これからはメールで「﨑」や「髙」を使うことにします http://uonuma.biz/blog/17925
guest

0

ベストアンサー

これ本当に化けませんか?
運営側へのメールの際、UTF-8とISO-2022-JP-MSが混在しているんですけど・・・
コードがiso-2022-jp-msで書かれていればいいんですが、そんなはずないですよね?
わたしの認識が間違っているのかな?(mb_internal_encoding('UTF-8');だしね)

content-typeにiso-2022-jp-msという指定はありえないんじゃないでしょうか。
何せ、iso-2022-jpにMicrosoftが独自拡張したものですから、Windows上でiso-2022-jpの文字コードのデータが来たらiso-2022-jp-msとして取り扱いますよね。

ubuntu上のthunderbirdはiso-2022-jpといいながら、丸数字もちゃんと出ます。
なので、大体のメーラーはiso-2022-jpときたら、iso-2022-jp-msと解釈しているんじゃないでしょうか?

追記

実験コードを書いてみました。

php

1<?php 2mb_language('ja'); 3mb_internal_encoding('UTF-8'); 4 5$text = '①②㈱髙アイウエオ'; 6$text = mb_convert_encoding($text, 'ISO-2022-JP-MS', 'UTF-8'); 7 8$body = "これがテストです\n\n$text"; // ※1 9 10$output = mb_convert_encoding($body, 'ISO-2022-JP', 'UTF-8'); // ※2 11echo mb_convert_encoding($output, 'UTF-8', 'ISO-2022-JP-MS'); // ※3 12```順を追います。 130. ※1の部分では、UTF-8とISO-2022-JP-MSの混合文が出来ています。 140. ※2の部分では、ISO-2022-JP-MSの部分($text変数の中身)はUTF-8ではないのでコンバートされません。 15その他の部分がISO-2022-JPにコンバートされます。 160. ※3の部分では、**ISO-2022-JPの部分**と**コンバートされなかったISO-2022-JP-MS部分**の両方がUTF-8へとコンバートされて出力されます。 17メールだとこの表示される形式へのコンバートをメーラーがやるわけです。大抵のメーラーはISO-2022-JPをISO-2022-JPのMS拡張形式として処理しますので、ちゃんと表示されます。 18 19したがって、メーラーだとちゃんと出力される、という訳です。 20しかしながら、文字コードを混在のままコンバートさせていいのかどうか、悩むところです。 21もし、ISO-2022-JP-MSに統一したとしても、`mb_send_mail`はUTF-8からISO-2022-JPへのコンバートをしようとしますので、そうれもどうなんでしょうか? 22 23`mb_send_mail`の代わりに`mail`を使うのも手ですが、subjectを`mb_encode_mimeheader`する必要があるので面倒ですか?

投稿2017/05/01 10:18

編集2017/05/01 12:46
shi_ue

総合スコア4437

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

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

7968

2017/05/01 11:14 編集

あれ?私が確認した限りでは、文字化けはしていないですね。 確認の仕方に問題があるんですかね? 質問には送信画面のコードしか記載していなかったので、念のため入力と確認画面のコードを追記しました。 入力画面上で上述した特殊文字を入力して送信画面まで遷移して、確かめました。 コードは UTF-8 で記述しています。 ちなみに、Gmail宛に届くようにして確認しましたが、問題なく表示されました。 iPhoneのメールというアプリでキャリアメールを受け取れるようにしているため、キャリアメール宛に届くようにして確認しましたが、こちらも問題なく表示されました。 mb_convert_encoding を記述しないと、特殊文字は ? と表示されました。 mb_convert_encoding を記述しないと ISO-2022-JP/Base64 として扱われると思いますが、ISO-2022-JP では、丸囲みや半角カナが ? になったため、ISO-2022-JP-MS を指定しました。 ISO-2022-JP-MS の場合は、先述したように各メーラーでも問題なく表示されたので、この文字コード最強じゃん!と思ってましたが、普通は指定しないのですか? 文字コードについて調べていますが、通常、ISO-2022-JP を指定するようですが、特殊文字に対応できないので、特殊文字にも対応する方法を調べていて、ISO-2022-JP-MS を試しました。 UTF-8 でもいけるのかなと思い、mb_convert_encoding で UTF-8 を指定しましたが、特殊文字のところは文字化けして ? になりました>< 私の中では、ISO-2022-JP と ISO-2022-JP-MS が混在している認識です。 件名というかヘッダ部分は ISO-2022-JP で処理され、mb_convert_encoding を指定しているところは ISO-2022-JP-MS で処理されていると思っていたのですが、違うんですかね...
shi_ue

2017/05/01 11:14

実験してみましたが、ちゃんとコンバートされてますね。 不思議・・・
7968

2017/05/01 11:16

試してくださりありがとうございます。 文字コードについて理解がないため、引き続き調べてみます。
7968

2017/05/02 09:07 編集

返信が遅くなりすいません。いろいろ調べていました。 ■神サイト見つけました ・PHP の mbstring に関するメモ http://www.asahi-net.or.jp/~wv7y-kmr/memo/php_mbstring.html ・「はしご高」を含むメールを送信したい https://teratail.com/questions/51786 mb_language('ja'); と mb_internal_encoding('UTF-8'); の記述について、きちんと理解していなかったので、調べた結果の私の認識です。 ■mb_language() 下記のように記述してmb_get_infoでどのようになるのか確認しました。  <?php  mb_language('ja');  mb_internal_encoding('UTF-8');  var_dump(mb_get_info()); mb_language('ja'); を指定することにより、メールヘッダを下記のように設定していました。  mail_charset => ISO-2022-JP  mail_header_encoding => BASE64  mail_body_encoding => 7bit これがメールヘッダに記述される内容かと思います。 ■mb_send_mail() > ヘッダと本文は mb_language() の設定に基づき変換、エンコードされます。 > 引用:http://php.net/manual/ja/function.mb-send-mail.php mb_language('ja')としているため、今回は ISO-2022-JP にエンコードされます。 ■ISO-2022-JP-MSでコンバートされた文字もメーラー側で表示する 追記頂いたコードを参考に混在した場合、どのようになるか確認しました。 追記頂いた通り、ISO-2022-JP-MSでコンバートされた文字も、「Content-Type: text/plain; charset=ISO-2022-JP」ならメーラー側で表示されました。 【mb_language('ja') のパターン】  <?php  header("Content-type: text/html; charset=utf-8");  mb_language('ja');  mb_internal_encoding('UTF-8');  $to = '□□□□□@□□□□□□□';  $headers = 'From: □□□□□@□□□□□□□' . "\r\n";  $subject = 'これはテストプログラムから送信したメール!';  $text = '①②㈱髙アイウエオ';  $text = mb_convert_encoding($text, 'ISO-2022-JP-MS', 'UTF-8');  $body = "これがテストです\n\n$text";  mb_send_mail ($to, $subject, $body, $headers);  (結果) これがテストです ①②㈱髙アイウエオ 【mb_language('uni') のパターン】  <?php  header("Content-type: text/html; charset=utf-8");  mb_language('uni');  mb_internal_encoding('UTF-8');  $to = '□□□□□@□□□□□□□';  $headers = 'From: □□□□□@□□□□□□□' . "\r\n";  $subject = 'これはテストプログラムから送信したメール!';  $text = '①②㈱髙アイウエオ';  $text = mb_convert_encoding($text, 'ISO-2022-JP-MS', 'UTF-8');  $body = "これがテストです\n\n$text";  mb_send_mail ($to, $subject, $body, $headers);  (結果) これがテストです ?$B-!-"-j|b?(I12345?(B ■今はUTF-8でもいいのですか? ISO-2022-JP-MS に拘りがあるわけではなく、特殊な文字も受け取れたらいいなということで指定していました。 何の端末で受信するかにもよるかと思いますが、ガラケーで受け取らないなら、もうUTF-8でいいんですかね? ・これからはメールで「﨑」や「髙」を使うことにします http://uonuma.biz/blog/17925 UTF-8で受け取るなら、mb_language を uni に変更するだけで、mb_send_mail でも受け取れるので、問題なさそうならUTF-8にしようかと考えています。
shi_ue

2017/05/02 10:34

今や主流はスマホかパソコンなので、UTF-8でもいいと思ますよ。
7968

2017/05/02 10:54

なるほど、参考になりました。 回答ありがとうございました((_ _ (´ω` )ペコ
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問