From eeb97db283aa9dee120a5d3ffd93c2b044dc9336 Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 20 Dec 2012 11:11:15 -0800 Subject: [PATCH] Fix EncodeQ implementation in PHPMailer, and provide SSL/TLS options Summary: See https://github.com/facebook/phabricator/commit/f5c2a2ab4bbe6317993fbcb406a86993e6ab75e0#commitcomment-2333247 Copy of working implementation from PHPMailerLite. Also expose the SSL/TLS options. Test Plan: Switched to this mailer, configured Gmail SMTP, sent email. Verified email arrived intact. Reviewers: btrahan, vrana Reviewed By: btrahan CC: aran, mbeck Differential Revision: https://secure.phabricator.com/D4239 --- conf/default.conf.php | 17 +++++++---- externals/phpmailer/class.phpmailer.php | 28 +++++++++++++++---- ...atorMailImplementationPHPMailerAdapter.php | 5 ++++ 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/conf/default.conf.php b/conf/default.conf.php index 80290c3de8..077dd9677e 100644 --- a/conf/default.conf.php +++ b/conf/default.conf.php @@ -291,13 +291,12 @@ return array( // mostly never arrive. 'metamta.can-send-as-user' => false, - // Adapter class to use to transmit mail to the MTA. The default uses // PHPMailerLite, which will invoke "sendmail". This is appropriate // if sendmail actually works on your host, but if you haven't configured mail - // it may not be so great. You can also use Amazon SES, by changing this to - // 'PhabricatorMailImplementationAmazonSESAdapter', signing up for SES, and - // filling in your 'amazon-ses.access-key' and 'amazon-ses.secret-key' below. + // it may not be so great. A number of other mailers are available (e.g., SES, + // SendGrid, SMTP, custom mailers), consult "Configuring Outbound Email" in + // the documentation for details. 'metamta.mail-adapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter', @@ -317,12 +316,18 @@ return array( 'metamta.user-address-format' => 'full', // If you're using PHPMailer to send email, provide the mailer and options - // here. PHPMailer is a superior to PHPMailerLite and provides more mailers. - // You need it when you want to use SMTP instead of sendmail as the mailer. + // here. PHPMailer is much more enormous than PHPMailerLite, and provides more + // mailers and greater enormity. You need it when you want to use SMTP + // instead of sendmail as the mailer. 'phpmailer.mailer' => 'smtp', 'phpmailer.smtp-host' => '', 'phpmailer.smtp-port' => 25, + // When using PHPMailer with SMTP, you can set this to one of "tls" or "ssl" + // to use TLS or SSL. Leave it blank for vanilla SMTP. If you're sending + // via Gmail, set it to "ssl". + 'phpmailer.smtp-protocol' => '', + // Set following if your smtp server requires authentication. 'phpmailer.smtp-user' => null, 'phpmailer.smtp-password' => null, diff --git a/externals/phpmailer/class.phpmailer.php b/externals/phpmailer/class.phpmailer.php index 56007cdfa1..0c62ddbe2c 100644 --- a/externals/phpmailer/class.phpmailer.php +++ b/externals/phpmailer/class.phpmailer.php @@ -1710,6 +1710,13 @@ class PHPMailer { return $out; } + /** + * NOTE: Phabricator patch to remove use of "/e". See D2147. + */ + private function encodeQCallback(array $matches) { + return '='.sprintf('%02X', ord($matches[1])); + } + /** * Encode string to q encoding. * @link http://tools.ietf.org/html/rfc2047 @@ -1719,21 +1726,32 @@ class PHPMailer { * @return string */ public function EncodeQ ($str, $position = 'text') { + + // NOTE: Phabricator patch to remove use of "/e". See D2147. + // There should not be any EOL in the string $encoded = preg_replace('/[\r\n]*/', '', $str); switch (strtolower($position)) { case 'phrase': - $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/", "'='.sprintf('%02X', ord('\\1'))", $encoded); + $encoded = preg_replace_callback( + "/([^A-Za-z0-9!*+\/ -])/", + array($this, 'encodeQCallback'), + $encoded); break; case 'comment': - $encoded = preg_replace("/([\(\)\"])/", "'='.sprintf('%02X', ord('\\1'))", $encoded); + $encoded = preg_replace_callback( + "/([\(\)\"])/", + array($this, 'encodeQCallback'), + $encoded); + break; case 'text': default: // Replace every high ascii, control =, ? and _ characters - //TODO using /e (equivalent to eval()) is probably not a good idea - $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/', - "'='.sprintf('%02X', ord('\\1'))", $encoded); + $encoded = preg_replace_callback( + '/([\000-\011\013\014\016-\037\075\077\137\177-\377])/', + array($this, 'encodeQCallback'), + $encoded); break; } diff --git a/src/applications/metamta/adapter/PhabricatorMailImplementationPHPMailerAdapter.php b/src/applications/metamta/adapter/PhabricatorMailImplementationPHPMailerAdapter.php index bfb24f74f3..8c401842b6 100644 --- a/src/applications/metamta/adapter/PhabricatorMailImplementationPHPMailerAdapter.php +++ b/src/applications/metamta/adapter/PhabricatorMailImplementationPHPMailerAdapter.php @@ -30,6 +30,11 @@ final class PhabricatorMailImplementationPHPMailerAdapter $this->mailer->Password = PhabricatorEnv::getEnvConfig('phpmailer.smtp-password'); } + + $protocol = PhabricatorEnv::getEnvConfig('phpmailer.smtp-protocol'); + if ($protocol) { + $this->mailer->SMTPSecure = $protocol; + } } else if ($mailer == 'sendmail') { $this->mailer->IsSendmail(); } else {