From 275f708f1447277f3dc05558b32d9ea400ecd2e7 Mon Sep 17 00:00:00 2001 From: Bob Trahan Date: Thu, 7 Feb 2013 15:17:11 -0800 Subject: [PATCH] Conpherence - make messages to btrahan@metamta.domain start conpherences Summary: I'm not super happy with the prettiness of the code, but I wasn't able to come up with a good way to clean it up. Happy for suggestions. Test Plan: sent message to btrahan@phabricator.dev from gmail. Copied raw email and piped it to mail_handler.php -- it created a conpherence! Repeated but sent to btrahan and xerxes and noted that the conpherence was created for both users Reviewers: epriestley, chad Reviewed By: epriestley CC: aran, Korvin Maniphest Tasks: T2431 Differential Revision: https://secure.phabricator.com/D4854 --- .../mail/ConpherenceReplyHandler.php | 29 ++++++++-- .../PhabricatorMetaMTAReceivedMail.php | 58 ++++++++++++++++--- 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/src/applications/conpherence/mail/ConpherenceReplyHandler.php b/src/applications/conpherence/mail/ConpherenceReplyHandler.php index f7de36cb25..0955a6a961 100644 --- a/src/applications/conpherence/mail/ConpherenceReplyHandler.php +++ b/src/applications/conpherence/mail/ConpherenceReplyHandler.php @@ -5,6 +5,16 @@ */ final class ConpherenceReplyHandler extends PhabricatorMailReplyHandler { + private $mailAddedParticipantPHIDs; + + public function setMailAddedParticipantPHIDs(array $phids) { + $this->mailAddedParticipantPHIDs = $phids; + return $this; + } + public function getMailAddedParticipantPHIDs() { + return $this->mailAddedParticipantPHIDs; + } + public function validateMailReceiver($mail_receiver) { if (!($mail_receiver instanceof ConpherenceThread)) { throw new Exception("Mail receiver is not a ConpherenceThread!"); @@ -67,14 +77,25 @@ final class ConpherenceReplyHandler extends PhabricatorMailReplyHandler { $file_phids, '{F%d}' ); - $xactions = $editor->generateTransactionsFromText( - $conpherence, - $body + + $xactions = array(); + if ($this->getMailAddedParticipantPHIDs()) { + $xactions[] = id(new ConpherenceTransaction()) + ->setTransactionType(ConpherenceTransactionType::TYPE_PARTICIPANTS) + ->setNewValue(array('+' => $this->getMailAddedParticipantPHIDs())); + } + + $xactions = array_merge( + $xactions, + $editor->generateTransactionsFromText( + $conpherence, + $body + ) ); $editor->applyTransactions($conpherence, $xactions); - return null; + return $conpherence; } } diff --git a/src/applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php b/src/applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php index ca7dee2acf..d547e458bd 100644 --- a/src/applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php +++ b/src/applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php @@ -78,7 +78,10 @@ final class PhabricatorMetaMTAReceivedMail extends PhabricatorMetaMTADAO { /** * 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. + * 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 @@ -99,6 +102,8 @@ final class PhabricatorMetaMTAReceivedMail extends PhabricatorMetaMTADAO { $receiver_name = null; $user_id = null; $hash = null; + $user_phids = array(); + $user_names = array(); foreach ($this->getToAddresses() as $address) { if ($address == $create_task) { $phabricator_address = $address; @@ -121,13 +126,31 @@ final class PhabricatorMetaMTAReceivedMail extends PhabricatorMetaMTADAO { $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; + } + } + + // since we haven't found a phabricator address, maybe this is + // someone trying to create a conpherence? + if (!$phabricator_address && $user_names) { + $users = id(new PhabricatorUser()) + ->loadAllWhere('userName IN (%Ls)', $user_names); + $user_phids = mpull($users, 'getPHID'); } return array( $phabricator_address, $receiver_name, $user_id, - $hash + $hash, + $user_phids ); } @@ -170,8 +193,9 @@ final class PhabricatorMetaMTAReceivedMail extends PhabricatorMetaMTADAO { list($to, $receiver_name, $user_id, - $hash) = $this->getPhabricatorToInformation(); - if (!$to) { + $hash, + $user_phids) = $this->getPhabricatorToInformation(); + if (!$to && !$user_phids) { $raw_to = idx($this->headers, 'to'); return $this->setMessage("Unrecognized 'to' format: {$raw_to}")->save(); } @@ -186,7 +210,7 @@ final class PhabricatorMetaMTAReceivedMail extends PhabricatorMetaMTADAO { if ($create_task && $to == $create_task) { $receiver = new ManiphestTask(); - $user = $this->lookupPublicUser(); + $user = $this->lookupSender(); if ($user) { $this->setAuthorPHID($user->getPHID()); } else { @@ -230,12 +254,32 @@ final class PhabricatorMetaMTAReceivedMail extends PhabricatorMetaMTADAO { return $this->save(); } + // means we're creating a conpherence...! + if ($user_phids) { + // we must have a valid user who created this conpherence + $user = $this->lookupSender(); + if (!$user) { + return $this->setMessage("Invalid public user '{$from}'.")->save(); + } + + $conpherence = id(new ConpherenceReplyHandler()) + ->setMailReceiver(new ConpherenceThread()) + ->setMailAddedParticipantPHIDs($user_phids) + ->setActor($user) + ->setExcludeMailRecipientPHIDs($this->loadExcludeMailRecipientPHIDs()) + ->processEmail($this); + + $this->setRelatedPHID($conpherence->getPHID()); + $this->setMessage('OK'); + return $this->save(); + } + if ($user_id == 'public') { if (!PhabricatorEnv::getEnvConfig('metamta.public-replies')) { return $this->setMessage("Public replies not enabled.")->save(); } - $user = $this->lookupPublicUser(); + $user = $this->lookupSender(); if (!$user) { return $this->setMessage("Invalid public user '{$from}'.")->save(); @@ -373,7 +417,7 @@ final class PhabricatorMetaMTAReceivedMail extends PhabricatorMetaMTADAO { return array_filter($raw_addresses); } - private function lookupPublicUser() { + private function lookupSender() { $from = idx($this->headers, 'from'); $from = $this->getRawEmailAddress($from);