From b80b567335d16915e100c380c6c7db246fcf79e9 Mon Sep 17 00:00:00 2001 From: Elliott Eggleston Date: Tue, 5 Dec 2017 11:17:34 -0500 Subject: [PATCH] CRM-21521: fix nested multipart handling When for example a multipart-report email body's first part is multipart-related, extract the text correctly instead of crashing. This logic should handle all kinds of weird multipart nesting, up to MAIL_MAX_RECURSION levels deep. --- CRM/Utils/Mail/EmailProcessor.php | 154 ++++++--- .../CRM/Utils/Mail/EmailProcessorTest.php | 15 + .../Mail/data/bounces/test_nested_message.eml | 313 ++++++++++++++++++ 3 files changed, 433 insertions(+), 49 deletions(-) create mode 100644 tests/phpunit/CRM/Utils/Mail/data/bounces/test_nested_message.eml diff --git a/CRM/Utils/Mail/EmailProcessor.php b/CRM/Utils/Mail/EmailProcessor.php index f08fa56272e5..aefcb146df68 100644 --- a/CRM/Utils/Mail/EmailProcessor.php +++ b/CRM/Utils/Mail/EmailProcessor.php @@ -35,6 +35,7 @@ // before the 4.1 release define('EMAIL_ACTIVITY_TYPE_ID', NULL); define('MAIL_BATCH_SIZE', 50); +define('MAIL_MAX_RECURSION', 10); /** * Class CRM_Utils_Mail_EmailProcessor. @@ -286,55 +287,7 @@ public static function _process($civiMail, $dao, $is_create_activities) { $text = $mail->body->text; } elseif ($mail->body instanceof ezcMailMultipart) { - if ($mail->body instanceof ezcMailMultipartReport) { - $part = $mail->body->getMachinePart(); - if ($part instanceof ezcMailDeliveryStatus) { - foreach ($part->recipients as $rec) { - if (isset($rec["Diagnostic-Code"])) { - $text = $rec["Diagnostic-Code"]; - break; - } - elseif (isset($rec["Description"])) { - $text = $rec["Description"]; - break; - } - // no diagnostic info present - try getting the human readable part - elseif (isset($rec["Status"])) { - $text = $rec["Status"]; - $textpart = $mail->body->getReadablePart(); - if ($textpart != NULL and isset($textpart->text)) { - $text .= " " . $textpart->text; - } - else { - $text .= " Delivery failed but no diagnostic code or description."; - } - break; - } - } - } - elseif ($part != NULL and isset($part->text)) { - $text = $part->text; - } - elseif (($part = $mail->body->getReadablePart()) != NULL) { - $text = $part->text; - } - } - elseif ($mail->body instanceof ezcMailMultipartRelated) { - foreach ($mail->body->getRelatedParts() as $part) { - if (isset($part->subType) and $part->subType == 'plain') { - $text = $part->text; - break; - } - } - } - else { - foreach ($mail->body->getParts() as $part) { - if (isset($part->subType) and $part->subType == 'plain') { - $text = $part->text; - break; - } - } - } + $text = self::getTextFromMultipart($mail->body); } if ( @@ -475,4 +428,107 @@ public static function _process($civiMail, $dao, $is_create_activities) { } } + /** + * @param \ezcMailMultipart $multipart + * @param int $recursionLevel + * + * @return array + */ + protected static function getTextFromMultipart($multipart, $recursionLevel = 0) { + if ($recursionLevel >= MAIL_MAX_RECURSION) { + return NULL; + } + $recursionLevel += 1; + $text = NULL; + if ($multipart instanceof ezcMailMultipartReport) { + $text = self::getTextFromMulipartReport($multipart, $recursionLevel); + } + elseif ($multipart instanceof ezcMailMultipartRelated) { + $text = self::getTextFromMultipartRelated($multipart, $recursionLevel); + } + else { + foreach ($multipart->getParts() as $part) { + if (isset($part->subType) and $part->subType === 'plain') { + $text = $part->text; + } + elseif ($part instanceof ezcMailMultipart) { + $text = self::getTextFromMultipart($part); + } + if ($text) { + break; + } + } + } + return $text; + } + + /** + * @param \ezcMailMultipartRelated $related + * @param int $recursionLevel + * + * @return array + */ + protected static function getTextFromMultipartRelated($related, $recursionLevel) { + $text = NULL; + foreach ($related->getRelatedParts() as $part) { + if (isset($part->subType) and $part->subType === 'plain') { + $text = $part->text; + } + elseif ($part instanceof ezcMailMultipart) { + $text = self::getTextFromMultipart($part, $recursionLevel); + } + if ($text) { + break; + } + } + return $text; + } + + /** + * @param \ezcMailMultipartReport $multipart + * @param $recursionLevel + * + * @return array + */ + protected static function getTextFromMulipartReport($multipart, $recursionLevel) { + $text = NULL; + $part = $multipart->getMachinePart(); + if ($part instanceof ezcMailDeliveryStatus) { + foreach ($part->recipients as $rec) { + if (isset($rec["Diagnostic-Code"])) { + $text = $rec["Diagnostic-Code"]; + break; + } + elseif (isset($rec["Description"])) { + $text = $rec["Description"]; + break; + } + // no diagnostic info present - try getting the human readable part + elseif (isset($rec["Status"])) { + $text = $rec["Status"]; + $textpart = $multipart->getReadablePart(); + if ($textpart !== NULL and isset($textpart->text)) { + $text .= " " . $textpart->text; + } + else { + $text .= " Delivery failed but no diagnostic code or description."; + } + break; + } + } + } + elseif ($part !== NULL and isset($part->text)) { + $text = $part->text; + } + elseif (($part = $multipart->getReadablePart()) !== NULL) { + if (isset($part->text)) { + $text = $part->text; + } + elseif ($part instanceof ezcMailMultipart) { + $text = self::getTextFromMultipart($part, $recursionLevel); + } + } + return $text; + } + } diff --git a/tests/phpunit/CRM/Utils/Mail/EmailProcessorTest.php b/tests/phpunit/CRM/Utils/Mail/EmailProcessorTest.php index 217b4d4aeb0e..59a1d0c07844 100644 --- a/tests/phpunit/CRM/Utils/Mail/EmailProcessorTest.php +++ b/tests/phpunit/CRM/Utils/Mail/EmailProcessorTest.php @@ -69,6 +69,21 @@ public function testProcessingMultipartRelatedEmail() { $this->checkMailingBounces(1); } + /** + * Tests that a nested multipart email does not cause pain & misery & fatal errors. + * + * Sample anonymized from an email that broke bounce processing at Wikimedia + */ + public function testProcessingNestedMultipartEmail() { + $this->setUpMailing(); + $mail = 'test_nested_message.eml'; + + copy(__DIR__ . '/data/bounces/' . $mail, __DIR__ . '/data/mail/' . $mail); + $this->callAPISuccess('job', 'fetch_bounces', array()); + $this->assertFalse(file_exists(__DIR__ . '/data/mail/' . $mail)); + $this->checkMailingBounces(1); + } + /** * Test that a deleted email does not cause a hard fail. * diff --git a/tests/phpunit/CRM/Utils/Mail/data/bounces/test_nested_message.eml b/tests/phpunit/CRM/Utils/Mail/data/bounces/test_nested_message.eml new file mode 100644 index 000000000000..96caf13eebd8 --- /dev/null +++ b/tests/phpunit/CRM/Utils/Mail/data/bounces/test_nested_message.eml @@ -0,0 +1,313 @@ +Return-Path: <> +X-Original-To: b.2.1.aaaaaaaaaaaaaaaa@donate.example.org +Delivered-To: b.2.1.aaaaaaaaaaaaaaaa@example.com +Received: from mx1001.example.org (mx1001.example.org [127.0.0.1]) +by civicrm.example.org (Postfix) with ESMTPS id 381BD2E95DC +for ; Sun, 3 Dec 2017 11:29:12 +0000 (UTC) +Received: from mail-qt0-x241.example.org ([1111:2222:3333:c0d::241]:34862) +by mx1001.example.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) +(Exim 4.84_2) +id 1eLSSM-0003Vj-7E +for b.aaaaaaaaaaaaaaaa.b322af9943c6facb@donate.example.org; Sun, 03 Dec 2017 11:29:12 +0000 +Received: by mail-qt0-x241.example.org with SMTP id u10so18073433qtg.2 + for ; Sun, 03 Dec 2017 03:29:10 -0800 (PST) +X-Received: by 127.0.0.1 with SMTP id f2mr16998556qth.140.1512300550024; + Sun, 03 Dec 2017 03:29:10 -0800 (PST) +Content-Type: multipart/report; boundary="f403043ae60413e73f055f6de970"; report-type=delivery-status +Received: by 127.0.0.1 with SMTP id xxxxxxxx.140; Sun, 03 Dec 2017 +03:29:10 -0800 (PST) +From: Mail Delivery Subsystem +To: b.2.1.aaaaaaaaaaaaaaaa@example.com +Auto-Submitted: auto-replied +Subject: Delivery Status Notification (Failure) +References: +In-Reply-To: +X-Failed-Recipients: bob@example.com +Message-ID: +Date: Sun, 03 Dec 2017 03:29:10 -0800 (PST) + +--f403043ae60413e73f055f6de970 +Content-Type: multipart/related; boundary="f403043ae60413e7e5055f6de971" + +--f403043ae60413e7e5055f6de971 +Content-Type: multipart/alternative; boundary="f403043ae60413e7eb055f6de972" + +--f403043ae60413e7eb055f6de972 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: quoted-printable + + +** Message not delivered ** + +There was a problem delivering your message to bob@example.com. See the te= +chnical details below, or try resending in a few minutes. + +Learn more here: https://checkspam.secureserver.net/?sid=xxxxxxxxxxxx= +1&mid=xxxxxxxxxxxxxxxx +(Warning: This link will take you to a third-party site) + +The response from the remote server was: +552 5.2.0 aaaaaaaaaaaaaaaa - bbbbbbbbbbbbbbbb This message has been = +rejected due to content judged to be spam by the internet community IB212 -= +If you feel this is in error, please submit a request using the following = +page. + +--f403043ae60413e7eb055f6de972 +Content-Type: text/html; charset="UTF-8" +Content-Transfer-Encoding: quoted-printable + + + + + + + + + + + + +
+ + +
++=3D"Error + + + + + +

