- ベストアンサー
メールヘッダのMIMEエンコードについて
今、CGIでメールを送信するフォームを作成しているます。 日本語のsubjectを使う場合はMIMEエンコードをしなければいけないと聞いてmime_plsというライブラリで試してみたのですが、受信した結果、「1月1日」→「1 月 1 日」のように半角数字と全角文字の間にスペースが入ってしまいます。 これはどうしたらよいのでしょうか。 コードは以下のように書いています。 $mon = substr($reserveday, 4, 2); $day = substr($reserveday, 6, 2); $subject = sprintf("%d月%d日の件について", $mon, $day); &Jcode::convert(\$subject, 'jis'); $from = &mimeencode($from); $to = &mimeencode($to); $subject = &mimeencode($subject); $contents .= "本文"; &Jcode::convert(\$contents, 'jis'); my $send_buf=''; $send_buf .= "From: $from\n"; $send_buf .= "To: $to\n"; $send_buf .= "Subject: $subject\n"; $send_buf .= "Content-Type: text/plain; charset=iso-2022-jp\n"; $send_buf .= "Content-Transfer-Encoding: 7bit\n"; $send_buf .= "Mime-Version: 1.0\n"; $send_buf .= "\n"; $send_buf .= $contents; # メール送信 open(MAIL,"| $sendmail -t -i -f $from"); print MAIL $send_buf; close(MAIL); よろしくお願いします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
ヘッダのMIMEエンコードでは、 「エンコードされた文字列」と「エンコードされていない生の文字列」の間には空白を入れなければなりません。 そのため、MIMEエンコードされていない「1」とMIMEエンコードされた「月」の間にスペースが入ってしまうのです。 元々、MIMEは英語圏で決められた規格であり、英語などでは単語と単語の間に空白が入るのが当たり前なため、「空白無しに文字列が続く」ような状況が想定されていないという、いわば MIME の規格の欠陥です。 規格にきちんと従うかぎりは、「1月1日」という文字列をそのままMIMEエンコードできないのです。 対処方法ですが、 ・規格にきちんと従うなら、半角スペースが入るのを許容するしかありません。 ・規格無視で、見た目重視なら、半角文字も含めてヘッダの全ての文字列をエンコードしてしまうという方法があります。 後者の方法は、手軽にやるなら、 > $subject = &mimeencode($subject); の代わりに > $subject = "=?ISO-2022-JP?B?".&MIME::base64encode($subject)."?="; でいけます。 ただし、メールヘッダは76文字以内で改行することが推奨されていますが、その処理をしてませんので、長い文字列を入れると文字列長の点でも規格外になります。 なお、mimeencode を使う場合は、この関数自身が改行処理をしてくれますが、その文字数の計算が間違えないように、 mimeencodeに渡す引数には、「Subject:」や「To:」込みのヘッダ行をまるごと渡したほうがいいでしょう。
その他の回答 (3)
- Tacosan
- ベストアンサー率23% (3656/15482)
mime_pls でできるかどうか分かりませんしどのくらいの人がやる気になるかもわかりませんが, あくまで理論的には「1」もエンコードすれば回避できます. つまり, 例えば 「1月1日」 =?US-ASCII?Q?1?= =?ISO-2022-JP?B?GyRCN24bKEI=?= =?US-ASCII?Q?1?= =?ISO-2022-JP?B?GyRCRnwbKEI=?= 「1月 1日」 =?US-ASCII?Q?1?= =?ISO-2022-JP?B?GyRCN24bKEI=?= =?US-ASCII?Q?_1?= =?ISO-2022-JP?B?GyRCRnwbKEI=?= とすれば区別できます (Q と B が混在しているという指摘は本質ではないので却下). 厳密に言うと MIME の規格はこの狭間を「完全に無視しているわけではない」のですが, なぜか中途半端にしか決めていないという不思議な状況.
お礼
回答ありがとうございます。
- Tacosan
- ベストアンサー率23% (3656/15482)
ちょっと確認してほしいことがあるのですが, 「1月1日」と「1月 1日」(後者は 2個目の「1」の前に空白が入っている) のそれぞれをエンコードした結果の文字列はどうなっているでしょうか? これらが一緒だとすると, 「MIME の仕様の狭間」に落っこちている可能性があります.
お礼
試してみました。 「1月1日」 1 =?ISO-2022-JP?B?GyRCN24bKEI=?= 1 =?ISO-2022-JP?B?GyRCRnwbKEI=?= 「1月 1日」 1 =?ISO-2022-JP?B?GyRCN24bKEI=?= 1 =?ISO-2022-JP?B?GyRCRnwbKEI=?= まったく同じ内容でした。 これが「MIME の仕様の狭間」というもので、mtaka2さんもおっしゃっていたものですね。 理由がわかりました。ありがとうございます。
- zxcv0000
- ベストアンサー率56% (111/196)
「そんな事は気にしない」が許容できるならベストだと思います。 許容できないとなると、「空白の挿入」の責任が送信側の「mime_plsというライブラリ」にあるのか、それとも受信者が使用するメールソフトにあるのか調べたり、どのメールソフトでどうなるかを確認したりと大変でしょう。 もし Encode.pm を使用できるなら、 encode('MIME-Header-ISO_2022_JP', $text); も試されてはいかがでしょうか。
お礼
気にしないってことができればいいんですけどね~(笑) メールクライアントはBecky!Ver2とgmailで確認していて、両方で同じ現象が起こるので、スクリプト側の原因と推測しているのです。 あとサーバのperlが5.6なのでEncode.pmは使えないようです。
お礼
とても詳しい解説ありがとうございます。MIME規格についてたいへん勉強になりました。 今回の場合、見た目を重視したいので、後者の方法を試してみようと思います。 ちなみに参考のためにお聞きしたいのですが、Outlook Express, Becky!Ver2, gmailなど私が使ったことのあるメールソフトでは半角と全角の間にスペースが 入るというのを見たことがありません。 これは後者の方法で規格を無視していると考えてもいいのでしょうか。 ご存知であれば教えていただけないでしょうか。