Asial Blog

Recruit! Asialで一緒に働きませんか?

symfonyでSwift Mailerを使用する際の注意点

カテゴリ :
バックエンド(プログラミング)
タグ :
Tech
symfony
Mail
Swift
2008.12.03 やっぱり使い方を間違っていなかったようなので、再修正です。田舎の開発者さんご指摘ありがとうございました。

2008.08.28 Swift_Messageの使い方を間違えるという、とっても初歩的なミスをしていたので、修正しました。 shuwat さんありがとうございました


先日のsymfonyのjpMailPlugin(メール送信プラグイン)の使い方のまとめのコメントで、Swift Mailerについてshuwatさんがコメントで言及されていたので、Swift Mailerについて軽くふれておきます。

とりあえず、symfonyのCookbookに書いてある通りに進めればできます。

symfony1.0 であってもgetPresentationFor()メソッドを使用して同様にメール送信することもできます。

SMTPを使用したメールのであれば、以下のコードで送信することができると思います。

  1. <?php
  2. // ...省略
  3. // 2008.08.28 修正
  4. /*
  5. $msg = new Swift_Message(
  6.   'サブジェクト',
  7.   mb_convert_encoding('本文', 'JIS', 'UTF-8'),
  8.   'text/plain',
  9.   '7bit',
  10.   'iso-2022-jp'
  11. );
  12. */
  13. // 2008.12.03 再修正
  14. /*
  15. $msg = new Swift_Message(
  16.   'サブジェクト',
  17.   '本文',
  18.   'text/plain',
  19.   'iso-2022-jp',
  20.   '7bit'
  21. );
  22. */
  23. $msg = new Swift_Message(
  24.   'サブジェクト',
  25.   mb_convert_encoding('本文', 'JIS', 'UTF-8'),
  26.   'text/plain',
  27.   '7bit',
  28.   'iso-2022-jp'
  29. );
  30. $conn = new Swift_Connection_SMTP('localhost');
  31. $mailer = new Swift($conn);
  32.  
  33. $mailer->send($msg, 'to@example.com', 'from@example.com');
  34. // ...省略

ソースコードがUTF-8で記述されていれば、これで本文が ISO-2022-JP のメールが送信されるのですが、SubjectヘッダーはUTF-8の状態で送信されます。そのため、メールのソースを見ると以下のようになってしまいます。

  1. Subject: =?utf-8?B?44K144OW44K444Kn44Kv44OI?=

Thunderbirdの場合、うまくデコードしてくれるのですが、その他のメーラーでもデコードできるかどうかは不明です。特に携帯メールの場合は怪しいと思います(おそらく絵文字を件名に入れたりはできないかと思われます)。

なお、ISO-2022-JP の件名を作成することも可能で、以下のようにします。

  1. <?php
  2. // ...省略
  3. /*
  4. $msg = new Swift_Message(
  5.   mb_convert_encoding('サブジェクト', 'JIS', 'UTF-8'),
  6.   mb_convert_encoding('本文', 'JIS', 'UTF-8'),
  7.   'text/plain',
  8.   '7bit',
  9.   'iso-2022-jp'
  10. );
  11. */
  12. /*
  13. $msg = new Swift_Message(
  14.   mb_convert_encoding('サブジェクト', 'JIS', 'UTF-8'),
  15.   '本文',
  16.   'text/plain',
  17.   'iso-2022-jp',
  18.   '7bit'
  19. );
  20. */
  21. $msg = new Swift_Message(
  22.   mb_convert_encoding('サブジェクト', 'JIS', 'UTF-8'),
  23.   mb_convert_encoding('本文', 'JIS', 'UTF-8'),
  24.   'text/plain',
  25.   '7bit',
  26.   'iso-2022-jp'
  27. );
  28. $msg->headers->setCharset('ISO-2022-JP');
  29. // ...省略

これでSubjectヘッダーは以下のように変更されます。

  1. Subject: =?ISO-2022-JP?B?GyRCJTUlViU4JSclLyVIGyhC?=

一見これでうまくいったかのように見えるのですが、件名が長い場合の折り返し処理で不都合が生じます。たとえば、「サブジェクトサブジェクトサブジェクト」とした場合には件名が文字化けを起こします。そのときのメールヘッダーは以下のようになります。

  1. Subject: =?ISO-2022-JP?B?GyRCJTUlViU4JSclLyVIJTUlViU4JSclLyVIJTUlViU4?=
  2.  =?ISO-2022-JP?B?JSclLyVIGyhC?=

なお、mb_encode_mimeheader()を使用すると以下のようになります。

  1. Subject: =?ISO-2022-JP?B?GyRCJTUlViU4JSclLyVIJTUlViU4JSclLyVIJTUlViU4GyhC?=
  2.  =?ISO-2022-JP?B?GyRCJSclLyVIGyhC?=

JISコードで使用するエスケープシーケンスを各行の最後に追加していないため、このようなことが起きてしまいます。

