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

Remove the last hardcoding from PhabricatorMetaMTAReceivedMail

Summary:
Moves all remaining mail handling into ReplyHandlers.

Farewell, `getPhabricatorToInformation()`! You were a bad method and no one liked you.

Ref T1205.

Test Plan:
- Used test console to send mail to Revisions, Tasks, Conpherences and Commits (these all actually work).
- Used test console to send mail to Requests, Macros, Questions and Mocks (these accept the mail but don't do anything with it, but didn't do anything before either).

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T1205

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

+144 -171
+13
src/applications/audit/mail/PhabricatorAuditMailReceiver.php
··· 20 20 ->executeOne(); 21 21 } 22 22 23 + protected function processReceivedObjectMail( 24 + PhabricatorMetaMTAReceivedMail $mail, 25 + PhabricatorLiskDAO $object, 26 + PhabricatorUser $sender) { 27 + 28 + $handler = PhabricatorAuditCommentEditor::newReplyHandlerForCommit($object); 29 + 30 + $handler->setActor($sender); 31 + $handler->setExcludeMailRecipientPHIDs( 32 + $mail->loadExcludeMailRecipientPHIDs()); 33 + $handler->processEmail($mail); 34 + } 35 + 23 36 }
+1 -1
src/applications/conpherence/mail/ConpherenceCreateThreadMailReceiver.php
··· 45 45 $usernames); 46 46 } 47 47 48 - public function processReceivedMail( 48 + protected function processReceivedMail( 49 49 PhabricatorMetaMTAReceivedMail $mail, 50 50 PhabricatorUser $sender) { 51 51
+13
src/applications/conpherence/mail/ConpherenceThreadMailReceiver.php
··· 21 21 ->executeOne(); 22 22 } 23 23 24 + protected function processReceivedObjectMail( 25 + PhabricatorMetaMTAReceivedMail $mail, 26 + PhabricatorLiskDAO $object, 27 + PhabricatorUser $sender) { 28 + 29 + $handler = id(new ConpherenceReplyHandler()) 30 + ->setMailReceiver($object); 31 + 32 + $handler->setActor($sender); 33 + $handler->setExcludeMailRecipientPHIDs( 34 + $mail->loadExcludeMailRecipientPHIDs()); 35 + $handler->processEmail($mail); 36 + } 24 37 25 38 }
+12
src/applications/differential/mail/DifferentialRevisionMailReceiver.php
··· 23 23 return head($results); 24 24 } 25 25 26 + protected function processReceivedObjectMail( 27 + PhabricatorMetaMTAReceivedMail $mail, 28 + PhabricatorLiskDAO $object, 29 + PhabricatorUser $sender) { 30 + 31 + $handler = DifferentialMail::newReplyHandlerForRevision($object); 32 + 33 + $handler->setActor($sender); 34 + $handler->setExcludeMailRecipientPHIDs( 35 + $mail->loadExcludeMailRecipientPHIDs()); 36 + $handler->processEmail($mail); 37 + } 26 38 27 39 }
+10
src/applications/macro/mail/PhabricatorMacroMailReceiver.php
··· 21 21 ->executeOne(); 22 22 } 23 23 24 + protected function processReceivedObjectMail( 25 + PhabricatorMetaMTAReceivedMail $mail, 26 + PhabricatorLiskDAO $object, 27 + PhabricatorUser $sender) { 28 + 29 + // TODO: For now, we just drop this mail on the floor. 30 + 31 + } 32 + 33 + 24 34 }
+1 -1
src/applications/maniphest/mail/ManiphestCreateMailReceiver.php
··· 56 56 } 57 57 } 58 58 59 - public function processReceivedMail( 59 + protected function processReceivedMail( 60 60 PhabricatorMetaMTAReceivedMail $mail, 61 61 PhabricatorUser $sender) { 62 62
+15
src/applications/maniphest/mail/ManiphestTaskMailReceiver.php
··· 22 22 return head($results); 23 23 } 24 24 25 + protected function processReceivedObjectMail( 26 + PhabricatorMetaMTAReceivedMail $mail, 27 + PhabricatorLiskDAO $object, 28 + PhabricatorUser $sender) { 29 + 30 + $editor = new ManiphestTransactionEditor(); 31 + $editor->setActor($sender); 32 + $handler = $editor->buildReplyHandler($object); 33 + 34 + $handler->setActor($sender); 35 + $handler->setExcludeMailRecipientPHIDs( 36 + $mail->loadExcludeMailRecipientPHIDs()); 37 + $handler->processEmail($mail); 38 + } 39 + 25 40 }
+1
src/applications/metamta/constants/MetaMTAReceivedMailStatus.php
··· 14 14 const STATUS_POLICY_PROBLEM = 'err:policy'; 15 15 const STATUS_NO_SUCH_OBJECT = 'err:not-found'; 16 16 const STATUS_HASH_MISMATCH = 'err:bad-hash'; 17 + const STATUS_UNHANDLED_EXCEPTION = 'err:exception'; 17 18 18 19 }
+2 -4
src/applications/metamta/receiver/PhabricatorMailReceiver.php
··· 5 5 abstract public function isEnabled(); 6 6 abstract public function canAcceptMail(PhabricatorMetaMTAReceivedMail $mail); 7 7 8 - public function processReceivedMail( 8 + abstract protected function processReceivedMail( 9 9 PhabricatorMetaMTAReceivedMail $mail, 10 - PhabricatorUser $sender) { 11 - return; 12 - } 10 + PhabricatorUser $sender); 13 11 14 12 final public function receiveMail( 15 13 PhabricatorMetaMTAReceivedMail $mail,
+43 -11
src/applications/metamta/receiver/PhabricatorObjectMailReceiver.php
··· 26 26 */ 27 27 abstract protected function loadObject($pattern, PhabricatorUser $viewer); 28 28 29 + 30 + final protected function processReceivedMail( 31 + PhabricatorMetaMTAReceivedMail $mail, 32 + PhabricatorUser $sender) { 33 + 34 + $object = $this->loadObjectFromMail($mail, $sender); 35 + $mail->setRelatedPHID($object->getPHID()); 36 + 37 + $this->processReceivedObjectMail($mail, $object, $sender); 38 + 39 + return $this; 40 + } 41 + 42 + abstract protected function processReceivedObjectMail( 43 + PhabricatorMetaMTAReceivedMail $mail, 44 + PhabricatorLiskDAO $object, 45 + PhabricatorUser $sender); 46 + 29 47 public function loadMailReceiverObject($pattern, PhabricatorUser $viewer) { 30 48 return $this->loadObject($pattern, $viewer); 31 49 } 32 50 33 - 34 51 public function validateSender( 35 52 PhabricatorMetaMTAReceivedMail $mail, 36 53 PhabricatorUser $sender) { 54 + 37 55 parent::validateSender($mail, $sender); 38 56 39 - foreach ($mail->getToAddresses() as $address) { 40 - $parts = $this->matchObjectAddress($address); 41 - if ($parts) { 42 - break; 43 - } 44 - } 57 + $parts = $this->matchObjectAddressInMail($mail); 45 58 46 59 try { 47 - $object = $this->loadObject($parts['pattern'], $sender); 60 + $object = $this->loadObjectFromMail($mail, $sender); 48 61 } catch (PhabricatorPolicyException $policy_exception) { 49 62 throw new PhabricatorMetaMTAReceivedMailProcessingException( 50 63 MetaMTAReceivedMailStatus::STATUS_POLICY_PROBLEM, ··· 99 112 100 113 101 114 final public function canAcceptMail(PhabricatorMetaMTAReceivedMail $mail) { 115 + if ($this->matchObjectAddressInMail($mail)) { 116 + return true; 117 + } 118 + 119 + return false; 120 + } 121 + 122 + private function matchObjectAddressInMail( 123 + PhabricatorMetaMTAReceivedmail $mail) { 124 + 102 125 foreach ($mail->getToAddresses() as $address) { 103 - if ($this->matchObjectAddress($address)) { 104 - return true; 126 + $parts = $this->matchObjectAddress($address); 127 + if ($parts) { 128 + return $parts; 105 129 } 106 130 } 107 131 108 - return false; 132 + return null; 109 133 } 110 134 111 135 private function matchObjectAddress($address) { ··· 135 159 '$)U'; 136 160 137 161 return $regexp; 162 + } 163 + 164 + private function loadObjectFromMail( 165 + PhabricatorMetaMTAReceivedMail $mail, 166 + PhabricatorUser $sender) { 167 + $parts = $this->matchObjectAddressInMail($mail); 168 + 169 + return $this->loadObject($parts['pattern'], $sender); 138 170 } 139 171 140 172 public static function computeMailHash($mail_key, $phid) {
+8 -154
src/applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php
··· 88 88 return array_merge($user_phids, $mailing_list_phids); 89 89 } 90 90 91 - /** 92 - * Parses "to" addresses, looking for a public create email address 93 - * first and if not found parsing the "to" address for reply handler 94 - * information: receiver name, user id, and hash. If nothing can be 95 - * found, it then loads user phids for as many to: email addresses as 96 - * it can, theoretically falling back to create a conpherence amongst 97 - * those users. 98 - */ 99 - private function getPhabricatorToInformation() { 100 - // Only one "public" create address so far 101 - $create_task = PhabricatorEnv::getEnvConfig( 102 - 'metamta.maniphest.public-create-email'); 103 - 104 - // For replies, look for an object address with a format like: 105 - // D291+291+b0a41ca848d66dcc@example.com 106 - $single_handle_prefix = PhabricatorEnv::getEnvConfig( 107 - 'metamta.single-reply-handler-prefix'); 108 - 109 - $prefixPattern = ($single_handle_prefix) 110 - ? preg_quote($single_handle_prefix, '/') . '\+' 111 - : ''; 112 - $pattern = "/^{$prefixPattern}((?:D|T|C|E)\d+)\+([\w]+)\+([a-f0-9]{16})@/U"; 113 - 114 - $phabricator_address = null; 115 - $receiver_name = null; 116 - $user_id = null; 117 - $hash = null; 118 - $user_names = array(); 119 - foreach ($this->getToAddresses() as $address) { 120 - if ($address == $create_task) { 121 - $phabricator_address = $address; 122 - // it's okay to stop here because we just need to map a create 123 - // address to an application and don't need / won't have more 124 - // information in these cases. 125 - break; 126 - } 127 - 128 - $matches = null; 129 - $ok = preg_match( 130 - $pattern, 131 - $address, 132 - $matches); 133 - 134 - if ($ok) { 135 - $phabricator_address = $address; 136 - $receiver_name = $matches[1]; 137 - $user_id = $matches[2]; 138 - $hash = $matches[3]; 139 - break; 140 - } 141 - 142 - $parts = explode('@', $address); 143 - $maybe_name = trim($parts[0]); 144 - $maybe_domain = trim($parts[1]); 145 - $mail_domain = PhabricatorEnv::getEnvConfig('metamta.domain'); 146 - if ($mail_domain == $maybe_domain && 147 - PhabricatorUser::validateUsername($maybe_name)) { 148 - $user_names[] = $maybe_name; 149 - } 150 - } 151 - 152 - return array( 153 - $phabricator_address, 154 - $receiver_name, 155 - $user_id, 156 - $hash, 157 - ); 158 - } 159 - 160 - 161 91 public function processReceivedMail() { 162 92 163 93 try { ··· 170 100 171 101 $this->setAuthorPHID($sender->getPHID()); 172 102 173 - // TODO: Once everything can receive mail, nuke this. 174 - $can_receive = false; 175 - if ($receiver instanceof ManiphestCreateMailReceiver) { 176 - $can_receive = true; 177 - } 178 - if ($receiver instanceof ConpherenceCreateThreadMailReceiver) { 179 - $can_receive = true; 180 - } 181 - 182 - if ($can_receive) { 183 - $receiver->receiveMail($this, $sender); 184 - return $this->setMessage('OK')->save(); 185 - } 186 - 103 + $receiver->receiveMail($this, $sender); 187 104 } catch (PhabricatorMetaMTAReceivedMailProcessingException $ex) { 188 105 $this 189 106 ->setStatus($ex->getStatusCode()) 190 107 ->setMessage($ex->getMessage()) 191 108 ->save(); 192 109 return $this; 193 - } 110 + } catch (Exception $ex) { 111 + $this 112 + ->setStatus(MetaMTAReceivedMailStatus::STATUS_UNHANDLED_EXCEPTION) 113 + ->setMessage(pht('Unhandled Exception: %s', $ex->getMessage())) 114 + ->save(); 194 115 195 - list($to, 196 - $receiver_name, 197 - $user_id, 198 - $hash) = $this->getPhabricatorToInformation(); 199 - if (!$to) { 200 - $raw_to = idx($this->headers, 'to'); 201 - return $this->setMessage("Unrecognized 'to' format: {$raw_to}")->save(); 116 + throw $ex; 202 117 } 203 118 204 - $from = idx($this->headers, 'from'); 205 - 206 - $user = $sender; 207 - 208 - $receiver = self::loadReceiverObject($receiver_name); 209 - if (!$receiver) { 210 - return $this->setMessage("Invalid object '{$receiver_name}'")->save(); 211 - } 212 - 213 - $this->setRelatedPHID($receiver->getPHID()); 214 - 215 - if ($receiver instanceof ManiphestTask) { 216 - $editor = new ManiphestTransactionEditor(); 217 - $editor->setActor($user); 218 - $handler = $editor->buildReplyHandler($receiver); 219 - } else if ($receiver instanceof DifferentialRevision) { 220 - $handler = DifferentialMail::newReplyHandlerForRevision($receiver); 221 - } else if ($receiver instanceof PhabricatorRepositoryCommit) { 222 - $handler = PhabricatorAuditCommentEditor::newReplyHandlerForCommit( 223 - $receiver); 224 - } else if ($receiver instanceof ConpherenceThread) { 225 - $handler = id(new ConpherenceReplyHandler()) 226 - ->setMailReceiver($receiver); 227 - } 228 - 229 - $handler->setActor($user); 230 - $handler->setExcludeMailRecipientPHIDs( 231 - $this->loadExcludeMailRecipientPHIDs()); 232 - $handler->processEmail($this); 233 - 234 - $this->setMessage('OK'); 235 - 236 - return $this->save(); 119 + return $this->setMessage('OK')->save(); 237 120 } 238 121 239 122 public function getCleanTextBody() { ··· 245 128 246 129 public function getRawTextBody() { 247 130 return idx($this->bodies, 'text'); 248 - } 249 - 250 - public static function loadReceiverObject($receiver_name) { 251 - if (!$receiver_name) { 252 - return null; 253 - } 254 - 255 - $receiver_type = $receiver_name[0]; 256 - $receiver_id = substr($receiver_name, 1); 257 - 258 - $class_obj = null; 259 - switch ($receiver_type) { 260 - case 'T': 261 - $class_obj = new ManiphestTask(); 262 - break; 263 - case 'D': 264 - $class_obj = new DifferentialRevision(); 265 - break; 266 - case 'C': 267 - $class_obj = new PhabricatorRepositoryCommit(); 268 - break; 269 - case 'E': 270 - $class_obj = new ConpherenceThread(); 271 - break; 272 - default: 273 - return null; 274 - } 275 - 276 - return $class_obj->load($receiver_id); 277 131 } 278 132 279 133 /**
+9
src/applications/pholio/mail/PholioMockMailReceiver.php
··· 20 20 ->executeOne(); 21 21 } 22 22 23 + protected function processReceivedObjectMail( 24 + PhabricatorMetaMTAReceivedMail $mail, 25 + PhabricatorLiskDAO $object, 26 + PhabricatorUser $sender) { 27 + 28 + // TODO: For now, we just drop this mail on the floor. 29 + 30 + } 31 + 23 32 24 33 }
+8
src/applications/ponder/mail/PonderQuestionMailReceiver.php
··· 20 20 ->executeOne(); 21 21 } 22 22 23 + protected function processReceivedObjectMail( 24 + PhabricatorMetaMTAReceivedMail $mail, 25 + PhabricatorLiskDAO $object, 26 + PhabricatorUser $sender) { 27 + 28 + // TODO: For now, we just drop this mail on the floor. 29 + 30 + } 23 31 24 32 }
+8
src/applications/releeph/mail/ReleephRequestMailReceiver.php
··· 20 20 ->executeOne(); 21 21 } 22 22 23 + protected function processReceivedObjectMail( 24 + PhabricatorMetaMTAReceivedMail $mail, 25 + PhabricatorLiskDAO $object, 26 + PhabricatorUser $sender) { 27 + 28 + // TODO: For now, we just drop this mail on the floor. 29 + 30 + } 23 31 24 32 }