@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.

Drop empty inbound mail at the beginning of the receive workflow, not inside object handlers

Summary:
Ref T920. Ref T7477. We currently drop empty mail only once it reaches the `ReplyHandler` layer.

I think no plausible receiver can ever do anything useful with this kind of mail, so we can safely drop it earlier and simplify some of the logic. After T7477, we'd end up throwing multiple exceptions if you sent empty mail to several valid receivers.

(I also want to move away from APIs oriented around raw addresses in more specialized layers, and this is one of the few callsites for raw mail address information.)

This requires updating some unit tests to actually have message bodies, since they failed with this error before hitting the other errors otherwise.

Test Plan: Used `bin/mail receive-test` to send empty mail, got appropriate "err:empty" out of it.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T7477, T920

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

+56 -43
+2 -4
src/applications/maniphest/mail/ManiphestTaskMailReceiver.php
··· 14 14 protected function loadObject($pattern, PhabricatorUser $viewer) { 15 15 $id = (int)trim($pattern, 'T'); 16 16 17 - $results = id(new ManiphestTaskQuery()) 17 + return id(new ManiphestTaskQuery()) 18 18 ->setViewer($viewer) 19 19 ->withIDs(array($id)) 20 20 ->needSubscriberPHIDs(true) 21 21 ->needProjectPHIDs(true) 22 - ->execute(); 23 - 24 - return head($results); 22 + ->executeOne(); 25 23 } 26 24 27 25 protected function getTransactionReplyHandler() {
+13 -8
src/applications/metamta/receiver/__tests__/PhabricatorObjectMailReceiverTestCase.php
··· 23 23 $mail->getStatus()); 24 24 } 25 25 26 - /* 27 - 28 - TODO: Tasks don't support policies yet. Implement this once they do. 29 - 30 26 public function testDropPolicyViolationMail() { 31 - list($task, $user, $mail) = $this->buildMail('public'); 27 + list($task, $user, $mail) = $this->buildMail('policy'); 32 28 33 - // TODO: Set task policy to "no one" here. 29 + $task 30 + ->setViewPolicy(PhabricatorPolicies::POLICY_NOONE) 31 + ->setOwnerPHID(null) 32 + ->save(); 33 + 34 + $env = PhabricatorEnv::beginScopedEnv(); 35 + $env->overrideEnvConfig('metamta.public-replies', true); 34 36 35 37 $mail->save(); 36 38 $mail->processReceivedMail(); ··· 39 41 MetaMTAReceivedMailStatus::STATUS_POLICY_PROBLEM, 40 42 $mail->getStatus()); 41 43 } 42 - 43 - */ 44 44 45 45 public function testDropInvalidObjectMail() { 46 46 list($task, $user, $mail) = $this->buildMail('404'); ··· 120 120 'Message-ID' => 'test@example.com', 121 121 'From' => $user->loadPrimaryEmail()->getAddress(), 122 122 'To' => $to, 123 + )); 124 + 125 + $mail->setBodies( 126 + array( 127 + 'text' => 'test', 123 128 )); 124 129 125 130 return array($task, $user, $mail);
-31
src/applications/metamta/replyhandler/PhabricatorMailReplyHandler.php
··· 67 67 PhabricatorMetaMTAReceivedMail $mail); 68 68 69 69 public function processEmail(PhabricatorMetaMTAReceivedMail $mail) { 70 - $this->dropEmptyMail($mail); 71 - 72 70 return $this->receiveEmail($mail); 73 - } 74 - 75 - private function dropEmptyMail(PhabricatorMetaMTAReceivedMail $mail) { 76 - $body = $mail->getCleanTextBody(); 77 - $attachments = $mail->getAttachments(); 78 - 79 - if (strlen($body) || $attachments) { 80 - return; 81 - } 82 - 83 - // Only send an error email if the user is talking to just Phabricator. 84 - // We can assume if there is only one "To" address it is a Phabricator 85 - // address since this code is running and everything. 86 - $is_direct_mail = (count($mail->getToAddresses()) == 1) && 87 - (count($mail->getCCAddresses()) == 0); 88 - 89 - if ($is_direct_mail) { 90 - $status_code = MetaMTAReceivedMailStatus::STATUS_EMPTY; 91 - } else { 92 - $status_code = MetaMTAReceivedMailStatus::STATUS_EMPTY_IGNORED; 93 - } 94 - 95 - throw new PhabricatorMetaMTAReceivedMailProcessingException( 96 - $status_code, 97 - pht( 98 - 'Your message does not contain any body text or attachments, so '. 99 - 'Phabricator can not do anything useful with it. Make sure comment '. 100 - 'text appears at the top of your message: quoted replies, inline '. 101 - 'text, and signatures are discarded and ignored.')); 102 71 } 103 72 104 73 public function supportsPrivateReplies() {
+29
src/applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php
··· 109 109 try { 110 110 $this->dropMailFromPhabricator(); 111 111 $this->dropMailAlreadyReceived(); 112 + $this->dropEmptyMail(); 112 113 113 114 $receiver = $this->loadReceiver(); 114 115 $sender = $receiver->loadSender($this); ··· 260 261 $message); 261 262 } 262 263 264 + private function dropEmptyMail() { 265 + $body = $this->getCleanTextBody(); 266 + $attachments = $this->getAttachments(); 267 + 268 + if (strlen($body) || $attachments) { 269 + return; 270 + } 271 + 272 + // Only send an error email if the user is talking to just Phabricator. 273 + // We can assume if there is only one "To" address it is a Phabricator 274 + // address since this code is running and everything. 275 + $is_direct_mail = (count($this->getToAddresses()) == 1) && 276 + (count($this->getCCAddresses()) == 0); 277 + 278 + if ($is_direct_mail) { 279 + $status_code = MetaMTAReceivedMailStatus::STATUS_EMPTY; 280 + } else { 281 + $status_code = MetaMTAReceivedMailStatus::STATUS_EMPTY_IGNORED; 282 + } 283 + 284 + throw new PhabricatorMetaMTAReceivedMailProcessingException( 285 + $status_code, 286 + pht( 287 + 'Your message does not contain any body text or attachments, so '. 288 + 'Phabricator can not do anything useful with it. Make sure comment '. 289 + 'text appears at the top of your message: quoted replies, inline '. 290 + 'text, and signatures are discarded and ignored.')); 291 + } 263 292 264 293 /** 265 294 * Load a concrete instance of the @{class:PhabricatorMailReceiver} which
+12
src/applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php
··· 54 54 'Message-ID' => 'test@example.com', 55 55 'To' => 'does+not+exist@example.com', 56 56 )); 57 + $mail->setBodies( 58 + array( 59 + 'text' => 'test', 60 + )); 57 61 $mail->save(); 58 62 59 63 $mail->processReceivedMail(); ··· 77 81 'To' => 'bugs@example.com', 78 82 'From' => 'does+not+exist@example.com', 79 83 )); 84 + $mail->setBodies( 85 + array( 86 + 'text' => 'test', 87 + )); 80 88 $mail->save(); 81 89 82 90 $mail->processReceivedMail(); ··· 100 108 'Message-ID' => 'test@example.com', 101 109 'From' => $user->loadPrimaryEmail()->getAddress(), 102 110 'To' => 'bugs@example.com', 111 + )); 112 + $mail->setBodies( 113 + array( 114 + 'text' => 'test', 103 115 )); 104 116 $mail->save(); 105 117