1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-22 13:30:55 +01:00

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
This commit is contained in:
epriestley 2013-05-17 10:00:49 -07:00
parent 1898a540d8
commit 5cd13c3c65
14 changed files with 146 additions and 173 deletions

View file

@ -20,4 +20,17 @@ final class PhabricatorAuditMailReceiver extends PhabricatorObjectMailReceiver {
->executeOne();
}
protected function processReceivedObjectMail(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorLiskDAO $object,
PhabricatorUser $sender) {
$handler = PhabricatorAuditCommentEditor::newReplyHandlerForCommit($object);
$handler->setActor($sender);
$handler->setExcludeMailRecipientPHIDs(
$mail->loadExcludeMailRecipientPHIDs());
$handler->processEmail($mail);
}
}

View file

@ -45,7 +45,7 @@ final class ConpherenceCreateThreadMailReceiver
$usernames);
}
public function processReceivedMail(
protected function processReceivedMail(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorUser $sender) {

View file

@ -21,5 +21,18 @@ final class ConpherenceThreadMailReceiver
->executeOne();
}
protected function processReceivedObjectMail(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorLiskDAO $object,
PhabricatorUser $sender) {
$handler = id(new ConpherenceReplyHandler())
->setMailReceiver($object);
$handler->setActor($sender);
$handler->setExcludeMailRecipientPHIDs(
$mail->loadExcludeMailRecipientPHIDs());
$handler->processEmail($mail);
}
}

View file

@ -23,5 +23,17 @@ final class DifferentialRevisionMailReceiver
return head($results);
}
protected function processReceivedObjectMail(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorLiskDAO $object,
PhabricatorUser $sender) {
$handler = DifferentialMail::newReplyHandlerForRevision($object);
$handler->setActor($sender);
$handler->setExcludeMailRecipientPHIDs(
$mail->loadExcludeMailRecipientPHIDs());
$handler->processEmail($mail);
}
}

View file

@ -21,4 +21,14 @@ final class PhabricatorMacroMailReceiver extends PhabricatorObjectMailReceiver {
->executeOne();
}
protected function processReceivedObjectMail(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorLiskDAO $object,
PhabricatorUser $sender) {
// TODO: For now, we just drop this mail on the floor.
}
}

View file

@ -56,7 +56,7 @@ final class ManiphestCreateMailReceiver extends PhabricatorMailReceiver {
}
}
public function processReceivedMail(
protected function processReceivedMail(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorUser $sender) {

View file

@ -22,4 +22,19 @@ final class ManiphestTaskMailReceiver extends PhabricatorObjectMailReceiver {
return head($results);
}
protected function processReceivedObjectMail(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorLiskDAO $object,
PhabricatorUser $sender) {
$editor = new ManiphestTransactionEditor();
$editor->setActor($sender);
$handler = $editor->buildReplyHandler($object);
$handler->setActor($sender);
$handler->setExcludeMailRecipientPHIDs(
$mail->loadExcludeMailRecipientPHIDs());
$handler->processEmail($mail);
}
}

View file

@ -14,5 +14,6 @@ final class MetaMTAReceivedMailStatus
const STATUS_POLICY_PROBLEM = 'err:policy';
const STATUS_NO_SUCH_OBJECT = 'err:not-found';
const STATUS_HASH_MISMATCH = 'err:bad-hash';
const STATUS_UNHANDLED_EXCEPTION = 'err:exception';
}

View file

