@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Support Postmark inbound mail via webhook

Summary: Depends on D19016. Ref T13053. Adds a listener for the Postmark webhook.

Test Plan:
Processed some test mail locally, at least:

{F5416053}

Reviewers: amckinley

Maniphest Tasks: T13053

Differential Revision: https://secure.phabricator.com/D19017

+125 -22
+2
src/__phutil_library_map__.php
··· 3272 3272 'PhabricatorMetaMTAMailgunReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAMailgunReceiveController.php', 3273 3273 'PhabricatorMetaMTAMemberQuery' => 'applications/metamta/query/PhabricatorMetaMTAMemberQuery.php', 3274 3274 'PhabricatorMetaMTAPermanentFailureException' => 'applications/metamta/exception/PhabricatorMetaMTAPermanentFailureException.php', 3275 + 'PhabricatorMetaMTAPostmarkReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAPostmarkReceiveController.php', 3275 3276 'PhabricatorMetaMTAReceivedMail' => 'applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php', 3276 3277 'PhabricatorMetaMTAReceivedMailProcessingException' => 'applications/metamta/exception/PhabricatorMetaMTAReceivedMailProcessingException.php', 3277 3278 'PhabricatorMetaMTAReceivedMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php', ··· 8787 8788 'PhabricatorMetaMTAMailgunReceiveController' => 'PhabricatorMetaMTAController', 8788 8789 'PhabricatorMetaMTAMemberQuery' => 'PhabricatorQuery', 8789 8790 'PhabricatorMetaMTAPermanentFailureException' => 'Exception', 8791 + 'PhabricatorMetaMTAPostmarkReceiveController' => 'PhabricatorMetaMTAController', 8790 8792 'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO', 8791 8793 'PhabricatorMetaMTAReceivedMailProcessingException' => 'Exception', 8792 8794 'PhabricatorMetaMTAReceivedMailTestCase' => 'PhabricatorTestCase',
+1
src/applications/metamta/application/PhabricatorMetaMTAApplication.php
··· 42 42 'detail/(?P<id>[1-9]\d*)/' => 'PhabricatorMetaMTAMailViewController', 43 43 'sendgrid/' => 'PhabricatorMetaMTASendGridReceiveController', 44 44 'mailgun/' => 'PhabricatorMetaMTAMailgunReceiveController', 45 + 'postmark/' => 'PhabricatorMetaMTAPostmarkReceiveController', 45 46 ), 46 47 ); 47 48 }
+4 -7
src/applications/metamta/controller/PhabricatorMetaMTAMailgunReceiveController.php
··· 17 17 // inbound mail from any of them. Test the signature to see if it matches 18 18 // any configured Mailgun mailer. 19 19 20 - $mailers = PhabricatorMetaMTAMail::newMailers(); 21 - $mailgun_type = PhabricatorMailImplementationMailgunAdapter::ADAPTERTYPE; 20 + $mailers = PhabricatorMetaMTAMail::newMailersWithTypes( 21 + array( 22 + PhabricatorMailImplementationMailgunAdapter::ADAPTERTYPE, 23 + )); 22 24 foreach ($mailers as $mailer) { 23 - if ($mailer->getAdapterType() != $mailgun_type) { 24 - continue; 25 - } 26 - 27 25 $api_key = $mailer->getOption('api-key'); 28 - 29 26 $hash = hash_hmac('sha256', $timestamp.$token, $api_key); 30 27 if (phutil_hashes_are_identical($sig, $hash)) { 31 28 return true;
+87
src/applications/metamta/controller/PhabricatorMetaMTAPostmarkReceiveController.php
··· 1 + <?php 2 + 3 + final class PhabricatorMetaMTAPostmarkReceiveController 4 + extends PhabricatorMetaMTAController { 5 + 6 + public function shouldRequireLogin() { 7 + return false; 8 + } 9 + 10 + /** 11 + * @phutil-external-symbol class PhabricatorStartup 12 + */ 13 + public function handleRequest(AphrontRequest $request) { 14 + // Don't process requests if we don't have a configured Postmark adapter. 15 + $mailers = PhabricatorMetaMTAMail::newMailersWithTypes( 16 + array( 17 + PhabricatorMailImplementationPostmarkAdapter::ADAPTERTYPE, 18 + )); 19 + if (!$mailers) { 20 + return new Aphront404Response(); 21 + } 22 + 23 + $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); 24 + $raw_input = PhabricatorStartup::getRawInput(); 25 + 26 + try { 27 + $data = phutil_json_decode($raw_input); 28 + } catch (Exception $ex) { 29 + return new Aphront400Response(); 30 + } 31 + 32 + $raw_headers = array(); 33 + $header_items = idx($data, 'Headers', array()); 34 + foreach ($header_items as $header_item) { 35 + $name = idx($header_item, 'Name'); 36 + $value = idx($header_item, 'Value'); 37 + $raw_headers[$name] = $value; 38 + } 39 + 40 + $headers = array( 41 + 'to' => idx($data, 'To'), 42 + 'from' => idx($data, 'From'), 43 + 'cc' => idx($data, 'Cc'), 44 + 'subject' => idx($data, 'Subject'), 45 + ) + $raw_headers; 46 + 47 + 48 + $received = id(new PhabricatorMetaMTAReceivedMail()) 49 + ->setHeaders($headers) 50 + ->setBodies( 51 + array( 52 + 'text' => idx($data, 'TextBody'), 53 + 'html' => idx($data, 'HtmlBody'), 54 + )); 55 + 56 + $file_phids = array(); 57 + $attachments = idx($data, 'Attachments', array()); 58 + foreach ($attachments as $attachment) { 59 + $file_data = idx($attachment, 'Content'); 60 + $file_data = base64_decode($file_data); 61 + 62 + try { 63 + $file = PhabricatorFile::newFromFileData( 64 + $file_data, 65 + array( 66 + 'name' => idx($attachment, 'Name'), 67 + 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE, 68 + )); 69 + $file_phids[] = $file->getPHID(); 70 + } catch (Exception $ex) { 71 + phlog($ex); 72 + } 73 + } 74 + $received->setAttachments($file_phids); 75 + 76 + try { 77 + $received->save(); 78 + $received->processReceivedMail(); 79 + } catch (Exception $ex) { 80 + phlog($ex); 81 + } 82 + 83 + return id(new AphrontWebpageResponse()) 84 + ->setContent(pht("Got it! Thanks, Postmark!\n")); 85 + } 86 + 87 + }
+5 -15
src/applications/metamta/controller/PhabricatorMetaMTASendGridReceiveController.php
··· 8 8 } 9 9 10 10 public function handleRequest(AphrontRequest $request) { 11 - $mailers = PhabricatorMetaMTAMail::newMailers(); 12 - $sendgrid_type = PhabricatorMailImplementationSendGridAdapter::ADAPTERTYPE; 13 - 14 11 // SendGrid doesn't sign payloads so we can't be sure that SendGrid 15 12 // actually sent this request, but require a configured SendGrid mailer 16 13 // before we activate this endpoint. 17 - 18 - $has_sendgrid = false; 19 - foreach ($mailers as $mailer) { 20 - if ($mailer->getAdapterType() != $sendgrid_type) { 21 - continue; 22 - } 23 - 24 - $has_sendgrid = true; 25 - break; 26 - } 27 - 28 - if (!$has_sendgrid) { 14 + $mailers = PhabricatorMetaMTAMail::newMailersWithTypes( 15 + array( 16 + PhabricatorMailImplementationSendGridAdapter::ADAPTERTYPE, 17 + )); 18 + if (!$mailers) { 29 19 return new Aphront404Response(); 30 20 } 31 21
+14
src/applications/metamta/storage/PhabricatorMetaMTAMail.php
··· 482 482 return $this->sendWithMailers($mailers); 483 483 } 484 484 485 + public static function newMailersWithTypes(array $types) { 486 + $mailers = self::newMailers(); 487 + $types = array_fuse($types); 488 + 489 + foreach ($mailers as $key => $mailer) { 490 + $mailer_type = $mailer->getAdapterType(); 491 + if (!isset($types[$mailer_type])) { 492 + unset($mailers[$key]); 493 + } 494 + } 495 + 496 + return array_values($mailers); 497 + } 498 + 485 499 public static function newMailers() { 486 500 $mailers = array(); 487 501
+12
src/docs/user/configuration/configuring_inbound_email.diviner
··· 14 14 | Receive Mail With | Setup | Cost | Notes | 15 15 |--------|-------|------|-------| 16 16 | Mailgun | Easy | Cheap | Recommended | 17 + | Postmark | Easy | Cheap | Recommended | 17 18 | SendGrid | Easy | Cheap | | 18 19 | Local MTA | Extremely Difficult | Free | Strongly discouraged! | 19 20 ··· 129 130 `forward("https://phabricator.example.com/mail/mailgun/")`. Replace the 130 131 example domain with your actual domain. 131 132 - Set the `mailgun.api-key` config key to your Mailgun API key. 133 + 134 + Postmark Setup 135 + ============== 136 + 137 + To process inbound mail from Postmark, configure this URI as your inbound 138 + webhook URI in the Postmark control panel: 139 + 140 + ``` 141 + https://<phabricator.yourdomain.com>/mail/postmark/ 142 + ``` 143 + 132 144 133 145 = SendGrid Setup = 134 146