Zend Framework

Zend_Mail_Transport should not add charset parameter to multipart Content-Type header

Details

  • Type: Bug Bug
  • Status: Resolved Resolved
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: 1.9.2
  • Fix Version/s: 1.9.6
  • Component/s: Zend_Mail
  • Labels:
    None
  • Fix Version Priority:
    Should Have

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?rs=180&uid=swg1PK48897 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'"

Activity

Hide
Oliver Baltz added a comment -

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; }
}

$addCharset = !in_array($type, array(
Zend_Mime::MULTIPART_MIXED,
Zend_Mime::MULTIPART_ALTERNATIVE,
Zend_Mime::MULTIPART_MIXED
));

$this->_headers['Content-Type'] = array(
$type . ( $addCharset ? ( '; charset=' . $this->_mail->getCharset() ) : "" ) . ';'
. $this->EOL
. " " . 'boundary="' . $boundary . '"'
);
$this->boundary = $boundary;
}

$this->_headers['MIME-Version'] = array('1.0');

return $this->_headers;
}

Show
Oliver Baltz added a comment - 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; } } $addCharset = !in_array($type, array( Zend_Mime::MULTIPART_MIXED, Zend_Mime::MULTIPART_ALTERNATIVE, Zend_Mime::MULTIPART_MIXED )); $this->_headers['Content-Type'] = array( $type . ( $addCharset ? ( '; charset=' . $this->_mail->getCharset() ) : "" ) . ';' . $this->EOL . " " . 'boundary="' . $boundary . '"' ); $this->boundary = $boundary; } $this->_headers['MIME-Version'] = array('1.0'); return $this->_headers; }
Hide
O Gray added a comment -

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.

Show
O Gray added a comment - 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.
Hide
Satoru Yoshida added a comment - - edited

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

Show
Satoru Yoshida added a comment - - edited 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
Hide
Satoru Yoshida added a comment -

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.

Show
Satoru Yoshida added a comment - 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.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved:

Time Tracking

Estimated:
1d
Original Estimate - 1 day
Remaining:
1d
Remaining Estimate - 1 day
Logged:
Not Specified
Time Spent - Not Specified