Page MenuHomePhabricator

D19005.id.diff
No OneTemporary

D19005.id.diff

diff --git a/src/applications/metamta/adapter/PhabricatorMailImplementationAdapter.php b/src/applications/metamta/adapter/PhabricatorMailImplementationAdapter.php
--- a/src/applications/metamta/adapter/PhabricatorMailImplementationAdapter.php
+++ b/src/applications/metamta/adapter/PhabricatorMailImplementationAdapter.php
@@ -3,6 +3,7 @@
abstract class PhabricatorMailImplementationAdapter extends Phobject {
private $key;
+ private $priority;
private $options = array();
final public function getAdapterType() {
@@ -57,6 +58,15 @@
return $this->key;
}
+ final public function setPriority($priority) {
+ $this->priority = $priority;
+ return $this;
+ }
+
+ final public function getPriority() {
+ return $this->priority;
+ }
+
final public function getOption($key) {
if (!array_key_exists($key, $this->options)) {
throw new Exception(
diff --git a/src/applications/metamta/controller/PhabricatorMetaMTAMailgunReceiveController.php b/src/applications/metamta/controller/PhabricatorMetaMTAMailgunReceiveController.php
--- a/src/applications/metamta/controller/PhabricatorMetaMTAMailgunReceiveController.php
+++ b/src/applications/metamta/controller/PhabricatorMetaMTAMailgunReceiveController.php
@@ -8,14 +8,31 @@
}
private function verifyMessage() {
- $api_key = PhabricatorEnv::getEnvConfig('mailgun.api-key');
$request = $this->getRequest();
$timestamp = $request->getStr('timestamp');
$token = $request->getStr('token');
$sig = $request->getStr('signature');
- $hash = hash_hmac('sha256', $timestamp.$token, $api_key);
- return phutil_hashes_are_identical($sig, $hash);
+ // An install may configure multiple Mailgun mailers, and we might receive
+ // inbound mail from any of them. Test the signature to see if it matches
+ // any configured Mailgun mailer.
+
+ $mailers = PhabricatorMetaMTAMail::newMailers();
+ $mailgun_type = PhabricatorMailImplementationMailgunAdapter::ADAPTERTYPE;
+ foreach ($mailers as $mailer) {
+ if ($mailer->getAdapterType() != $mailgun_type) {
+ continue;
+ }
+
+ $api_key = $mailer->getOption('api-key');
+
+ $hash = hash_hmac('sha256', $timestamp.$token, $api_key);
+ if (phutil_hashes_are_identical($sig, $hash)) {
+ return true;
+ }
+ }
+
+ return false;
}
public function handleRequest(AphrontRequest $request) {
diff --git a/src/applications/metamta/controller/PhabricatorMetaMTASendGridReceiveController.php b/src/applications/metamta/controller/PhabricatorMetaMTASendGridReceiveController.php
--- a/src/applications/metamta/controller/PhabricatorMetaMTASendGridReceiveController.php
+++ b/src/applications/metamta/controller/PhabricatorMetaMTASendGridReceiveController.php
@@ -8,6 +8,26 @@
}
public function handleRequest(AphrontRequest $request) {
+ $mailers = PhabricatorMetaMTAMail::newMailers();
+ $sendgrid_type = PhabricatorMailImplementationSendGridAdapter::ADAPTERTYPE;
+
+ // SendGrid doesn't sign payloads so we can't be sure that SendGrid
+ // actually sent this request, but require a configured SendGrid mailer
+ // before we activate this endpoint.
+
+ $has_sendgrid = false;
+ foreach ($mailers as $mailer) {
+ if ($mailer->getAdapterType() != $sendgrid_type) {
+ continue;
+ }
+
+ $has_sendgrid = true;
+ break;
+ }
+
+ if (!$has_sendgrid) {
+ return new Aphront404Response();
+ }
// No CSRF for SendGrid.
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
diff --git a/src/applications/metamta/storage/PhabricatorMetaMTAMail.php b/src/applications/metamta/storage/PhabricatorMetaMTAMail.php
--- a/src/applications/metamta/storage/PhabricatorMetaMTAMail.php
+++ b/src/applications/metamta/storage/PhabricatorMetaMTAMail.php
@@ -463,33 +463,85 @@
throw new Exception(pht('Trying to send an already-sent mail!'));
}
- $mailers = $this->newMailers();
+ $mailers = self::newMailers();
return $this->sendWithMailers($mailers);
}
- private function newMailers() {
+ public static function newMailers() {
$mailers = array();
- $mailer = PhabricatorEnv::newObjectFromConfig('metamta.mail-adapter');
+ $config = PhabricatorEnv::getEnvConfig('cluster.mailers');
+ if ($config === null) {
+ $mailer = PhabricatorEnv::newObjectFromConfig('metamta.mail-adapter');
- $defaults = $mailer->newDefaultOptions();
- $options = $mailer->newLegacyOptions();
+ $defaults = $mailer->newDefaultOptions();
+ $options = $mailer->newLegacyOptions();
- $options = $options + $defaults;
+ $options = $options + $defaults;
- $mailer
- ->setKey('default')
- ->setOptions($options);
+ $mailer
+ ->setKey('default')
+ ->setPriority(-1)
+ ->setOptions($options);
- $mailer->prepareForSend();
+ $mailers[] = $mailer;
+ } else {
+ $adapters = PhabricatorMailImplementationAdapter::getAllAdapters();
+ $next_priority = -1;
+
+ foreach ($config as $spec) {
+ $type = $spec['type'];
+ if (!isset($adapters[$type])) {
+ throw new Exception(
+ pht(
+ 'Unknown mailer ("%s")!',
+ $type));
+ }
- $mailers[] = $mailer;
+ $key = $spec['key'];
+ $mailer = id(clone $adapters[$type])
+ ->setKey($key);
- return $mailers;
+ $priority = idx($spec, 'priority');
+ if (!$priority) {
+ $priority = $next_priority;
+ $next_priority--;
+ }
+ $mailer->setPriority($priority);
+
+ $defaults = $mailer->newDefaultOptions();
+ $options = idx($spec, 'options', array()) + $defaults;
+ $mailer->setOptions($options);
+ }
+ }
+
+ $sorted = array();
+ $groups = mgroup($mailers, 'getPriority');
+ ksort($groups);
+ foreach ($groups as $group) {
+ // Reorder services within the same priority group randomly.
+ shuffle($group);
+ foreach ($group as $mailer) {
+ $sorted[] = $mailer;
+ }
+ }
+
+ foreach ($sorted as $mailer) {
+ $mailer->prepareForSend();
+ }
+
+ return $sorted;
}
public function sendWithMailers(array $mailers) {
+ if (!$mailers) {
+ return $this
+ ->setStatus(PhabricatorMailOutboundStatus::STATUS_VOID)
+ ->setMessage(pht('No mailers are configured.'))
+ ->save();
+ }
+
$exceptions = array();
foreach ($mailers as $template_mailer) {
$mailer = null;
@@ -865,6 +917,12 @@
$mailer->addCCs($add_cc);
}
+ // Keep track of which mailer actually ended up accepting the message.
+ $mailer_key = $mailer->getKey();
+ if ($mailer_key !== null) {
+ $this->setParam('mailer.key', $mailer_key);
+ }
+
return $mailer;
}
diff --git a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
--- a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
+++ b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
@@ -2575,12 +2575,13 @@
$mail = $this->buildMailForTarget($object, $xactions, $target);
- if ($this->mustEncrypt) {
- $mail
- ->setMustEncrypt(true)
- ->setMustEncryptReasons($this->mustEncrypt);
+ if ($mail) {
+ if ($this->mustEncrypt) {
+ $mail
+ ->setMustEncrypt(true)
+ ->setMustEncryptReasons($this->mustEncrypt);
+ }
}
-
} catch (Exception $ex) {
$caught = $ex;
}

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 3, 6:15 PM (1 w, 6 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6735914
Default Alt Text
D19005.id.diff (7 KB)

Event Timeline