@ -5,11 +5,9 @@ abstract class PhabricatorMailReceiver {
abstract public function isEnabled();
abstract public function canAcceptMail(PhabricatorMetaMTAReceivedMail $mail);
public function processReceivedMail(
abstract protected function processReceivedMail(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorUser $sender) {
return;
}
PhabricatorUser $sender);
final public function receiveMail(
PhabricatorMetaMTAReceivedMail $mail,

View file

@ -26,25 +26,38 @@ abstract class PhabricatorObjectMailReceiver extends PhabricatorMailReceiver {
*/
abstract protected function loadObject($pattern, PhabricatorUser $viewer);
final protected function processReceivedMail(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorUser $sender) {
$object = $this->loadObjectFromMail($mail, $sender);
$mail->setRelatedPHID($object->getPHID());
$this->processReceivedObjectMail($mail, $object, $sender);
return $this;
}
abstract protected function processReceivedObjectMail(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorLiskDAO $object,
PhabricatorUser $sender);
public function loadMailReceiverObject($pattern, PhabricatorUser $viewer) {
return $this->loadObject($pattern, $viewer);
}
public function validateSender(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorUser $sender) {
parent::validateSender($mail, $sender);
foreach ($mail->getToAddresses() as $address) {
$parts = $this->matchObjectAddress($address);
if ($parts) {
break;
}
}
$parts = $this->matchObjectAddressInMail($mail);
try {
$object = $this->loadObject($parts['pattern'], $sender);
$object = $this->loadObjectFromMail($mail, $sender);
} catch (PhabricatorPolicyException $policy_exception) {
throw new PhabricatorMetaMTAReceivedMailProcessingException(
MetaMTAReceivedMailStatus::STATUS_POLICY_PROBLEM,
@ -99,15 +112,26 @@ abstract class PhabricatorObjectMailReceiver extends PhabricatorMailReceiver {
final public function canAcceptMail(PhabricatorMetaMTAReceivedMail $mail) {
foreach ($mail->getToAddresses() as $address) {
if ($this->matchObjectAddress($address)) {
return true;
}
if ($this->matchObjectAddressInMail($mail)) {
return true;
}
return false;
}
private function matchObjectAddressInMail(
PhabricatorMetaMTAReceivedmail $mail) {
foreach ($mail->getToAddresses() as $address) {
$parts = $this->matchObjectAddress($address);
if ($parts) {
return $parts;
}
}
return null;
}
private function matchObjectAddress($address) {
$regexp = $this->getAddressRegexp();
@ -137,6 +161,14 @@ abstract class PhabricatorObjectMailReceiver extends PhabricatorMailReceiver {
return $regexp;
}
private function loadObjectFromMail(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorUser $sender) {
$parts = $this->matchObjectAddressInMail($mail);
return $this->loadObject($parts['pattern'], $sender);
}
public static function computeMailHash($mail_key, $phid) {
$global_mail_key = PhabricatorEnv::getEnvConfig('phabricator.mail-key');

View file

@ -88,76 +88,6 @@ final class PhabricatorMetaMTAReceivedMail extends PhabricatorMetaMTADAO {
return array_merge($user_phids, $mailing_list_phids);
}
/**
* Parses "to" addresses, looking for a public create email address
* first and if not found parsing the "to" address for reply handler
* information: receiver name, user id, and hash. If nothing can be
* found, it then loads user phids for as many to: email addresses as
* it can, theoretically falling back to create a conpherence amongst
* those users.
*/
private function getPhabricatorToInformation() {
// Only one "public" create address so far
$create_task = PhabricatorEnv::getEnvConfig(
'metamta.maniphest.public-create-email');
// For replies, look for an object address with a format like:
// D291+291+b0a41ca848d66dcc@example.com
$single_handle_prefix = PhabricatorEnv::getEnvConfig(
'metamta.single-reply-handler-prefix');
$prefixPattern = ($single_handle_prefix)
? preg_quote($single_handle_prefix, '/') . '\+'
: '';
$pattern = "/^{$prefixPattern}((?:D|T|C|E)\d+)\+([\w]+)\+([a-f0-9]{16})@/U";
$phabricator_address = null;
$receiver_name = null;
$user_id = null;
$hash = null;
$user_names = array();
foreach ($this->getToAddresses() as $address) {
if ($address == $create_task) {
$phabricator_address = $address;
// it's okay to stop here because we just need to map a create
// address to an application and don't need / won't have more
// information in these cases.
break;
}
$matches = null;
$ok = preg_match(
$pattern,
$address,
$matches);
if ($ok) {
$phabricator_address = $address;
$receiver_name = $matches[1];
$user_id = $matches[2];
$hash = $matches[3];
break;
}
$parts = explode('@', $address);
$maybe_name = trim($parts[0]);
$maybe_domain = trim($parts[1]);
$mail_domain = PhabricatorEnv::getEnvConfig('metamta.domain');
if ($mail_domain == $maybe_domain &&
PhabricatorUser::validateUsername($maybe_name)) {
$user_names[] = $maybe_name;
}
}
return array(
$phabricator_address,
$receiver_name,
$user_id,
$hash,
);
}
public function processReceivedMail() {
try {
@ -170,70 +100,23 @@ final class PhabricatorMetaMTAReceivedMail extends PhabricatorMetaMTADAO {
$this->setAuthorPHID($sender->getPHID());
// TODO: Once everything can receive mail, nuke this.
$can_receive = false;
if ($receiver instanceof ManiphestCreateMailReceiver) {
$can_receive = true;
}
if ($receiver instanceof ConpherenceCreateThreadMailReceiver) {
$can_receive = true;
}
if ($can_receive) {
$receiver->receiveMail($this, $sender);
return $this->setMessage('OK')->save();
}
$receiver->receiveMail($this, $sender);
} catch (PhabricatorMetaMTAReceivedMailProcessingException $ex) {
$this
->setStatus($ex->getStatusCode())
->setMessage($ex->getMessage())
->save();
return $this;
} catch (Exception $ex) {
$this
->setStatus(MetaMTAReceivedMailStatus::STATUS_UNHANDLED_EXCEPTION)
->setMessage(pht('Unhandled Exception: %s', $ex->getMessage()))
->save();
throw $ex;
}
list($to,
$receiver_name,
$user_id,
$hash) = $this->getPhabricatorToInformation();
if (!$to) {
$raw_to = idx($this->headers, 'to');
return $this->setMessage("Unrecognized 'to' format: {$raw_to}")->save();
}
$from = idx($this->headers, 'from');
$user = $sender;
$receiver = self::loadReceiverObject($receiver_name);
if (!$receiver) {
return $this->setMessage("Invalid object '{$receiver_name}'")->save();
}
$this->setRelatedPHID($receiver->getPHID());
if ($receiver instanceof ManiphestTask) {
$editor = new ManiphestTransactionEditor();
$editor->setActor($user);
$handler = $editor->buildReplyHandler($receiver);
} else if ($receiver instanceof DifferentialRevision) {
$handler = DifferentialMail::newReplyHandlerForRevision($receiver);
} else if ($receiver instanceof PhabricatorRepositoryCommit) {
$handler = PhabricatorAuditCommentEditor::newReplyHandlerForCommit(
$receiver);
} else if ($receiver instanceof ConpherenceThread) {
$handler = id(new ConpherenceReplyHandler())
->setMailReceiver($receiver);
}
$handler->setActor($user);
$handler->setExcludeMailRecipientPHIDs(
$this->loadExcludeMailRecipientPHIDs());
$handler->processEmail($this);
$this->setMessage('OK');
return $this->save();
return $this->setMessage('OK')->save();
}
public function getCleanTextBody() {
@ -247,35 +130,6 @@ final class PhabricatorMetaMTAReceivedMail extends PhabricatorMetaMTADAO {
return idx($this->bodies, 'text');
}
public static function loadReceiverObject($receiver_name) {
if (!$receiver_name) {
return null;
}
$receiver_type = $receiver_name[0];
$receiver_id = substr($receiver_name, 1);
$class_obj = null;
switch ($receiver_type) {
case 'T':
$class_obj = new ManiphestTask();
break;
case 'D':
$class_obj = new DifferentialRevision();
break;
case 'C':
$class_obj = new PhabricatorRepositoryCommit();
break;
case 'E':
$class_obj = new ConpherenceThread();
break;
default:
return null;
}
return $class_obj->load($receiver_id);
}
/**
* Strip an email address down to the actual user@domain.tld part if
* necessary, since sometimes it will have formatting like

View file

@ -20,5 +20,14 @@ final class PholioMockMailReceiver extends PhabricatorObjectMailReceiver {
->executeOne();
}
protected function processReceivedObjectMail(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorLiskDAO $object,
PhabricatorUser $sender) {
// TODO: For now, we just drop this mail on the floor.
}
}

View file

@ -20,5 +20,13 @@ final class PonderQuestionMailReceiver extends PhabricatorObjectMailReceiver {
->executeOne();
}
protected function processReceivedObjectMail(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorLiskDAO $object,
PhabricatorUser $sender) {
// TODO: For now, we just drop this mail on the floor.
}
}

View file

@ -20,5 +20,13 @@ final class ReleephRequestMailReceiver extends PhabricatorObjectMailReceiver {
->executeOne();
}
protected function processReceivedObjectMail(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorLiskDAO $object,
PhabricatorUser $sender) {
// TODO: For now, we just drop this mail on the floor.
}
}