|
symfony1.4の「SwiftMailer」を日本語対応(iso-2022-jp)してみた
2010年3月 1日(月) 11:00 JST
投稿者: 河口
symfony1.2までは「jpMailPlugin」を利用していましたが、1.4へとバージョンアップの機会に
とりあえずsymfonyのマニュアル通りに送信してみることに・・・
mb_language('ja');
mb_internal_encoding('UTF-8');
$message = Swift_Message::newInstance()
->setFrom('from@hoge.com')
->setTo('to@hoge.com')
->setSubject(mb_encode_mimeheader('日本語のサブジェクト',
'iso-2022-jp', 'B', "\r\n"))
->setBody(mb_convert_encoding('日本語のBody',
'iso-2022-jp',
mb_internal_encoding()));
$this->getMailer()->send($message);
結果・・・Subject,Bodyともに文字化け。(これは、予想通り) 文字化けしたメールのヘッダ
$message = Swift_Message~
// 文字コード指定
$message->setCharset('iso-2022-jp');
// メール本文のエンコード指定
$message->setEncoder('7bit'); → ここでPHPエラー。
なにやら、getName() メソッドが無いよ!と怒られてしまいます。 しょうがないので、ソースを追っていくと、Swift_Encodingというクラスに定義されている模様。 これでヘッダは期待通りの出力になり、body部の文字化けもなくなりましたが、 Subjectだけが文字化け・・・
/**
* 日本語対応(iso-2022-jp)メールヘッダクラス
*/
class kzl_Jp_Swift_Mime_Headers_UnstructuredHeader
extends Swift_Mime_Headers_UnstructuredHeader
{
// override
public function getFieldBody()
{
if (!$this->getCachedValue())
{
// ISO-2022-JP対応
if (strcasecmp($this->getCharset(), 'iso-2022-jp') === 0)
{
// subjectをセットする際にエンコードするのでここでは何もしない
$this->setCachedValue($this->getValue());
// 本来はこちらが正しいと思う
// $this->setCachedValue(mb_encode_mimeheader($this->getValue(),
// $this->getCharset(), 'B', "\r\n"));
} else {
parent::getFieldBody();
}
}
return $this->getCachedValue();
}
}
上記クラスを作成し、libフォルダ以下へ保存。
// Subjectヘッダを削除
$message->getHeaders()->remove('Subject');
// 新ヘッダクラスのインスタンス作成。
$subjectHeader
= new kzl_Jp_Swift_Mime_Headers_UnstructuredHeader('Subject',
new Swift_Mime_HeaderEncoder_Base64HeaderEncoder());
// 文字コードセット
$header->setCharset('iso-2022-jp');
// ヘッダを設定
$message->getHeaders()->set($header);
これで、長いSubjectの文字化けもなくなりました。
<?php
/**
* 日本語送信用Swift_Messageクラス
*/
class kzl_Jp_Swift_Message extends Swift_Message
{
public function __construct($subject = null, $body = null)
{
mb_language('ja');
mb_internal_encoding('UTF-8');
$contentType = 'text/plain';
$charset = 'iso-2022-jp';
call_user_func_array(
array($this, 'Swift_Mime_SimpleMessage::__construct'),
Swift_DependencyContainer::getInstance()
->createDependenciesFor('mime.message')
);
// Subjectヘッダのクラスを自前のクラスに変更
$this->getHeaders()->remove('Subject');
$header = new kzl_Jp_Swift_Mime_Headers_UnstructuredHeader(
'Subject',
new Swift_Mime_HeaderEncoder_Base64HeaderEncoder()
);
$header->setCharset($charset);
$this->getHeaders()->set($header);
// ヘッダのソート(一応あわせておく)
$this->sortHeader();
// charset, Content-Typeの設定
$this->setCharset($charset);
$this->setContentType($contentType);
// Content-Transfer-Encodingの設定
$this->setEncoder(Swift_Encoding::get7BitEncoding());
$this->setSubject($subject);
$this->setBody($body);
}
// override
public static function newInstance($subject = null, $body = null,
$contentType = null, $charset = null)
{
// content-type ,charsetは固定なので無視する
return new self($subject, $body);
}
// ---------- Swift_Mime_SimpleMessage のメソッドをoverride ----------
public function setSubject($subject)
{
return parent::setSubject($this->_mb_encode_mimeheader($subject));
}
public function setFrom($addresses, $name = null)
{
if(isset($name))
{
$name = $this->_mb_encode_mimeheader($name);
}
return parent::setFrom($addresses, $name);
}
public function setTo($addresses, $name = null)
{
if(isset($name))
{
$name = $this->_mb_encode_mimeheader($name);
}
return parent::setTo($addresses, $name);
}
public function setBody($body, $contentType = null, $charset = null)
{
// content-type ,charsetは固定なので無視する
return parent::setBody(mb_convert_encoding(
$body,
$this->getCharset(),
mb_internal_encoding()));
}
// ~省略。 CC,BCC等も同様にoverride
// ----------------------------------------------------
/**
* Swift_Mime_SimpleMessageのコンストラクタ内からコピー。
* ヘッダの順番を設定している模様。
*/
private function sortHeader()
{
$this->getHeaders()->defineOrdering(array(
'Return-Path',
'Sender',
'Message-ID',
'Date',
'Subject',
'From',
'Reply-To',
'To',
'Cc',
'Bcc',
'MIME-Version',
'Content-Type',
'Content-Transfer-Encoding'
));
}
/**
* ヘッダの日本語文字列エンコード処理
* @param string $value
* @return string
*/
private function _mb_encode_mimeheader($value)
{
return mb_encode_mimeheader($value, $this->getCharset(), 'B', "\r\n");
}
}
?>
最終的な、メール送信処理は以下のようになります。
$message = kzl_Jp_Swift_Message::newInstance()
->setFrom('from@hoge.com', '日本語の名前From')
->setTo('to@hoge.com', '日本語の名前To')
->setSubject('日本語のながいながい件名です。')
->setBody("日本語の本文。\r\n改行もOK");
$this->getMailer()->send($message);
エンコード処理等の記述もなくなり、大分すっきりしました。
---2010/9/22 追記--- |

