Skip to content

Commit c3cafff

Browse files
author
epriestley
committedJan 16, 2019
Update the "SES" and "sendmail" mailers for the new API; remove "encoding"
Summary: Ref T13222. Ref T920. This is the last of the upstream adapter updates. Test Plan: - Sent mail with SES. - Sent mail with "sendmail". I don't have sendmail actually configured to an upstream MTA so I'm not 100% sure this worked, but the `sendmail` binary didn't complain and almost all of the code is shared with SES, so I'm reasonably confident this actually works. Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13222, T920 Differential Revision: https://secure.phabricator.com/D19965
1 parent 43a6f34 commit c3cafff

File tree

5 files changed

+136
-114
lines changed

5 files changed

+136
-114
lines changed
 

‎externals/phpmailer/class.phpmailer-lite.php

+96
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,102 @@
4242

4343
class PHPMailerLite {
4444

45+
public static function newFromMessage(
46+
PhabricatorMailExternalMessage $message) {
47+
48+
$mailer = new self($use_exceptions = true);
49+
50+
// By default, PHPMailerLite sends one mail per recipient. We handle
51+
// combining or separating To and Cc higher in the stack, so tell it to
52+
// send mail exactly like we ask.
53+
$mailer->SingleTo = false;
54+
55+
$mailer->CharSet = 'utf-8';
56+
$mailer->Encoding = 'base64';
57+
58+
$subject = $message->getSubject();
59+
if ($subject !== null) {
60+
$mailer->Subject = $subject;
61+
}
62+
63+
$from_address = $message->getFromAddress();
64+
if ($from_address) {
65+
$mailer->SetFrom(
66+
$from_address->getAddress(),
67+
(string)$from_address->getDisplayName(),
68+
$crazy_side_effects = false);
69+
}
70+
71+
$reply_address = $message->getReplyToAddress();
72+
if ($reply_address) {
73+
$mailer->AddReplyTo(
74+
$reply_address->getAddress(),
75+
(string)$reply_address->getDisplayName());
76+
}
77+
78+
$to_addresses = $message->getToAddresses();
79+
if ($to_addresses) {
80+
foreach ($to_addresses as $address) {
81+
$mailer->AddAddress(
82+
$address->getAddress(),
83+
(string)$address->getDisplayName());
84+
}
85+
}
86+
87+
$cc_addresses = $message->getCCAddresses();
88+
if ($cc_addresses) {
89+
foreach ($cc_addresses as $address) {
90+
$mailer->AddCC(
91+
$address->getAddress(),
92+
(string)$address->getDisplayName());
93+
}
94+
}
95+
96+
$headers = $message->getHeaders();
97+
if ($headers) {
98+
foreach ($headers as $header) {
99+
$name = $header->getName();
100+
$value = $header->getValue();
101+
102+
if (phutil_utf8_strtolower($name) === 'message-id') {
103+
$mailer->MessageID = $value;
104+
} else {
105+
$mailer->AddCustomHeader("{$name}: {$value}");
106+
}
107+
}
108+
}
109+
110+
$attachments = $message->getAttachments();
111+
if ($attachments) {
112+
foreach ($attachments as $attachment) {
113+
$mailer->AddStringAttachment(
114+
$attachment->getData(),
115+
$attachment->getFilename(),
116+
'base64',
117+
$attachment->getMimeType());
118+
}
119+
}
120+
121+
$text_body = $message->getTextBody();
122+
if ($text_body !== null) {
123+
$mailer->Body = $text_body;
124+
}
125+
126+
$html_body = $message->getHTMLBody();
127+
if ($html_body !== null) {
128+
$mailer->IsHTML(true);
129+
$mailer->Body = $html_body;
130+
if ($text_body !== null) {
131+
$mailer->AltBody = $text_body;
132+
}
133+
}
134+
135+
return $mailer;
136+
}
137+
138+
139+
140+
45141
/////////////////////////////////////////////////
46142
// PROPERTIES, PUBLIC
47143
/////////////////////////////////////////////////

‎src/__phutil_library_map__.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -9222,7 +9222,7 @@
92229222
'PhabricatorMacroTransactionType' => 'PhabricatorModularTransactionType',
92239223
'PhabricatorMacroViewController' => 'PhabricatorMacroController',
92249224
'PhabricatorMailAdapter' => 'Phobject',
9225-
'PhabricatorMailAmazonSESAdapter' => 'PhabricatorMailSendmailAdapter',
9225+
'PhabricatorMailAmazonSESAdapter' => 'PhabricatorMailAdapter',
92269226
'PhabricatorMailAttachment' => 'Phobject',
92279227
'PhabricatorMailConfigTestCase' => 'PhabricatorTestCase',
92289228
'PhabricatorMailEmailEngine' => 'PhabricatorMailMessageEngine',

‎src/applications/metamta/adapter/PhabricatorMailAdapter.php

+2-8
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,8 @@ final public static function getAllAdapters() {
2323
->execute();
2424
}
2525

26-
/* abstract */ public function getSupportedMessageTypes() {
27-
throw new PhutilMethodNotImplementedException();
28-
}
29-
30-
/* abstract */ public function sendMessage(
31-
PhabricatorMailExternalMessage $message) {
32-
throw new PhutilMethodNotImplementedException();
33-
}
26+
abstract public function getSupportedMessageTypes();
27+
abstract public function sendMessage(PhabricatorMailExternalMessage $message);
3428

3529
/**
3630
* Return true if this adapter supports setting a "Message-ID" when sending

‎src/applications/metamta/adapter/PhabricatorMailAmazonSESAdapter.php

+23-11
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
<?php
22

33
final class PhabricatorMailAmazonSESAdapter
4-
extends PhabricatorMailSendmailAdapter {
4+
extends PhabricatorMailAdapter {
55

66
const ADAPTERTYPE = 'ses';
77

8-
private $message;
9-
private $isHTML;
10-
11-
public function prepareForSend() {
12-
parent::prepareForSend();
13-
$this->mailer->Mailer = 'amazon-ses';
14-
$this->mailer->customMailer = $this;
8+
public function getSupportedMessageTypes() {
9+
return array(
10+
PhabricatorMailEmailMessage::MESSAGETYPE,
11+
);
1512
}
1613

1714
public function supportsMessageIDHeader() {
18-
// Amazon SES will ignore any Message-ID we provide.
1915
return false;
2016
}
2117

@@ -26,7 +22,6 @@ protected function validateOptions(array $options) {
2622
'access-key' => 'string',
2723
'secret-key' => 'string',
2824
'endpoint' => 'string',
29-
'encoding' => 'string',
3025
));
3126
}
3227

@@ -35,10 +30,27 @@ public function newDefaultOptions() {
3530
'access-key' => null,
3631
'secret-key' => null,
3732
'endpoint' => null,
38-
'encoding' => 'base64',
3933
);
4034
}
4135

36+
/**
37+
* @phutil-external-symbol class PHPMailerLite
38+
*/
39+
public function sendMessage(PhabricatorMailExternalMessage $message) {
40+
$root = phutil_get_library_root('phabricator');
41+
$root = dirname($root);
42+
require_once $root.'/externals/phpmailer/class.phpmailer-lite.php';
43+
44+
$mailer = PHPMailerLite::newFromMessage($message);
45+
46+
$mailer->Mailer = 'amazon-ses';
47+
$mailer->customMailer = $this;
48+
49+
$mailer->Send();
50+
}
51+
52+
53+
4254
/**
4355
* @phutil-external-symbol class SimpleEmailService
4456
*/
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
<?php
22

3-
/**
4-
* TODO: Should be final, but inherited by SES.
5-
*
6-
* @concrete-extensible
7-
*/
8-
class PhabricatorMailSendmailAdapter
3+
final class PhabricatorMailSendmailAdapter
94
extends PhabricatorMailAdapter {
105

116
const ADAPTERTYPE = 'sendmail';
127

13-
protected $mailer;
8+
9+
public function getSupportedMessageTypes() {
10+
return array(
11+
PhabricatorMailEmailMessage::MESSAGETYPE,
12+
);
13+
}
14+
15+
public function supportsMessageIDHeader() {
16+
return true;
17+
}
1418

1519
protected function validateOptions(array $options) {
1620
PhutilTypeSpec::checkMap(
@@ -29,97 +33,13 @@ public function newDefaultOptions() {
2933
/**
3034
* @phutil-external-symbol class PHPMailerLite
3135
*/
32-
public function prepareForSend() {
36+
public function sendMessage(PhabricatorMailExternalMessage $message) {
3337
$root = phutil_get_library_root('phabricator');
3438
$root = dirname($root);
3539
require_once $root.'/externals/phpmailer/class.phpmailer-lite.php';
36-
$this->mailer = new PHPMailerLite($use_exceptions = true);
37-
$this->mailer->CharSet = 'utf-8';
38-
39-
$encoding = $this->getOption('encoding');
40-
$this->mailer->Encoding = $encoding;
41-
42-
// By default, PHPMailerLite sends one mail per recipient. We handle
43-
// combining or separating To and Cc higher in the stack, so tell it to
44-
// send mail exactly like we ask.
45-
$this->mailer->SingleTo = false;
46-
}
47-
48-
public function supportsMessageIDHeader() {
49-
return true;
50-
}
51-
52-
public function setFrom($email, $name = '') {
53-
$this->mailer->SetFrom($email, $name, $crazy_side_effects = false);
54-
return $this;
55-
}
56-
57-
public function addReplyTo($email, $name = '') {
58-
$this->mailer->AddReplyTo($email, $name);
59-
return $this;
60-
}
61-
62-
public function addTos(array $emails) {
63-
foreach ($emails as $email) {
64-
$this->mailer->AddAddress($email);
65-
}
66-
return $this;
67-
}
68-
69-
public function addCCs(array $emails) {
70-
foreach ($emails as $email) {
71-
$this->mailer->AddCC($email);
72-
}
73-
return $this;
74-
}
75-
76-
public function addAttachment($data, $filename, $mimetype) {
77-
$this->mailer->AddStringAttachment(
78-
$data,
79-
$filename,
80-
'base64',
81-
$mimetype);
82-
return $this;
83-
}
84-
85-
public function addHeader($header_name, $header_value) {
86-
if (strtolower($header_name) == 'message-id') {
87-
$this->mailer->MessageID = $header_value;
88-
} else {
89-
$this->mailer->AddCustomHeader($header_name.': '.$header_value);
90-
}
91-
return $this;
92-
}
93-
94-
public function setBody($body) {
95-
$this->mailer->Body = $body;
96-
$this->mailer->IsHTML(false);
97-
return $this;
98-
}
99-
100-
101-
/**
102-
* Note: phpmailer-lite does NOT support sending messages with mixed version
103-
* (plaintext and html). So for now lets just use HTML if it's available.
104-
* @param $html
105-
*/
106-
public function setHTMLBody($html_body) {
107-
$this->mailer->Body = $html_body;
108-
$this->mailer->IsHTML(true);
109-
return $this;
110-
}
111-
112-
public function setSubject($subject) {
113-
$this->mailer->Subject = $subject;
114-
return $this;
115-
}
116-
117-
public function hasValidRecipients() {
118-
return true;
119-
}
12040

121-
public function send() {
122-
return $this->mailer->Send();
41+
$mailer = PHPMailerLite::newFromMessage($message);
42+
$mailer->Send();
12343
}
12444

12545
}

0 commit comments

Comments
 (0)
Failed to load comments.