ZF-7874: Zend_Mail_Transport should not add charset parameter to multipart Content-Type header
Description
When generating a multipart (text and html) message, Zend_Mail includes the following in the headers:
Content-Type: multipart/alternative; charset=iso-8859-1;
boundary="=--whatever--"
As far as I can tell, the charset parameter is not appropriate to a multipart/alternative Content-Type declaration.
from RFC 2045, p. 10:
For example, the "charset" parameter is applicable to any subtype of "text", while the "boundary" parameter is required for any subtype of the "multipart" media type.
At http://www-01.ibm.com/support/docview.wss/… I found this:
The charset parameter isn't valid in the headers of ANY multipart type. Neither the multipart/related specification nor any example in any specification suggests that it should be allowed. It only applies to text and to text-related formats such as application/xml. The body of a multipart/related document is not text so it cannot have a charset. It is a collection of parts which are required to consist of valid 7-bit ASCII headers combined with data in whatever encoding is specified in the content-type and content-encoding headers for the relevant part.
The inclusion of the charset parameter causes at least one webmail client (UebiMiau 2.7.10) to choke on the message.
modifying the _getHeaders() fucntion in Zend/Mail/Transport/Abstract.php to change this:
$this->_headers['Content-Type'] = array(
$type . '; charset=' . $this->_mail->getCharset() . ';'
. $this->EOL
. " " . 'boundary="' . $boundary . '"'
);
to this
$this->_headers['Content-Type'] = array(
$type . ';'
. $this->EOL
. " " . 'boundary="' . $boundary . '"'
);
$this->boundary = $boundary;
}
Solved the problem with the web client
Also, if a message generated by the existing code is run through message lint at http://www.apps.ietf.org/node/11, it warns: "WARNING: Unexpected parameter 'charset' in header 'Content-Type'"
Comments
Posted by Oliver Baltz (dewoob) on 2009-10-06T03:40:36.000+0000
This fix seems to work for me:
protected function _getHeaders($boundary) { if (null !== $boundary) { // Build multipart mail $type = $this->_mail->getType(); if (!$type) { if ($this->_mail->hasAttachments) { $type = Zend_Mime::MULTIPART_MIXED; } elseif ($this->_mail->getBodyText() && $this->_mail->getBodyHtml()) { $type = Zend_Mime::MULTIPART_ALTERNATIVE; } else { $type = Zend_Mime::MULTIPART_MIXED; } }
Posted by O Gray (ovgray) on 2009-10-06T05:08:42.000+0000
Mr. Baltz's proposed fix assumes that there is some Multipart type for which charset is a valid header parameter. The reference I quoted from the IBM site is categorical that this is not so. Is there some authority to the contrary?
Zend_Mime only contemplates three multipart types: MULTIPART_ALTERNATIVE, MULTIPART_MIXED and MULTIPART_RELATED. Zend_Mail only permits those three types (see Zend_Mail::setType). Thus, this fix would permit a charset header parameter for the MULTIPART_RELATED type only. That type is defined in http://tools.ietf.org/html/rfc2387. Nothing in that definition suggests that charset is a valid header parameter for that type.
It seems odd that Zend_Mime::MULTIPART_MIXED is mentioned twice in this part of the _getHeaders function (this is presumably why Mr. Baltz includes Zend_Mime::MULTIPART_MIXED twice in the array his code adds):
if (!$type) { if ($this->_mail->hasAttachments) { $type = Zend_Mime::MULTIPART_MIXED; } elseif ($this->_mail->getBodyText() && $this->_mail->getBodyHtml()) { $type = Zend_Mime::MULTIPART_ALTERNATIVE; } else { $type = Zend_Mime::MULTIPART_MIXED; } }
I wonder if the code I have just quoted should have been:
if (!$type) { if ($this->_mail->hasAttachments) { $type = Zend_Mime::MULTIPART_MIXED; } elseif ($this->_mail->getBodyText() && $this->_mail->getBodyHtml()) { $type = Zend_Mime::MULTIPART_ALTERNATIVE; } else { $type = Zend_Mime::MULTIPART_RELATED; } }
In any event, if charset is not a valid parameter in the header of any multipart type (as opposed to the header of a part), then its seems better (and simpler) just to eliminate it from the _getHeaders() function altogether.
Posted by Satoru Yoshida (satoruyoshida) on 2009-10-06T20:40:17.000+0000
Thank you for the suggestions, Oliver Baltz and O Gray . I'm working now, and I'll be happy if you give me several weeks, Thanks ;-)
Posted by Satoru Yoshida (satoruyoshida) on 2009-10-31T06:13:19.000+0000
Solved in SVN r18759 of trunk, r18760 of 1.9 branch.
But 2 Zend_Mime::MULTIPART_MIXEDs seem to be correct.
I think 2nd Zend_Mime::MULTIPART_MIXED is default value if script can not set the type automatically.