Description

There is a possibility to have a massive speedup in Zend_Mime::encodeQuotedPrintable().
If the imap extension in php is enabled, the function imap_8bit() should be used instead of doing it on your own. Here's a little script showing the speedup.

The page says, ??Zend Framework components may use an extension only if that extension is enabled by default in the PHP.net binary distribution supported by the current release of Zend Framework.??

Therefore, I think the exptension is not available at present unfortunately. :-(

Posted by Michael Kliewe (mkliewe) on 2009-10-28T10:47:27.000+0000

If the extension is not available, it is not used. There is no problem I think.

I have the same "problem" with the bad performance...

Posted by Martin Körner (mkone) on 2009-10-28T11:09:09.000+0000

What about Zend_Db_Adapter_Sqlsrv? This class even uses a 3rd party extension (sqlsrv.dll from Microsoft Corp.) which is currently only available on Win32.

The Coding Standard should not be used in this case because:
1. it's a draft
2. there are other classes that don't follow it
3. the Zend_Mime class will work without the extension enabled furthermore

Posted by Nico Edtinger (nico) on 2009-11-05T05:37:33.000+0000

An extension, which is not in the default build may be used as a soft dependency AFAIK. BTW adapters are a bad example, because they invert the dependency (you use an adapter, because you have database X).

As long as imap/c-client doesn't have problems, like different output than build-in methods or platform specific issues, it could be used if the benefit is big enough. The given example doesn't really test a real life issue if the page content is not fetched inside of the loop, so the benefit hasn't been measured yet.

There are new functions available since PHP 5.3: quoted_printable_encode & quoted_printable_decode

php.net:
- encode
Returns a quoted printable string created according to » RFC2045, section 6.7.
This function is similar to imap_8bit(), except this one does not require the IMAP module to work.

decode:
This function returns an 8-bit binary string corresponding to the decoded quoted printable string (according to » RFC2045, section 6.7, not » RFC2821, section 4.5.2, so additional periods are not stripped from the beginning of line).
This function is similar to imap_qprint(), except this one does not require the IMAP module to work.

Hello?!?
Could anyone please be so kind and put the changes in the trunk?
Greets

Posted by Marc Hodgins (mjh_ca) on 2010-12-02T23:37:49.000+0000

The original patch could use a couple of improvements before going into trunk. First, the optimization should be applied in Zend_Mime::_encodeQuotedPrintable() because this makes it available for calls to Zend_Mime::encodeQuotedPrintable() as well as ::encode().

Also, Marc Bennewitz noted, PHP5.3 now includes quoted_printable_encode(). I have benchmarked this and it is even faster than using the IMAP extension. So, IMO the ideal solution here is to test for quoted_printable_encode(), then test for imap_8bit(), then fall back to the existing behavior. Speed tests from the benchmark (with 5000 iterations):

imap_8bit() is 145.0137 seconds faster than Zend_Mime!
It is 42.36 times faster
quoted_printable_encode() is 145.3856 seconds faster than Zend_Mime!
It is 47.39 times faster

Attaching two files:

Revised benchmark script which includes testing of quoted_printable_encode(), and

Revised patch which:

Moves the fix to Zend_Mime::_encodeQuotedPrintable()

Modifies the behavior to try quoted_printable_encode(), then fall back to imap_8bit(), then fall back to existing internal encoding behavior.

Adds a note to the documentation about how enabling the IMAP extension on PHP < 5.3 will result in a speedup.

Adds a test to tests/Zend/MimeTest.php to ensure that calls optimized to these faster PHP functions as well as the internal ability of Zend_Mime to handle quoted-printable encoding are tested no matter what platform or extensions are active when the tests are run.

If someone could test this patch by running tests/Zend/MimeTest on PHP5.2 that would be great as I've only tested this on PHP5.3.

Posted by Marc Hodgins (mjh_ca) on 2010-12-02T23:40:16.000+0000

Targeting for next mini release since the patch is backwards-compatible and fixes a performance bottleneck.

Posted by Jonas Wüste (jwueste) on 2010-12-03T00:05:09.000+0000

I've noticed a needed modification in this patch.
Instead of directly returning the result of imap_8bit() or quoted_printable_encode() you have to replace the lineendings "\r\n" by "$EOL, which defaults to "\n".
Without this modification the lineends in the mail are "\r\r\n".
When sending this mail with a SMTP-Server that tries to repair broken lineends (e.g. PowerMTA) the lineends are now "\r\n\r\n". This leads to misformatted (HTML-)mails.
So the function should look like this

@Jonas: Good catch. Hadn't noticed that the PHP methods do the line breaks for you. This was at odds with how Zend_Mime allows specifying custom lineLength and lineBreak, so I refactored the patch a little more to support it.

Also added a few additional tests that should have been in there to confirm lineLength and lineBreak behavior.