+Message not delivered +

+There was a problem delivering your message to bob@example.com. See the technical details = +below, or try resending in a few minutes. +
+LEARN MORE +
+3D"War= +This link will take you to a third-party site +
+
+
+The response from the remote server was:
+

+552 5.2.0 aaaaaaaaaaaaaaaa - bbbbbbbbbbbbbbbbbbb This message has been = +rejected due to content judged to be spam by the internet community IB212 -= +If you feel this is in error, please submit a request using the following = +page. <https://checkspam.secureserver.net/?sid=xxxxxxxx&m= +id=xxxxxxxxxxxxxxxx> +

+
+ + + +--f403043ae60413e7eb055f6de972-- +--f403043ae60413e7e5055f6de971 +Content-Type: image/png; name="icon.png" +Content-Disposition: attachment; filename="icon.png" +Content-Transfer-Encoding: base64 +Content-ID: + +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 +--f403043ae60413e7e5055f6de971 +Content-Type: image/png; name="warning_triangle.png" +Content-Disposition: attachment; filename="warning_triangle.png" +Content-Transfer-Encoding: base64 +Content-ID: + +iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAYxJREFUSA3t +VLFOhEAUBKLFXXMd3VlqZXGJrX6AP+AHWFsZ4CpDoQmBhMTyfkdbEwsrLaiJnQ1XmIAzCuTt3nKs +xk432fB2dmYeb9+C4/ypEQTBKed3ivZsyavVatd13ZyTsa3OOkFRFBdN0xxwMrZN4NoQ4zj2q6p6 +gfmMfFTxNp1O94G/jumtKoD5TWdOQ8bExsy5P1rBcrlc1HX9AFPlZVBF7XneUZIkj9sSKSITEea3 +ujl5xLhn0khsawJcyTMYHUuBjLlHjsT0eDBBnucTkDMpyLLM5ZQYOS1Xg7+WgwnKsoxAmRtVKjhv +uSrarowJoijaQ/mhUWEAyaXGsOUYE0CQgswjsh2TVrPB18/TQdPY1LsNph1wgh7dS6pSAb5MD/d7 +9OpJAxlTSw+JKYv1en2OUheSIOOBW9RTqKVHDyDoE6BJM3w413LzJzE96NVpd7oA2a8Q+93a9ER/ +GhOuYX7rdUn8s8lhGPI3/IS19X9eM9WX7+jHYZqmz90R5b9ozmR8UXr+j/ET+ADSfKckAihanAAA +AABJRU5ErkJggg== +--f403043ae60413e7e5055f6de971-- +--f403043ae60413e73f055f6de970 +Content-Type: message/global-delivery-status + +Reporting-MTA: dns; example.com +Received-From-MTA: dns; b.aaaaaaaaaaaaaaaa.b322af9943c6facb@donate.example.org +Arrival-Date: Sun, 03 Dec 2017 03:29:08 -0800 (PST) +X-Original-Message-ID: + +Final-Recipient: rfc822; bob@example.com +Action: failed +Status: 5.2.0 +Remote-MTA: dns; smtp.secureserver.net (22.33.44.55, the relay for the domain.) +Diagnostic-Code: smtp; 552 5.2.0 aaaaaaaaaaaaaaaaa - bbbbbbbbbbbbbbbbbbb This message has been rejected due to content judged to b +e spam by the internet community IB212 - If you feel this is in error, please submit a request using the following page. +Last-Attempt-Date: Sun, 03 Dec 2017 03:29:10 -0800 (PST) + +--f403043ae60413e73f055f6de970 +Content-Type: message/rfc822 + +X-Received: by 127.0.0.1 with SMTP id f2mr16998507qth.140.1512300548827; + Sun, 03 Dec 2017 03:29:08 -0800 (PST) +Return-Path: +Received: from civicrm.example.org (civicrm.example.org. [111.222.33.44]) + by mx.example.org with ESMTPS id w61si1072744qte.335.2017.12.22.33.44.55 + for + (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); + Sun, 03 Dec 2017 03:29:08 -0800 (PST) +Received: by civicrm.example.org (Postfix, from userid 33) +id 5657F2E7E23; Sun, 3 Dec 2017 11:29:08 +0000 (UTC) +To: Bob The Bobby one +Subject: =?utf-8?Q?We=E2=80=99re_here_for_you._Thanks_for_being_here_for_us?= +X-PHP-Originating-Script: 0:class.phpmailer.php +Date: Sun, 3 Dec 2017 03:29:08 -0800 +From: Donations Manager +Reply-To: Donations Manager +Message-ID: +X-Mailer: PHPMailer 5.2.25 (https://github.com/PHPMailer/PHPMailer) +List-Unsubscribe: +MIME-Version: 1.0 +Content-Type: multipart/alternative; +boundary="b1_xxxxxxxxxxxxxxxxxxxxxxxx" + +This is a multi-part message in MIME format. + +--b1_xxxxxxxxxxxxxxxxxxxxxxxx +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: quoted-printable + +Dear Bob, You sent us lots of money, we like money. + +--b1_xxxxxxxxxxxxxxxxxxxxxxxx +Content-Type: text/html; charset=utf-8 +Content-Transfer-Encoding: quoted-printable + + + + + + + +

Dear Bob,

+ + +

Thank you for supporting us and sending us lots of money.

+ +----- Message truncated ----- + +--f403043ae60413e73f055f6de970--