Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14039494
D19017.id45613.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
8 KB
Referenced Files
None
Subscribers
None
D19017.id45613.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -3272,6 +3272,7 @@
'PhabricatorMetaMTAMailgunReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAMailgunReceiveController.php',
'PhabricatorMetaMTAMemberQuery' => 'applications/metamta/query/PhabricatorMetaMTAMemberQuery.php',
'PhabricatorMetaMTAPermanentFailureException' => 'applications/metamta/exception/PhabricatorMetaMTAPermanentFailureException.php',
+ 'PhabricatorMetaMTAPostmarkReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAPostmarkReceiveController.php',
'PhabricatorMetaMTAReceivedMail' => 'applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php',
'PhabricatorMetaMTAReceivedMailProcessingException' => 'applications/metamta/exception/PhabricatorMetaMTAReceivedMailProcessingException.php',
'PhabricatorMetaMTAReceivedMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php',
@@ -8787,6 +8788,7 @@
'PhabricatorMetaMTAMailgunReceiveController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAMemberQuery' => 'PhabricatorQuery',
'PhabricatorMetaMTAPermanentFailureException' => 'Exception',
+ 'PhabricatorMetaMTAPostmarkReceiveController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTAReceivedMailProcessingException' => 'Exception',
'PhabricatorMetaMTAReceivedMailTestCase' => 'PhabricatorTestCase',
diff --git a/src/applications/metamta/application/PhabricatorMetaMTAApplication.php b/src/applications/metamta/application/PhabricatorMetaMTAApplication.php
--- a/src/applications/metamta/application/PhabricatorMetaMTAApplication.php
+++ b/src/applications/metamta/application/PhabricatorMetaMTAApplication.php
@@ -42,6 +42,7 @@
'detail/(?P<id>[1-9]\d*)/' => 'PhabricatorMetaMTAMailViewController',
'sendgrid/' => 'PhabricatorMetaMTASendGridReceiveController',
'mailgun/' => 'PhabricatorMetaMTAMailgunReceiveController',
+ 'postmark/' => 'PhabricatorMetaMTAPostmarkReceiveController',
),
);
}
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
@@ -17,15 +17,12 @@
// 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;
+ $mailers = PhabricatorMetaMTAMail::newMailersWithTypes(
+ array(
+ 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;
diff --git a/src/applications/metamta/controller/PhabricatorMetaMTAPostmarkReceiveController.php b/src/applications/metamta/controller/PhabricatorMetaMTAPostmarkReceiveController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/metamta/controller/PhabricatorMetaMTAPostmarkReceiveController.php
@@ -0,0 +1,87 @@
+<?php
+
+final class PhabricatorMetaMTAPostmarkReceiveController
+ extends PhabricatorMetaMTAController {
+
+ public function shouldRequireLogin() {
+ return false;
+ }
+
+ /**
+ * @phutil-external-symbol class PhabricatorStartup
+ */
+ public function handleRequest(AphrontRequest $request) {
+ // Don't process requests if we don't have a configured Postmark adapter.
+ $mailers = PhabricatorMetaMTAMail::newMailersWithTypes(
+ array(
+ PhabricatorMailImplementationPostmarkAdapter::ADAPTERTYPE,
+ ));
+ if (!$mailers) {
+ return new Aphront404Response();
+ }
+
+ $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
+ $raw_input = PhabricatorStartup::getRawInput();
+
+ try {
+ $data = phutil_json_decode($raw_input);
+ } catch (Exception $ex) {
+ return new Aphront400Response();
+ }
+
+ $raw_headers = array();
+ $header_items = idx($data, 'Headers', array());
+ foreach ($header_items as $header_item) {
+ $name = idx($header_item, 'Name');
+ $value = idx($header_item, 'Value');
+ $raw_headers[$name] = $value;
+ }
+
+ $headers = array(
+ 'to' => idx($data, 'To'),
+ 'from' => idx($data, 'From'),
+ 'cc' => idx($data, 'Cc'),
+ 'subject' => idx($data, 'Subject'),
+ ) + $raw_headers;
+
+
+ $received = id(new PhabricatorMetaMTAReceivedMail())
+ ->setHeaders($headers)
+ ->setBodies(
+ array(
+ 'text' => idx($data, 'TextBody'),
+ 'html' => idx($data, 'HtmlBody'),
+ ));
+
+ $file_phids = array();
+ $attachments = idx($data, 'Attachments', array());
+ foreach ($attachments as $attachment) {
+ $file_data = idx($attachment, 'Content');
+ $file_data = base64_decode($file_data);
+
+ try {
+ $file = PhabricatorFile::newFromFileData(
+ $file_data,
+ array(
+ 'name' => idx($attachment, 'Name'),
+ 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE,
+ ));
+ $file_phids[] = $file->getPHID();
+ } catch (Exception $ex) {
+ phlog($ex);
+ }
+ }
+ $received->setAttachments($file_phids);
+
+ try {
+ $received->save();
+ $received->processReceivedMail();
+ } catch (Exception $ex) {
+ phlog($ex);
+ }
+
+ return id(new AphrontWebpageResponse())
+ ->setContent(pht("Got it! Thanks, Postmark!\n"));
+ }
+
+}
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,24 +8,14 @@
}
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) {
+ $mailers = PhabricatorMetaMTAMail::newMailersWithTypes(
+ array(
+ PhabricatorMailImplementationSendGridAdapter::ADAPTERTYPE,
+ ));
+ if (!$mailers) {
return new Aphront404Response();
}
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
@@ -482,6 +482,20 @@
return $this->sendWithMailers($mailers);
}
+ public static function newMailersWithTypes(array $types) {
+ $mailers = self::newMailers();
+ $types = array_fuse($types);
+
+ foreach ($mailers as $key => $mailer) {
+ $mailer_type = $mailer->getAdapterType();
+ if (!isset($types[$mailer_type])) {
+ unset($mailers[$key]);
+ }
+ }
+
+ return array_values($mailers);
+ }
+
public static function newMailers() {
$mailers = array();
diff --git a/src/docs/user/configuration/configuring_inbound_email.diviner b/src/docs/user/configuration/configuring_inbound_email.diviner
--- a/src/docs/user/configuration/configuring_inbound_email.diviner
+++ b/src/docs/user/configuration/configuring_inbound_email.diviner
@@ -14,6 +14,7 @@
| Receive Mail With | Setup | Cost | Notes |
|--------|-------|------|-------|
| Mailgun | Easy | Cheap | Recommended |
+| Postmark | Easy | Cheap | Recommended |
| SendGrid | Easy | Cheap | |
| Local MTA | Extremely Difficult | Free | Strongly discouraged! |
@@ -130,6 +131,17 @@
example domain with your actual domain.
- Set the `mailgun.api-key` config key to your Mailgun API key.
+Postmark Setup
+==============
+
+To process inbound mail from Postmark, configure this URI as your inbound
+webhook URI in the Postmark control panel:
+
+```
+https://<phabricator.yourdomain.com>/mail/postmark/
+```
+
+
= SendGrid Setup =
To use SendGrid, you need a SendGrid account with access to the "Parse API" for
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Nov 12, 5:47 AM (5 d, 5 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6718309
Default Alt Text
D19017.id45613.diff (8 KB)
Attached To
Mode
D19017: Support Postmark inbound mail via webhook
Attached
Detach File
Event Timeline
Log In to Comment