Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14013883
D19005.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Referenced Files
None
Subscribers
None
D19005.id.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D19005: Use "cluster.mailers" if it is configured
Attached
Detach File
Event Timeline
Log In to Comment