Swift_Mailer の内部的な処理としてヘッダーのエスケープ処理(Swift_Message_Headers)が記述されているので、mb_encode_mimeheader()を使用してエンコードする処理に変更する必要があります(もしくはSwift_Message_Headersを直接変更してしまいます)。

とは言ってもそこまでする必要はあまりないかと思います。普通に symfony1.1 でも jpMail を使用できないことはないので、そちらを使った方が今のところは良いと思います。

コメント

  • shuwat

    SwiftMailerで長い件名が文字化けするのは、たぶんコンストラクタの引数が違うからではないでしょうか。

    手元では以下の内容で変換作業をすることもなく、文字化けを起こさず使えています。

    <pre>
    $this->message = new Swift_Message('仮タイトル', '仮本文', 'text/plain', 'iso-2022-jp', '7bit'); //encodingとcharsetの位置が逆
    </pre>


    ただ、これでもFromに日本語を入れるとが文字化けを起こすことがあったので、改行文字を先頭にくっつけて回避しています。
    これはバッドノウハウかな?

  • joe

    shuwat さん指摘ありがとうございます。

    まさにその通りで、encoding と charset がまちがっていました!

    なので、内容を修正しました。

    ただ、やっぱりヘッダーの文字エンコーディングはUTF-8となってしまうので、気にくわないです。

    しかも、$msg->headers->setCharset('ISO-2022-JP'); を実行すると、UTF-8のままの文字列を =?ISO-2022-JP?B? ---- ?=としてしまうという困ったことになります。。。

  • 田舎の開発者

    情報、ありがとうございました。参考にさせていただきました。おかげさまで、何とかメール送信に目処が立ちそうです。

    ところでjpMailpluginは、package.xmlで明示的にSymfony1.1.0以上へのインストールを禁じていますね。これは単に動作確認が取れていない、というだけでしょうか? それとも、1.1.1以降では何かしらの不具合があるのでしょうか?

    一応、作者のbright.River様にもメールで問い合わせましたが、1.1.1以降の動作について何かご存知のことがあれば情報を頂ければ幸いです。

  • joe

    jpMailPlugin は symfony 1.1 以降では動かないと思います。

    理由は jpMailView の中で symfony 1.1 以降では使用できないメソッド等を使っているからかなぁ。

    jpMailView を使わないのであれば、 sfCompat10Plugin と合わせて使えば jpMail は動くのではないかと思います。

    メーラの決定版が欲しい今日この頃ですね。

  • 田舎の開発者

    お返事、ありがとうございます。確かに、内部でsfMailなどを使っているようですね。

    なのですが、jpMailpluginのpackage.xmlでは、明示的に1.1.0『には』インストールを許可しているのですよ。これってpackage.xmlの記述ミスでしょうか?(苦笑)

    さしあたってはSwiftを使用することにしますが……携帯にメールを配信したいと言われた場合は少々面倒ですね。確かにもう少しスマートな解決方法が欲しいところです。

    では、改めてお返事にお礼を申し上げます。

  • 田舎の開発者

    ご無沙汰しています。実は上のコメントに関連して、私の現在の環境では以下のように書かないと正しく動かない、という現象が起きます。swiftの方で順番を入れ替えたのでしょうか?

    new Swift_Message($title, $body, 'text/plain', '7bit', 'utf-8');

    もしかしたら「順番を間違えているのでデフォルトのまま出力してるだけ」という可能性もあるのですが、入れ替えてメールを送信すると以下のようなヘッダになります。

    Content-Type: text/plain; charset=7bit; format=flowed
    Content-Transfer-Encoding: utf-8

    貼り付けたコードで送信するとこうなるのです。

    Content-Type: text/plain; charset=utf-8; format=flowed
    Content-Transfer-Encoding: 7bit

    大変申し訳ありませんが、今一度、現在のswiftで動作を確認していただけませんか? お手数とは存じますが宜しくお願いします

  • joe

    > 田舎の開発者 さん
    確かにおっしゃる通りでした。。。

    ブログ再修正です(といっても元にもどしただけなのですが)


    それにしてもなんで自分で確かめたときに変だと思わなかったのか不思議です。

    SwiftMailer以外の選択肢として、Qdmail というものもあるので、参考にしてはいかがでしょうか?

    http://hal456.net/qdmail/

    また、おやぢ組さんが新しくプラグインを作成したみたいなので、そちらも見てみるとよいと思います。

    http://openpear.org/package/jpSimpleMailPlugin

  • bogati

    mb_convert_encoding

    使えば件名も文字化けしない

コメントフォーム



captcha_key

アシアルの会社情報

アシアル株式会社はPHP、HTML5、JavaScriptに特化したWebエンジニアリング企業です。ユーザーエクスペリエンス設計から大規模システム構築まで、アシアルメンバーが各々の専門性を通じてインターネットの進化に貢献します。

会社情報詳細

最近の記事