Update Postmark adapter for multiple mail media
Summary: Depends on D19955. Ref T920. Ref T5969. Update Postmark to accept new Message objects. Also: - Update the inbound whitelist. - Add a little support for `media` configuration. - Add a service call timeout (see T5969). - Drop the needless word "Implementation" from the Adapter class tree. I could call these "Mailers" instead of "Adapters", but then we get "PhabricatorMailMailer" which feels questionable. Test Plan: Used `bin/mail send-test` to send mail via Postmark with various options (mulitple recipients, text vs html, attachments). Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T5969, T920 Differential Revision: https://secure.phabricator.com/D19956
This commit is contained in:
parent
b5797ce60a
commit
a8657e6ab6
|
@ -3387,6 +3387,8 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorMacroTransactionQuery' => 'applications/macro/query/PhabricatorMacroTransactionQuery.php',
|
'PhabricatorMacroTransactionQuery' => 'applications/macro/query/PhabricatorMacroTransactionQuery.php',
|
||||||
'PhabricatorMacroTransactionType' => 'applications/macro/xaction/PhabricatorMacroTransactionType.php',
|
'PhabricatorMacroTransactionType' => 'applications/macro/xaction/PhabricatorMacroTransactionType.php',
|
||||||
'PhabricatorMacroViewController' => 'applications/macro/controller/PhabricatorMacroViewController.php',
|
'PhabricatorMacroViewController' => 'applications/macro/controller/PhabricatorMacroViewController.php',
|
||||||
|
'PhabricatorMailAdapter' => 'applications/metamta/adapter/PhabricatorMailAdapter.php',
|
||||||
|
'PhabricatorMailAmazonSESAdapter' => 'applications/metamta/adapter/PhabricatorMailAmazonSESAdapter.php',
|
||||||
'PhabricatorMailAttachment' => 'applications/metamta/message/PhabricatorMailAttachment.php',
|
'PhabricatorMailAttachment' => 'applications/metamta/message/PhabricatorMailAttachment.php',
|
||||||
'PhabricatorMailConfigTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMailConfigTestCase.php',
|
'PhabricatorMailConfigTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMailConfigTestCase.php',
|
||||||
'PhabricatorMailEmailEngine' => 'applications/metamta/engine/PhabricatorMailEmailEngine.php',
|
'PhabricatorMailEmailEngine' => 'applications/metamta/engine/PhabricatorMailEmailEngine.php',
|
||||||
|
@ -3397,14 +3399,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorMailEngineExtension' => 'applications/metamta/engine/PhabricatorMailEngineExtension.php',
|
'PhabricatorMailEngineExtension' => 'applications/metamta/engine/PhabricatorMailEngineExtension.php',
|
||||||
'PhabricatorMailExternalMessage' => 'applications/metamta/message/PhabricatorMailExternalMessage.php',
|
'PhabricatorMailExternalMessage' => 'applications/metamta/message/PhabricatorMailExternalMessage.php',
|
||||||
'PhabricatorMailHeader' => 'applications/metamta/message/PhabricatorMailHeader.php',
|
'PhabricatorMailHeader' => 'applications/metamta/message/PhabricatorMailHeader.php',
|
||||||
'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAdapter.php',
|
'PhabricatorMailMailgunAdapter' => 'applications/metamta/adapter/PhabricatorMailMailgunAdapter.php',
|
||||||
'PhabricatorMailImplementationAmazonSESAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAmazonSESAdapter.php',
|
|
||||||
'PhabricatorMailImplementationMailgunAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationMailgunAdapter.php',
|
|
||||||
'PhabricatorMailImplementationPHPMailerAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerAdapter.php',
|
|
||||||
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerLiteAdapter.php',
|
|
||||||
'PhabricatorMailImplementationPostmarkAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPostmarkAdapter.php',
|
|
||||||
'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationSendGridAdapter.php',
|
|
||||||
'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationTestAdapter.php',
|
|
||||||
'PhabricatorMailManagementListInboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementListInboundWorkflow.php',
|
'PhabricatorMailManagementListInboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementListInboundWorkflow.php',
|
||||||
'PhabricatorMailManagementListOutboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementListOutboundWorkflow.php',
|
'PhabricatorMailManagementListOutboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementListOutboundWorkflow.php',
|
||||||
'PhabricatorMailManagementReceiveTestWorkflow' => 'applications/metamta/management/PhabricatorMailManagementReceiveTestWorkflow.php',
|
'PhabricatorMailManagementReceiveTestWorkflow' => 'applications/metamta/management/PhabricatorMailManagementReceiveTestWorkflow.php',
|
||||||
|
@ -3422,14 +3417,19 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingSelfEmailHeraldAction.php',
|
'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingSelfEmailHeraldAction.php',
|
||||||
'PhabricatorMailOutboundRoutingSelfNotificationHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingSelfNotificationHeraldAction.php',
|
'PhabricatorMailOutboundRoutingSelfNotificationHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingSelfNotificationHeraldAction.php',
|
||||||
'PhabricatorMailOutboundStatus' => 'applications/metamta/constants/PhabricatorMailOutboundStatus.php',
|
'PhabricatorMailOutboundStatus' => 'applications/metamta/constants/PhabricatorMailOutboundStatus.php',
|
||||||
|
'PhabricatorMailPHPMailerAdapter' => 'applications/metamta/adapter/PhabricatorMailPHPMailerAdapter.php',
|
||||||
|
'PhabricatorMailPHPMailerLiteAdapter' => 'applications/metamta/adapter/PhabricatorMailPHPMailerLiteAdapter.php',
|
||||||
|
'PhabricatorMailPostmarkAdapter' => 'applications/metamta/adapter/PhabricatorMailPostmarkAdapter.php',
|
||||||
'PhabricatorMailPropertiesDestructionEngineExtension' => 'applications/metamta/engineextension/PhabricatorMailPropertiesDestructionEngineExtension.php',
|
'PhabricatorMailPropertiesDestructionEngineExtension' => 'applications/metamta/engineextension/PhabricatorMailPropertiesDestructionEngineExtension.php',
|
||||||
'PhabricatorMailReceiver' => 'applications/metamta/receiver/PhabricatorMailReceiver.php',
|
'PhabricatorMailReceiver' => 'applications/metamta/receiver/PhabricatorMailReceiver.php',
|
||||||
'PhabricatorMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorMailReceiverTestCase.php',
|
'PhabricatorMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorMailReceiverTestCase.php',
|
||||||
'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php',
|
'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php',
|
||||||
'PhabricatorMailRoutingRule' => 'applications/metamta/constants/PhabricatorMailRoutingRule.php',
|
'PhabricatorMailRoutingRule' => 'applications/metamta/constants/PhabricatorMailRoutingRule.php',
|
||||||
|
'PhabricatorMailSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailSendGridAdapter.php',
|
||||||
'PhabricatorMailSetupCheck' => 'applications/config/check/PhabricatorMailSetupCheck.php',
|
'PhabricatorMailSetupCheck' => 'applications/config/check/PhabricatorMailSetupCheck.php',
|
||||||
'PhabricatorMailStamp' => 'applications/metamta/stamp/PhabricatorMailStamp.php',
|
'PhabricatorMailStamp' => 'applications/metamta/stamp/PhabricatorMailStamp.php',
|
||||||
'PhabricatorMailTarget' => 'applications/metamta/replyhandler/PhabricatorMailTarget.php',
|
'PhabricatorMailTarget' => 'applications/metamta/replyhandler/PhabricatorMailTarget.php',
|
||||||
|
'PhabricatorMailTestAdapter' => 'applications/metamta/adapter/PhabricatorMailTestAdapter.php',
|
||||||
'PhabricatorMailUtil' => 'applications/metamta/util/PhabricatorMailUtil.php',
|
'PhabricatorMailUtil' => 'applications/metamta/util/PhabricatorMailUtil.php',
|
||||||
'PhabricatorMainMenuBarExtension' => 'view/page/menu/PhabricatorMainMenuBarExtension.php',
|
'PhabricatorMainMenuBarExtension' => 'view/page/menu/PhabricatorMainMenuBarExtension.php',
|
||||||
'PhabricatorMainMenuSearchView' => 'view/page/menu/PhabricatorMainMenuSearchView.php',
|
'PhabricatorMainMenuSearchView' => 'view/page/menu/PhabricatorMainMenuSearchView.php',
|
||||||
|
@ -9221,6 +9221,8 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorMacroTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
'PhabricatorMacroTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||||
'PhabricatorMacroTransactionType' => 'PhabricatorModularTransactionType',
|
'PhabricatorMacroTransactionType' => 'PhabricatorModularTransactionType',
|
||||||
'PhabricatorMacroViewController' => 'PhabricatorMacroController',
|
'PhabricatorMacroViewController' => 'PhabricatorMacroController',
|
||||||
|
'PhabricatorMailAdapter' => 'Phobject',
|
||||||
|
'PhabricatorMailAmazonSESAdapter' => 'PhabricatorMailPHPMailerLiteAdapter',
|
||||||
'PhabricatorMailAttachment' => 'Phobject',
|
'PhabricatorMailAttachment' => 'Phobject',
|
||||||
'PhabricatorMailConfigTestCase' => 'PhabricatorTestCase',
|
'PhabricatorMailConfigTestCase' => 'PhabricatorTestCase',
|
||||||
'PhabricatorMailEmailEngine' => 'PhabricatorMailMessageEngine',
|
'PhabricatorMailEmailEngine' => 'PhabricatorMailMessageEngine',
|
||||||
|
@ -9231,14 +9233,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorMailEngineExtension' => 'Phobject',
|
'PhabricatorMailEngineExtension' => 'Phobject',
|
||||||
'PhabricatorMailExternalMessage' => 'Phobject',
|
'PhabricatorMailExternalMessage' => 'Phobject',
|
||||||
'PhabricatorMailHeader' => 'Phobject',
|
'PhabricatorMailHeader' => 'Phobject',
|
||||||
'PhabricatorMailImplementationAdapter' => 'Phobject',
|
'PhabricatorMailMailgunAdapter' => 'PhabricatorMailAdapter',
|
||||||
'PhabricatorMailImplementationAmazonSESAdapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter',
|
|
||||||
'PhabricatorMailImplementationMailgunAdapter' => 'PhabricatorMailImplementationAdapter',
|
|
||||||
'PhabricatorMailImplementationPHPMailerAdapter' => 'PhabricatorMailImplementationAdapter',
|
|
||||||
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter',
|
|
||||||
'PhabricatorMailImplementationPostmarkAdapter' => 'PhabricatorMailImplementationAdapter',
|
|
||||||
'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter',
|
|
||||||
'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter',
|
|
||||||
'PhabricatorMailManagementListInboundWorkflow' => 'PhabricatorMailManagementWorkflow',
|
'PhabricatorMailManagementListInboundWorkflow' => 'PhabricatorMailManagementWorkflow',
|
||||||
'PhabricatorMailManagementListOutboundWorkflow' => 'PhabricatorMailManagementWorkflow',
|
'PhabricatorMailManagementListOutboundWorkflow' => 'PhabricatorMailManagementWorkflow',
|
||||||
'PhabricatorMailManagementReceiveTestWorkflow' => 'PhabricatorMailManagementWorkflow',
|
'PhabricatorMailManagementReceiveTestWorkflow' => 'PhabricatorMailManagementWorkflow',
|
||||||
|
@ -9256,14 +9251,19 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction',
|
'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction',
|
||||||
'PhabricatorMailOutboundRoutingSelfNotificationHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction',
|
'PhabricatorMailOutboundRoutingSelfNotificationHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction',
|
||||||
'PhabricatorMailOutboundStatus' => 'Phobject',
|
'PhabricatorMailOutboundStatus' => 'Phobject',
|
||||||
|
'PhabricatorMailPHPMailerAdapter' => 'PhabricatorMailAdapter',
|
||||||
|
'PhabricatorMailPHPMailerLiteAdapter' => 'PhabricatorMailAdapter',
|
||||||
|
'PhabricatorMailPostmarkAdapter' => 'PhabricatorMailAdapter',
|
||||||
'PhabricatorMailPropertiesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension',
|
'PhabricatorMailPropertiesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension',
|
||||||
'PhabricatorMailReceiver' => 'Phobject',
|
'PhabricatorMailReceiver' => 'Phobject',
|
||||||
'PhabricatorMailReceiverTestCase' => 'PhabricatorTestCase',
|
'PhabricatorMailReceiverTestCase' => 'PhabricatorTestCase',
|
||||||
'PhabricatorMailReplyHandler' => 'Phobject',
|
'PhabricatorMailReplyHandler' => 'Phobject',
|
||||||
'PhabricatorMailRoutingRule' => 'Phobject',
|
'PhabricatorMailRoutingRule' => 'Phobject',
|
||||||
|
'PhabricatorMailSendGridAdapter' => 'PhabricatorMailAdapter',
|
||||||
'PhabricatorMailSetupCheck' => 'PhabricatorSetupCheck',
|
'PhabricatorMailSetupCheck' => 'PhabricatorSetupCheck',
|
||||||
'PhabricatorMailStamp' => 'Phobject',
|
'PhabricatorMailStamp' => 'Phobject',
|
||||||
'PhabricatorMailTarget' => 'Phobject',
|
'PhabricatorMailTarget' => 'Phobject',
|
||||||
|
'PhabricatorMailTestAdapter' => 'PhabricatorMailAdapter',
|
||||||
'PhabricatorMailUtil' => 'Phobject',
|
'PhabricatorMailUtil' => 'Phobject',
|
||||||
'PhabricatorMainMenuBarExtension' => 'Phobject',
|
'PhabricatorMainMenuBarExtension' => 'Phobject',
|
||||||
'PhabricatorMainMenuSearchView' => 'AphrontView',
|
'PhabricatorMainMenuSearchView' => 'AphrontView',
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
abstract class PhabricatorMailImplementationAdapter extends Phobject {
|
abstract class PhabricatorMailAdapter
|
||||||
|
extends Phobject {
|
||||||
|
|
||||||
private $key;
|
private $key;
|
||||||
private $priority;
|
private $priority;
|
||||||
|
private $media;
|
||||||
private $options = array();
|
private $options = array();
|
||||||
|
|
||||||
private $supportsInbound = true;
|
private $supportsInbound = true;
|
||||||
private $supportsOutbound = true;
|
private $supportsOutbound = true;
|
||||||
|
private $mediaMap;
|
||||||
|
|
||||||
final public function getAdapterType() {
|
final public function getAdapterType() {
|
||||||
return $this->getPhobjectClassConstant('ADAPTERTYPE');
|
return $this->getPhobjectClassConstant('ADAPTERTYPE');
|
||||||
|
@ -20,37 +23,67 @@ abstract class PhabricatorMailImplementationAdapter extends Phobject {
|
||||||
->execute();
|
->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* abstract */ public function getSupportedMessageTypes() {
|
||||||
|
throw new PhutilMethodNotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
abstract public function setFrom($email, $name = '');
|
/* abstract */ public function sendMessage(
|
||||||
abstract public function addReplyTo($email, $name = '');
|
PhabricatorMailExternalMessage $message) {
|
||||||
abstract public function addTos(array $emails);
|
throw new PhutilMethodNotImplementedException();
|
||||||
abstract public function addCCs(array $emails);
|
}
|
||||||
abstract public function addAttachment($data, $filename, $mimetype);
|
|
||||||
abstract public function addHeader($header_name, $header_value);
|
|
||||||
abstract public function setBody($plaintext_body);
|
|
||||||
abstract public function setHTMLBody($html_body);
|
|
||||||
abstract public function setSubject($subject);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some mailers, notably Amazon SES, do not support us setting a specific
|
* Return true if this adapter supports setting a "Message-ID" when sending
|
||||||
* Message-ID header.
|
* email.
|
||||||
|
*
|
||||||
|
* This is an ugly implementation detail because mail threading is a horrible
|
||||||
|
* mess, implemented differently by every client in existence.
|
||||||
*/
|
*/
|
||||||
abstract public function supportsMessageIDHeader();
|
public function supportsMessageIDHeader() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function supportsMessageType($message_type) {
|
||||||
|
if ($this->mediaMap === null) {
|
||||||
|
$media_map = $this->getSupportedMessageTypes();
|
||||||
|
$media_map = array_fuse($media_map);
|
||||||
|
|
||||||
/**
|
if ($this->media) {
|
||||||
* Send the message. Generally, this means connecting to some service and
|
$config_map = $this->media;
|
||||||
* handing data to it.
|
$config_map = array_fuse($config_map);
|
||||||
*
|
|
||||||
* If the adapter determines that the mail will never be deliverable, it
|
$media_map = array_intersect_key($media_map, $config_map);
|
||||||
* should throw a @{class:PhabricatorMetaMTAPermanentFailureException}.
|
}
|
||||||
*
|
|
||||||
* For temporary failures, throw some other exception or return `false`.
|
$this->mediaMap = $media_map;
|
||||||
*
|
}
|
||||||
* @return bool True on success.
|
|
||||||
*/
|
return isset($this->mediaMap[$message_type]);
|
||||||
abstract public function send();
|
}
|
||||||
|
|
||||||
|
final public function setMedia(array $media) {
|
||||||
|
$native_map = $this->getSupportedMessageTypes();
|
||||||
|
$native_map = array_fuse($native_map);
|
||||||
|
|
||||||
|
foreach ($media as $medium) {
|
||||||
|
if (!isset($native_map[$medium])) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Adapter ("%s") is configured for medium "%s", but this is not '.
|
||||||
|
'a supported delivery medium. Supported media are: %s.',
|
||||||
|
$medium,
|
||||||
|
implode(', ', $native_map)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->media = $media;
|
||||||
|
$this->mediaMap = null;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getMedia() {
|
||||||
|
return $this->media;
|
||||||
|
}
|
||||||
|
|
||||||
final public function setKey($key) {
|
final public function setKey($key) {
|
||||||
$this->key = $key;
|
$this->key = $key;
|
||||||
|
@ -110,18 +143,4 @@ abstract class PhabricatorMailImplementationAdapter extends Phobject {
|
||||||
|
|
||||||
abstract public function newDefaultOptions();
|
abstract public function newDefaultOptions();
|
||||||
|
|
||||||
public function prepareForSend() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function renderAddress($email, $name = null) {
|
|
||||||
if (strlen($name)) {
|
|
||||||
return (string)id(new PhutilEmailAddress())
|
|
||||||
->setDisplayName($name)
|
|
||||||
->setAddress($email);
|
|
||||||
} else {
|
|
||||||
return $email;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
final class PhabricatorMailImplementationAmazonSESAdapter
|
final class PhabricatorMailAmazonSESAdapter
|
||||||
extends PhabricatorMailImplementationPHPMailerLiteAdapter {
|
extends PhabricatorMailPHPMailerLiteAdapter {
|
||||||
|
|
||||||
const ADAPTERTYPE = 'ses';
|
const ADAPTERTYPE = 'ses';
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
final class PhabricatorMailImplementationPostmarkAdapter
|
|
||||||
extends PhabricatorMailImplementationAdapter {
|
|
||||||
|
|
||||||
const ADAPTERTYPE = 'postmark';
|
|
||||||
|
|
||||||
private $parameters = array();
|
|
||||||
|
|
||||||
public function setFrom($email, $name = '') {
|
|
||||||
$this->parameters['From'] = $this->renderAddress($email, $name);
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addReplyTo($email, $name = '') {
|
|
||||||
$this->parameters['ReplyTo'] = $this->renderAddress($email, $name);
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addTos(array $emails) {
|
|
||||||
foreach ($emails as $email) {
|
|
||||||
$this->parameters['To'][] = $email;
|
|
||||||
}
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addCCs(array $emails) {
|
|
||||||
foreach ($emails as $email) {
|
|
||||||
$this->parameters['Cc'][] = $email;
|
|
||||||
}
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addAttachment($data, $filename, $mimetype) {
|
|
||||||
$this->parameters['Attachments'][] = array(
|
|
||||||
'Name' => $filename,
|
|
||||||
'ContentType' => $mimetype,
|
|
||||||
'Content' => base64_encode($data),
|
|
||||||
);
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addHeader($header_name, $header_value) {
|
|
||||||
$this->parameters['Headers'][] = array(
|
|
||||||
'Name' => $header_name,
|
|
||||||
'Value' => $header_value,
|
|
||||||
);
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setBody($body) {
|
|
||||||
$this->parameters['TextBody'] = $body;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setHTMLBody($html_body) {
|
|
||||||
$this->parameters['HtmlBody'] = $html_body;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setSubject($subject) {
|
|
||||||
$this->parameters['Subject'] = $subject;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function supportsMessageIDHeader() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function validateOptions(array $options) {
|
|
||||||
PhutilTypeSpec::checkMap(
|
|
||||||
$options,
|
|
||||||
array(
|
|
||||||
'access-token' => 'string',
|
|
||||||
'inbound-addresses' => 'list<string>',
|
|
||||||
));
|
|
||||||
|
|
||||||
// Make sure this is properly formatted.
|
|
||||||
PhutilCIDRList::newList($options['inbound-addresses']);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function newDefaultOptions() {
|
|
||||||
return array(
|
|
||||||
'access-token' => null,
|
|
||||||
'inbound-addresses' => array(
|
|
||||||
// Via Postmark support circa February 2018, see:
|
|
||||||
//
|
|
||||||
// https://postmarkapp.com/support/article/800-ips-for-firewalls
|
|
||||||
//
|
|
||||||
// "Configuring Outbound Email" should be updated if this changes.
|
|
||||||
'50.31.156.6/32',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function send() {
|
|
||||||
$access_token = $this->getOption('access-token');
|
|
||||||
|
|
||||||
$parameters = $this->parameters;
|
|
||||||
$flatten = array(
|
|
||||||
'To',
|
|
||||||
'Cc',
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach ($flatten as $key) {
|
|
||||||
if (isset($parameters[$key])) {
|
|
||||||
$parameters[$key] = implode(', ', $parameters[$key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
id(new PhutilPostmarkFuture())
|
|
||||||
->setAccessToken($access_token)
|
|
||||||
->setMethod('email', $parameters)
|
|
||||||
->resolve();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -3,8 +3,8 @@
|
||||||
/**
|
/**
|
||||||
* Mail adapter that uses Mailgun's web API to deliver email.
|
* Mail adapter that uses Mailgun's web API to deliver email.
|
||||||
*/
|
*/
|
||||||
final class PhabricatorMailImplementationMailgunAdapter
|
final class PhabricatorMailMailgunAdapter
|
||||||
extends PhabricatorMailImplementationAdapter {
|
extends PhabricatorMailAdapter {
|
||||||
|
|
||||||
const ADAPTERTYPE = 'mailgun';
|
const ADAPTERTYPE = 'mailgun';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
final class PhabricatorMailImplementationPHPMailerAdapter
|
final class PhabricatorMailPHPMailerAdapter
|
||||||
extends PhabricatorMailImplementationAdapter {
|
extends PhabricatorMailAdapter {
|
||||||
|
|
||||||
const ADAPTERTYPE = 'smtp';
|
const ADAPTERTYPE = 'smtp';
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Should be final, but inherited by SES.
|
* TODO: Should be final, but inherited by SES.
|
||||||
|
*
|
||||||
|
* @concrete-extensible
|
||||||
*/
|
*/
|
||||||
class PhabricatorMailImplementationPHPMailerLiteAdapter
|
class PhabricatorMailPHPMailerLiteAdapter
|
||||||
extends PhabricatorMailImplementationAdapter {
|
extends PhabricatorMailAdapter {
|
||||||
|
|
||||||
const ADAPTERTYPE = 'sendmail';
|
const ADAPTERTYPE = 'sendmail';
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorMailPostmarkAdapter
|
||||||
|
extends PhabricatorMailAdapter {
|
||||||
|
|
||||||
|
const ADAPTERTYPE = 'postmark';
|
||||||
|
|
||||||
|
public function getSupportedMessageTypes() {
|
||||||
|
return array(
|
||||||
|
PhabricatorMailEmailMessage::MESSAGETYPE,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function supportsMessageIDHeader() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function validateOptions(array $options) {
|
||||||
|
PhutilTypeSpec::checkMap(
|
||||||
|
$options,
|
||||||
|
array(
|
||||||
|
'access-token' => 'string',
|
||||||
|
'inbound-addresses' => 'list<string>',
|
||||||
|
));
|
||||||
|
|
||||||
|
// Make sure this is properly formatted.
|
||||||
|
PhutilCIDRList::newList($options['inbound-addresses']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newDefaultOptions() {
|
||||||
|
return array(
|
||||||
|
'access-token' => null,
|
||||||
|
'inbound-addresses' => array(
|
||||||
|
// Via Postmark support circa February 2018, see:
|
||||||
|
//
|
||||||
|
// https://postmarkapp.com/support/article/800-ips-for-firewalls
|
||||||
|
//
|
||||||
|
// "Configuring Outbound Email" should be updated if this changes.
|
||||||
|
//
|
||||||
|
// These addresses were last updated in January 2019.
|
||||||
|
'50.31.156.6/32',
|
||||||
|
'50.31.156.77/32',
|
||||||
|
'18.217.206.57/32',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendMessage(PhabricatorMailExternalMessage $message) {
|
||||||
|
$access_token = $this->getOption('access-token');
|
||||||
|
|
||||||
|
$parameters = array();
|
||||||
|
|
||||||
|
$subject = $message->getSubject();
|
||||||
|
if ($subject !== null) {
|
||||||
|
$parameters['Subject'] = $subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
$from_address = $message->getFromAddress();
|
||||||
|
if ($from_address) {
|
||||||
|
$parameters['From'] = (string)$from_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
$to_addresses = $message->getToAddresses();
|
||||||
|
if ($to_addresses) {
|
||||||
|
$to = array();
|
||||||
|
foreach ($to_addresses as $address) {
|
||||||
|
$to[] = (string)$address;
|
||||||
|
}
|
||||||
|
$parameters['To'] = implode(', ', $to);
|
||||||
|
}
|
||||||
|
|
||||||
|
$cc_addresses = $message->getCCAddresses();
|
||||||
|
if ($cc_addresses) {
|
||||||
|
$cc = array();
|
||||||
|
foreach ($cc_addresses as $address) {
|
||||||
|
$cc[] = (string)$address;
|
||||||
|
}
|
||||||
|
$parameters['Cc'] = implode(', ', $cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
$reply_address = $message->getReplyToAddress();
|
||||||
|
if ($reply_address) {
|
||||||
|
$parameters['ReplyTo'] = (string)$reply_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
$headers = $message->getHeaders();
|
||||||
|
if ($headers) {
|
||||||
|
$list = array();
|
||||||
|
foreach ($headers as $header) {
|
||||||
|
$list[] = array(
|
||||||
|
'Name' => $header->getName(),
|
||||||
|
'Value' => $header->getValue(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$parameters['Headers'] = $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
$text_body = $message->getTextBody();
|
||||||
|
if ($text_body !== null) {
|
||||||
|
$parameters['TextBody'] = $text_body;
|
||||||
|
}
|
||||||
|
|
||||||
|
$html_body = $message->getHTMLBody();
|
||||||
|
if ($html_body !== null) {
|
||||||
|
$parameters['HtmlBody'] = $html_body;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attachments = $message->getAttachments();
|
||||||
|
if ($attachments) {
|
||||||
|
$files = array();
|
||||||
|
foreach ($attachments as $attachment) {
|
||||||
|
$files[] = array(
|
||||||
|
'Name' => $attachment->getFilename(),
|
||||||
|
'ContentType' => $attachment->getMimeType(),
|
||||||
|
'Content' => base64_encode($attachment->getData()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$parameters['Attachments'] = $files;
|
||||||
|
}
|
||||||
|
|
||||||
|
id(new PhutilPostmarkFuture())
|
||||||
|
->setAccessToken($access_token)
|
||||||
|
->setMethod('email', $parameters)
|
||||||
|
->setTimeout(60)
|
||||||
|
->resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,8 +3,8 @@
|
||||||
/**
|
/**
|
||||||
* Mail adapter that uses SendGrid's web API to deliver email.
|
* Mail adapter that uses SendGrid's web API to deliver email.
|
||||||
*/
|
*/
|
||||||
final class PhabricatorMailImplementationSendGridAdapter
|
final class PhabricatorMailSendGridAdapter
|
||||||
extends PhabricatorMailImplementationAdapter {
|
extends PhabricatorMailAdapter {
|
||||||
|
|
||||||
const ADAPTERTYPE = 'sendgrid';
|
const ADAPTERTYPE = 'sendgrid';
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
* Mail adapter that doesn't actually send any email, for writing unit tests
|
* Mail adapter that doesn't actually send any email, for writing unit tests
|
||||||
* against.
|
* against.
|
||||||
*/
|
*/
|
||||||
final class PhabricatorMailImplementationTestAdapter
|
final class PhabricatorMailTestAdapter
|
||||||
extends PhabricatorMailImplementationAdapter {
|
extends PhabricatorMailAdapter {
|
||||||
|
|
||||||
const ADAPTERTYPE = 'test';
|
const ADAPTERTYPE = 'test';
|
||||||
|
|
|
@ -21,7 +21,7 @@ final class PhabricatorMetaMTAMailgunReceiveController
|
||||||
array(
|
array(
|
||||||
'inbound' => true,
|
'inbound' => true,
|
||||||
'types' => array(
|
'types' => array(
|
||||||
PhabricatorMailImplementationMailgunAdapter::ADAPTERTYPE,
|
PhabricatorMailMailgunAdapter::ADAPTERTYPE,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
foreach ($mailers as $mailer) {
|
foreach ($mailers as $mailer) {
|
||||||
|
|
|
@ -16,7 +16,7 @@ final class PhabricatorMetaMTAPostmarkReceiveController
|
||||||
array(
|
array(
|
||||||
'inbound' => true,
|
'inbound' => true,
|
||||||
'types' => array(
|
'types' => array(
|
||||||
PhabricatorMailImplementationPostmarkAdapter::ADAPTERTYPE,
|
PhabricatorMailPostmarkAdapter::ADAPTERTYPE,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
if (!$mailers) {
|
if (!$mailers) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ final class PhabricatorMetaMTASendGridReceiveController
|
||||||
array(
|
array(
|
||||||
'inbound' => true,
|
'inbound' => true,
|
||||||
'types' => array(
|
'types' => array(
|
||||||
PhabricatorMailImplementationSendGridAdapter::ADAPTERTYPE,
|
PhabricatorMailSendGridAdapter::ADAPTERTYPE,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
if (!$mailers) {
|
if (!$mailers) {
|
||||||
|
|
|
@ -8,8 +8,7 @@ abstract class PhabricatorMailMessageEngine
|
||||||
private $actors = array();
|
private $actors = array();
|
||||||
private $preferences;
|
private $preferences;
|
||||||
|
|
||||||
final public function setMailer(
|
final public function setMailer(PhabricatorMailAdapter $mailer) {
|
||||||
PhabricatorMailImplementationAdapter $mailer) {
|
|
||||||
|
|
||||||
$this->mailer = $mailer;
|
$this->mailer = $mailer;
|
||||||
return $this;
|
return $this;
|
||||||
|
|
|
@ -547,13 +547,14 @@ final class PhabricatorMetaMTAMail
|
||||||
'types' => 'optional list<string>',
|
'types' => 'optional list<string>',
|
||||||
'inbound' => 'optional bool',
|
'inbound' => 'optional bool',
|
||||||
'outbound' => 'optional bool',
|
'outbound' => 'optional bool',
|
||||||
|
'media' => 'optional list<string>',
|
||||||
));
|
));
|
||||||
|
|
||||||
$mailers = array();
|
$mailers = array();
|
||||||
|
|
||||||
$config = PhabricatorEnv::getEnvConfig('cluster.mailers');
|
$config = PhabricatorEnv::getEnvConfig('cluster.mailers');
|
||||||
|
|
||||||
$adapters = PhabricatorMailImplementationAdapter::getAllAdapters();
|
$adapters = PhabricatorMailAdapter::getAllAdapters();
|
||||||
$next_priority = -1;
|
$next_priority = -1;
|
||||||
|
|
||||||
foreach ($config as $spec) {
|
foreach ($config as $spec) {
|
||||||
|
@ -583,6 +584,11 @@ final class PhabricatorMetaMTAMail
|
||||||
$mailer->setSupportsInbound(idx($spec, 'inbound', true));
|
$mailer->setSupportsInbound(idx($spec, 'inbound', true));
|
||||||
$mailer->setSupportsOutbound(idx($spec, 'outbound', true));
|
$mailer->setSupportsOutbound(idx($spec, 'outbound', true));
|
||||||
|
|
||||||
|
$media = idx($spec, 'media');
|
||||||
|
if ($media !== null) {
|
||||||
|
$mailer->setMedia($media);
|
||||||
|
}
|
||||||
|
|
||||||
$mailers[] = $mailer;
|
$mailers[] = $mailer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,6 +624,24 @@ final class PhabricatorMetaMTAMail
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Select only the mailers which can transmit messages with requested media
|
||||||
|
// types.
|
||||||
|
if (!empty($constraints['media'])) {
|
||||||
|
foreach ($mailers as $key => $mailer) {
|
||||||
|
$supports_any = false;
|
||||||
|
foreach ($constraints['media'] as $medium) {
|
||||||
|
if ($mailer->supportsMessageType($medium)) {
|
||||||
|
$supports_any = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$supports_any) {
|
||||||
|
unset($mailers[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$sorted = array();
|
$sorted = array();
|
||||||
$groups = mgroup($mailers, 'getPriority');
|
$groups = mgroup($mailers, 'getPriority');
|
||||||
krsort($groups);
|
krsort($groups);
|
||||||
|
|
|
@ -17,7 +17,7 @@ final class PhabricatorMetaMTAMailTestCase extends PhabricatorTestCase {
|
||||||
$mail = new PhabricatorMetaMTAMail();
|
$mail = new PhabricatorMetaMTAMail();
|
||||||
$mail->addTos(array($phid));
|
$mail->addTos(array($phid));
|
||||||
|
|
||||||
$mailer = new PhabricatorMailImplementationTestAdapter();
|
$mailer = new PhabricatorMailTestAdapter();
|
||||||
$mail->sendWithMailers(array($mailer));
|
$mail->sendWithMailers(array($mailer));
|
||||||
$this->assertEqual(
|
$this->assertEqual(
|
||||||
PhabricatorMailOutboundStatus::STATUS_SENT,
|
PhabricatorMailOutboundStatus::STATUS_SENT,
|
||||||
|
@ -28,7 +28,7 @@ final class PhabricatorMetaMTAMailTestCase extends PhabricatorTestCase {
|
||||||
$mail = new PhabricatorMetaMTAMail();
|
$mail = new PhabricatorMetaMTAMail();
|
||||||
$mail->addTos(array($phid));
|
$mail->addTos(array($phid));
|
||||||
|
|
||||||
$mailer = new PhabricatorMailImplementationTestAdapter();
|
$mailer = new PhabricatorMailTestAdapter();
|
||||||
$mailer->setFailTemporarily(true);
|
$mailer->setFailTemporarily(true);
|
||||||
try {
|
try {
|
||||||
$mail->sendWithMailers(array($mailer));
|
$mail->sendWithMailers(array($mailer));
|
||||||
|
@ -44,7 +44,7 @@ final class PhabricatorMetaMTAMailTestCase extends PhabricatorTestCase {
|
||||||
$mail = new PhabricatorMetaMTAMail();
|
$mail = new PhabricatorMetaMTAMail();
|
||||||
$mail->addTos(array($phid));
|
$mail->addTos(array($phid));
|
||||||
|
|
||||||
$mailer = new PhabricatorMailImplementationTestAdapter();
|
$mailer = new PhabricatorMailTestAdapter();
|
||||||
$mailer->setFailPermanently(true);
|
$mailer->setFailPermanently(true);
|
||||||
try {
|
try {
|
||||||
$mail->sendWithMailers(array($mailer));
|
$mail->sendWithMailers(array($mailer));
|
||||||
|
@ -60,7 +60,7 @@ final class PhabricatorMetaMTAMailTestCase extends PhabricatorTestCase {
|
||||||
$user = $this->generateNewTestUser();
|
$user = $this->generateNewTestUser();
|
||||||
$phid = $user->getPHID();
|
$phid = $user->getPHID();
|
||||||
|
|
||||||
$mailer = new PhabricatorMailImplementationTestAdapter();
|
$mailer = new PhabricatorMailTestAdapter();
|
||||||
|
|
||||||
$mail = new PhabricatorMetaMTAMail();
|
$mail = new PhabricatorMetaMTAMail();
|
||||||
$mail->addTos(array($phid));
|
$mail->addTos(array($phid));
|
||||||
|
@ -182,7 +182,7 @@ final class PhabricatorMetaMTAMailTestCase extends PhabricatorTestCase {
|
||||||
$supports_message_id,
|
$supports_message_id,
|
||||||
$is_first_mail) {
|
$is_first_mail) {
|
||||||
|
|
||||||
$mailer = new PhabricatorMailImplementationTestAdapter();
|
$mailer = new PhabricatorMailTestAdapter();
|
||||||
|
|
||||||
$mailer->prepareForSend(
|
$mailer->prepareForSend(
|
||||||
array(
|
array(
|
||||||
|
@ -261,10 +261,10 @@ final class PhabricatorMetaMTAMailTestCase extends PhabricatorTestCase {
|
||||||
$status_queue = PhabricatorMailOutboundStatus::STATUS_QUEUE;
|
$status_queue = PhabricatorMailOutboundStatus::STATUS_QUEUE;
|
||||||
$status_fail = PhabricatorMailOutboundStatus::STATUS_FAIL;
|
$status_fail = PhabricatorMailOutboundStatus::STATUS_FAIL;
|
||||||
|
|
||||||
$mailer1 = id(new PhabricatorMailImplementationTestAdapter())
|
$mailer1 = id(new PhabricatorMailTestAdapter())
|
||||||
->setKey('mailer1');
|
->setKey('mailer1');
|
||||||
|
|
||||||
$mailer2 = id(new PhabricatorMailImplementationTestAdapter())
|
$mailer2 = id(new PhabricatorMailTestAdapter())
|
||||||
->setKey('mailer2');
|
->setKey('mailer2');
|
||||||
|
|
||||||
$mailers = array(
|
$mailers = array(
|
||||||
|
@ -350,7 +350,7 @@ final class PhabricatorMetaMTAMailTestCase extends PhabricatorTestCase {
|
||||||
->setBody($string_1kb)
|
->setBody($string_1kb)
|
||||||
->setHTMLBody($html_1kb);
|
->setHTMLBody($html_1kb);
|
||||||
|
|
||||||
$mailer = new PhabricatorMailImplementationTestAdapter();
|
$mailer = new PhabricatorMailTestAdapter();
|
||||||
$mail->sendWithMailers(array($mailer));
|
$mail->sendWithMailers(array($mailer));
|
||||||
$this->assertEqual(
|
$this->assertEqual(
|
||||||
PhabricatorMailOutboundStatus::STATUS_SENT,
|
PhabricatorMailOutboundStatus::STATUS_SENT,
|
||||||
|
@ -370,7 +370,7 @@ final class PhabricatorMetaMTAMailTestCase extends PhabricatorTestCase {
|
||||||
->setBody($string_1mb)
|
->setBody($string_1mb)
|
||||||
->setHTMLBody($html_1mb);
|
->setHTMLBody($html_1mb);
|
||||||
|
|
||||||
$mailer = new PhabricatorMailImplementationTestAdapter();
|
$mailer = new PhabricatorMailTestAdapter();
|
||||||
$mail->sendWithMailers(array($mailer));
|
$mail->sendWithMailers(array($mailer));
|
||||||
$this->assertEqual(
|
$this->assertEqual(
|
||||||
PhabricatorMailOutboundStatus::STATUS_SENT,
|
PhabricatorMailOutboundStatus::STATUS_SENT,
|
||||||
|
@ -398,7 +398,7 @@ final class PhabricatorMetaMTAMailTestCase extends PhabricatorTestCase {
|
||||||
->setBody($string_1kb)
|
->setBody($string_1kb)
|
||||||
->setHTMLBody($html_1mb);
|
->setHTMLBody($html_1mb);
|
||||||
|
|
||||||
$mailer = new PhabricatorMailImplementationTestAdapter();
|
$mailer = new PhabricatorMailTestAdapter();
|
||||||
$mail->sendWithMailers(array($mailer));
|
$mail->sendWithMailers(array($mailer));
|
||||||
$this->assertEqual(
|
$this->assertEqual(
|
||||||
PhabricatorMailOutboundStatus::STATUS_SENT,
|
PhabricatorMailOutboundStatus::STATUS_SENT,
|
||||||
|
|
|
@ -85,12 +85,18 @@ The supported keys for each mailer are:
|
||||||
used to receive inbound mail.
|
used to receive inbound mail.
|
||||||
- `outbound`: Optional bool. Use `false` to prevent this mailer from being
|
- `outbound`: Optional bool. Use `false` to prevent this mailer from being
|
||||||
used to send outbound mail.
|
used to send outbound mail.
|
||||||
|
- `media`: Optional list<string>. Some mailers support delivering multiple
|
||||||
|
types of messages (like Email and SMS). If you want to configure a mailer
|
||||||
|
to support only a subset of possible message types, list only those message
|
||||||
|
types. Normally, you do not need to configure this. See below for a list
|
||||||
|
of media types.
|
||||||
|
|
||||||
The `type` field can be used to select these third-party mailers:
|
The `type` field can be used to select these third-party mailers:
|
||||||
|
|
||||||
- `mailgun`: Use Mailgun.
|
- `mailgun`: Use Mailgun.
|
||||||
- `ses`: Use Amazon SES.
|
- `ses`: Use Amazon SES.
|
||||||
- `sendgrid`: Use Sendgrid.
|
- `sendgrid`: Use Sendgrid.
|
||||||
|
- `postmark`: Use Postmark.
|
||||||
|
|
||||||
It also supports these local mailers:
|
It also supports these local mailers:
|
||||||
|
|
||||||
|
@ -99,7 +105,11 @@ It also supports these local mailers:
|
||||||
- `test`: Internal mailer for testing. Does not send mail.
|
- `test`: Internal mailer for testing. Does not send mail.
|
||||||
|
|
||||||
You can also write your own mailer by extending
|
You can also write your own mailer by extending
|
||||||
`PhabricatorMailImplementationAdapter`.
|
`PhabricatorMailAdapter`.
|
||||||
|
|
||||||
|
The `media` field supports these values:
|
||||||
|
|
||||||
|
- `email`: Configure this mailer for email.
|
||||||
|
|
||||||
Once you've selected a mailer, find the corresponding section below for
|
Once you've selected a mailer, find the corresponding section below for
|
||||||
instructions on configuring it.
|
instructions on configuring it.
|
||||||
|
@ -171,11 +181,13 @@ The option accepts a list of CIDR ranges, like `1.2.3.4/16` (IPv4) or
|
||||||
|
|
||||||
```lang=json
|
```lang=json
|
||||||
[
|
[
|
||||||
"50.31.156.6/32"
|
"50.31.156.6/32",
|
||||||
|
"50.31.156.77/32",
|
||||||
|
"18.217.206.57/32"
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
The default address ranges were last updated in February 2018, and were
|
The default address ranges were last updated in January 2019, and were
|
||||||
documented at: <https://postmarkapp.com/support/article/800-ips-for-firewalls>
|
documented at: <https://postmarkapp.com/support/article/800-ips-for-firewalls>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ final class PhabricatorClusterMailersConfigType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$adapters = PhabricatorMailImplementationAdapter::getAllAdapters();
|
$adapters = PhabricatorMailAdapter::getAllAdapters();
|
||||||
|
|
||||||
$map = array();
|
$map = array();
|
||||||
foreach ($value as $index => $spec) {
|
foreach ($value as $index => $spec) {
|
||||||
|
|
Loading…
Reference in a new issue