私もこの記事のコードを参考にしてsubject, from, 本文に日本語を使ったメールが問題なく送信できることを確認していたのですが、この送信ロジックを複数のコントローラ内に散乱させてしまっていたので、サービスにして共通化しようとリファクタリングを始めました。
mimeが効かない
services: my_mailer: class: MyBundle\Service\Mailer arguments: - @mailer - @templating - @translator - @loggerとサービスを定義して、Switf_Mailerをコンストラクタ内で注入して、sendメソッドでは$this->mailer->send()で送信。コントローラ内のロジックをサービスに集約する、ごくごく普通のリファクタリングをしたつもりでした。
ところが、このリファクタリングを入れてからsubjectのmimeエンコーディングがされなくなり、いわゆる「文字化け」が発生するようになりました。
原因はわかっているものの
mimeが効いていないので、おそらくはSwift::init(function () { Swift_DependencyContainer::getInstance() ->register('mime.qpheaderencoder') ->asAliasOf('mime.base64headerencoder'); Swift_Preferences::getInstance()->setCharset('iso-2022-jp'); });の設定がうまく反映されていないんだろうという見当はすぐつきました。ただ、なぜサービス内に移しただけで反映しないのかが釈然としません。
シングルトン
さきほどの設定部分のコードを眺めていてわかるのは、- Swift::init()はstaticなメソッドである。
- Swift_DependencyContainerとSwift_Preferencesはシングルトンである。
解決
mimeの設定をSwiht::init()で行うことを公式ページでも推奨しているのですが、別にsend()毎に実行してもよいのではないか?ということで、Swift_DependencyContainer::getInstance() ->register('mime.qpheaderencoder') ->asAliasOf('mime.base64headerencoder'); Swift_Preferences::getInstance()->setCharset('iso-2022-jp'); (snip)とSwift::init()内から外に出して解決しました。mimeの設定コストがどのくらいなのか計測していませんが、バッチで大量に配信するものでなく、ウェブアプリケーションからなんらかのクライアントのリクエストからキックされてメールを送る用途では、気にしないでいいのではないでしょうか。 このやり方であれば、メール毎にmime設定のオンオフができます(する機会があるかは疑問ですが)