Skip to content
Permalink
Browse files

Adding configuration options to CakeEmail to set the header encoding …

…and body encoding, also translating

all string from the App.encoding value to the configured charset if they differ. This makes possible to
send correctly emails in japanese charset
  • Loading branch information...
lorenzo committed Oct 16, 2011
1 parent 3ed712e commit b38c0e50a4d7d7f59a39807611cc4ef0babf5cfc
@@ -30,6 +30,7 @@
* transport => The name of a supported transport; valid options are as follows:
* Mail - Send using PHP mail function
* Smtp - Send using SMTP
* Debug - Do not send the email, just return the result
*
* You can add custom transports (or override existing transports) by adding the
* appropriate file to app/Network/Email. Transports should be named 'YourTransport.php',
@@ -43,7 +44,9 @@ class EmailConfig {

public $default = array(
'transport' => 'Mail',
'from' => 'you@localhost'
'from' => 'you@localhost',
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
);

public $smtp = array(
@@ -54,7 +57,10 @@ class EmailConfig {
'timeout' => 30,
'username' => 'user',
'password' => 'secret',
'client' => null
'client' => null,
'log' => false
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
);

public $fast = array(
@@ -82,7 +88,10 @@ class EmailConfig {
'timeout' => 30,
'username' => 'user',
'password' => 'secret',
'client' => null
'client' => null,
'log' => true,
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
);

}
@@ -30,6 +30,7 @@
* transport => The name of a supported transport; valid options are as follows:
* Mail - Send using PHP mail function
* Smtp - Send using SMTP
* Debug - Do not send the email, just return the result
*
* You can add custom transports (or override existing transports) by adding the
* appropriate file to app/Network/Email. Transports should be named 'YourTransport.php',
@@ -43,7 +44,9 @@ class EmailConfig {

public $default = array(
'transport' => 'Mail',
'from' => 'you@localhost'
'from' => 'you@localhost',
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
);

public $smtp = array(
@@ -54,7 +57,10 @@ class EmailConfig {
'timeout' => 30,
'username' => 'user',
'password' => 'secret',
'client' => null
'client' => null,
'log' => false
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
);

public $fast = array(
@@ -82,7 +88,10 @@ class EmailConfig {
'timeout' => 30,
'username' => 'user',
'password' => 'secret',
'client' => null
'client' => null,
'log' => true,
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
);

}
@@ -239,12 +239,26 @@ class CakeEmail {
protected $_transportClass = null;
/**
* charset the email is sent in
* Charset the email body is sent in
*
*
* @var string
*/
public $charset = 'utf-8';
/**
* Charset the email header is sent in
* If null, the $charset property will be used as default
* @var string
*/
public $headerCharset = null;
/**
* The application wide charset, used to encode headers and body
* @var string
*/
public $_appCharset = null;
/**
* List of files that should be attached to the email.
*
@@ -274,13 +288,16 @@ class CakeEmail {
*
*/
public function __construct($config = null) {
$charset = Configure::read('App.encoding');
if ($charset !== null) {
$this->charset = $charset;
$this->_appCharset = Configure::read('App.encoding');
if ($this->_appCharset !== null) {
$this->charset = $this->_appCharset;
}
if ($config) {
$this->config($config);
}
if (empty($this->headerCharset)) {
$this->headerCharset = $this->charset;
}
}
/**
@@ -994,15 +1011,24 @@ public static function deliver($to = null, $subject = null, $message = null, $tr
protected function _applyConfig($config) {
if (is_string($config)) {
if (!class_exists('EmailConfig') && !config('email')) {
throw new SocketException(__d('cake_dev', '%s not found.', APP . 'Config' . DS . 'email.php'));
throw new ConfigureException(__d('cake_dev', '%s not found.', APP . 'Config' . DS . 'email.php'));
}
$configs = new EmailConfig();
if (!isset($configs->{$config})) {
throw new SocketException(__d('cake_dev', 'Unknown email configuration "%s".', $config));
throw new ConfigureException(__d('cake_dev', 'Unknown email configuration "%s".', $config));
}
$config = $configs->{$config};
}
$this->_config += $config;
if (!empty($config['charset'])) {
$this->charset = $config['charset'];
}
if (!empty($config['headerCharset'])) {
$this->headerCharset = $config['headerCharset'];
}
if (empty($this->headerCharset)) {
$this->headerCharset = $this->charset;
}
$simpleMethods = array(
'from', 'sender', 'to', 'replyTo', 'readReceipt', 'returnPath', 'cc', 'bcc',
'messageId', 'subject', 'viewRender', 'viewVars', 'attachments',
@@ -1073,15 +1099,31 @@ protected function _encode($text) {
$internalEncoding = function_exists('mb_internal_encoding');
if ($internalEncoding) {
$restore = mb_internal_encoding();
mb_internal_encoding($this->charset);
mb_internal_encoding($this->_appCharset);
}
$return = mb_encode_mimeheader($text, $this->charset, 'B');
$text = $this->_encodeString($text, $this->headerCharset);
$return = mb_encode_mimeheader($text, $this->headerCharset, 'B');
if ($internalEncoding) {
mb_internal_encoding($restore);
}
return $return;
}
/**
* Translates a string for one charset to another if the App.encoding value
* differs and the mb_convert_encoding function exists
*
* @param string $text The text to be converted
* @param string $charset the target encoding
* @return string
*/
protected function _encodeString($text, $charset) {
if ($this->_appCharset === $charset || !function_exists('mb_convert_encoding')) {
return $text;
}
return mb_convert_encoding($text, $charset, $this->_appCharset);
}
/**
* Wrap the message to follow the RFC 2822 - 2.1.1
*
@@ -1322,7 +1364,7 @@ protected function _render($content) {
$View->viewPath = $View->layoutPath = 'Emails' . DS . $this->_emailFormat;
$View->viewVars['content'] = $content;
$rendered = $View->render($template, $layout);
$rendered = $this->_encodeString($View->render($template, $layout), $this->charset);
$content = explode("\n", $rendered);
if ($this->_emailFormat === 'html') {
@@ -1120,4 +1120,67 @@ public function testEmailFormat() {
$result = $this->CakeEmail->emailFormat('invalid');
}
/**
* Tests that it is possible to add charset configuration to a CakeEmail object
*
* @return void
*/
public function testConfigCharset() {
$email = new CakeEmail();
$this->assertEquals($email->charset, Configure::read('App.encoding'));
$this->assertEquals($email->headerCharset, Configure::read('App.encoding'));
$email = new CakeEmail(array('charset' => 'iso-2022-jp', 'headerCharset' => 'iso-2022-jp-ms'));
$this->assertEquals($email->charset, 'iso-2022-jp');
$this->assertEquals($email->headerCharset, 'iso-2022-jp-ms');
$email = new CakeEmail(array('charset' => 'iso-2022-jp'));
$this->assertEquals($email->charset, 'iso-2022-jp');
$this->assertEquals($email->headerCharset, 'iso-2022-jp');
$email = new CakeEmail(array('headerCharset' => 'iso-2022-jp-ms'));
$this->assertEquals($email->charset, Configure::read('App.encoding'));
$this->assertEquals($email->headerCharset, 'iso-2022-jp-ms');
}
/**
* Tests that the header is encoded using the configured headerCharset
*
* @return void
*/
public function testHeaderEncoding() {
$this->skipIf(!function_exists('mb_convert_encoding'));
$email = new CakeEmail(array('headerCharset' => 'iso-2022-jp-ms', 'transport' => 'Debug'));
$email->subject('あれ?もしかしての前と');
$headers = $email->getHeaders(array('subject'));
$expected = "?ISO-2022-JP?B?GyRCJCIkbCEpJGIkNyQrJDckRiROQTAkSBsoQg==?=";
$this->assertContains($expected, $headers['Subject']);
$email->to('someone@example.com')->from('someone@example.com');
$result = $email->send('ってテーブルを作ってやってたらう');
$this->assertContains('ってテーブルを作ってやってたらう', $result['message']);
}
/**
* Tests that the body is encoded using the configured charset
*
* @return void
*/
public function testBodyEncoding() {
$this->skipIf(!function_exists('mb_convert_encoding'));
$email = new CakeEmail(array(
'charset' => 'iso-2022-jp',
'headerCharset' => 'iso-2022-jp-ms',
'transport' => 'Debug'
));
$email->subject('あれ?もしかしての前と');
$headers = $email->getHeaders(array('subject'));
$expected = "?ISO-2022-JP?B?GyRCJCIkbCEpJGIkNyQrJDckRiROQTAkSBsoQg==?=";
$this->assertContains($expected, $headers['Subject']);
$email->to('someone@example.com')->from('someone@example.com');
$result = $email->send('ってテーブルを作ってやってたらう');
$this->assertContains('Content-Type: text/plain; charset=iso-2022-jp', $result['headers']);
$this->assertContains('ってテーブルを作ってやってたらう', $result['message']);
}
}

0 comments on commit b38c0e5

Please sign in to comment.
You can’t perform that action at this time.