diff --git a/scripts/mail/manage_mail.php b/scripts/mail/manage_mail.php index b80bc00b15..4b87a38fca 100755 --- a/scripts/mail/manage_mail.php +++ b/scripts/mail/manage_mail.php @@ -19,6 +19,7 @@ $workflows = array( new PhutilHelpArgumentWorkflow(), new PhabricatorMailManagementShowOutboundWorkflow(), new PhabricatorMailManagementShowInboundWorkflow(), + new PhabricatorMailManagementReceiveTestWorkflow(), ); $args->parseWorkflows($workflows); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index d1307936c3..b54d5ef98d 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1211,6 +1211,7 @@ phutil_register_library_map(array( 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerLiteAdapter.php', 'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationSendGridAdapter.php', 'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationTestAdapter.php', + 'PhabricatorMailManagementReceiveTestWorkflow' => 'applications/metamta/management/PhabricatorMailManagementReceiveTestWorkflow.php', 'PhabricatorMailManagementResendWorkflow' => 'applications/metamta/management/PhabricatorMailManagementResendWorkflow.php', 'PhabricatorMailManagementShowInboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementShowInboundWorkflow.php', 'PhabricatorMailManagementShowOutboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementShowOutboundWorkflow.php', @@ -1244,7 +1245,6 @@ phutil_register_library_map(array( 'PhabricatorMetaMTAMailBodyTestCase' => 'applications/metamta/view/__tests__/PhabricatorMetaMTAMailBodyTestCase.php', 'PhabricatorMetaMTAMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAMailTestCase.php', 'PhabricatorMetaMTAMailingList' => 'applications/mailinglists/storage/PhabricatorMetaMTAMailingList.php', - 'PhabricatorMetaMTAReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAReceiveController.php', 'PhabricatorMetaMTAReceivedListController' => 'applications/metamta/controller/PhabricatorMetaMTAReceivedListController.php', 'PhabricatorMetaMTAReceivedMail' => 'applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php', 'PhabricatorMetaMTAReceivedMailProcessingException' => 'applications/metamta/exception/PhabricatorMetaMTAReceivedMailProcessingException.php', @@ -3166,6 +3166,7 @@ phutil_register_library_map(array( 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter', + 'PhabricatorMailManagementReceiveTestWorkflow' => 'PhabricatorSearchManagementWorkflow', 'PhabricatorMailManagementResendWorkflow' => 'PhabricatorSearchManagementWorkflow', 'PhabricatorMailManagementShowInboundWorkflow' => 'PhabricatorSearchManagementWorkflow', 'PhabricatorMailManagementShowOutboundWorkflow' => 'PhabricatorSearchManagementWorkflow', @@ -3191,7 +3192,6 @@ phutil_register_library_map(array( 'PhabricatorMetaMTAMailBodyTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAMailTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAMailingList' => 'PhabricatorMetaMTADAO', - 'PhabricatorMetaMTAReceiveController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAReceivedListController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO', 'PhabricatorMetaMTAReceivedMailProcessingException' => 'Exception', diff --git a/src/applications/metamta/application/PhabricatorApplicationMetaMTA.php b/src/applications/metamta/application/PhabricatorApplicationMetaMTA.php index 0ac2afd146..17beb4f606 100644 --- a/src/applications/metamta/application/PhabricatorApplicationMetaMTA.php +++ b/src/applications/metamta/application/PhabricatorApplicationMetaMTA.php @@ -32,7 +32,6 @@ final class PhabricatorApplicationMetaMTA extends PhabricatorApplication { '' => 'PhabricatorMetaMTAListController', 'send/' => 'PhabricatorMetaMTASendController', 'view/(?P[1-9]\d*)/' => 'PhabricatorMetaMTAViewController', - 'receive/' => 'PhabricatorMetaMTAReceiveController', 'received/' => 'PhabricatorMetaMTAReceivedListController', 'sendgrid/' => 'PhabricatorMetaMTASendGridReceiveController', ), diff --git a/src/applications/metamta/controller/PhabricatorMetaMTAController.php b/src/applications/metamta/controller/PhabricatorMetaMTAController.php index 48acdf86ce..18b84f75a8 100644 --- a/src/applications/metamta/controller/PhabricatorMetaMTAController.php +++ b/src/applications/metamta/controller/PhabricatorMetaMTAController.php @@ -17,7 +17,6 @@ abstract class PhabricatorMetaMTAController extends PhabricatorController { if ($this->getRequest()->getUser()->getIsAdmin()) { $nav->addLabel(pht('Diagnostics')); $nav->addFilter('send', pht('Send Test')); - $nav->addFilter('receive', pht('Receive Test')); } return $nav; diff --git a/src/applications/metamta/controller/PhabricatorMetaMTAReceiveController.php b/src/applications/metamta/controller/PhabricatorMetaMTAReceiveController.php deleted file mode 100644 index 91c12c2617..0000000000 --- a/src/applications/metamta/controller/PhabricatorMetaMTAReceiveController.php +++ /dev/null @@ -1,142 +0,0 @@ -getRequest(); - $user = $request->getUser(); - - if ($request->isFormPost()) { - $received = new PhabricatorMetaMTAReceivedMail(); - $header_content = array( - 'Message-ID' => Filesystem::readRandomCharacters(12), - ); - $from = $request->getStr('sender'); - $to = $request->getStr('receiver'); - $uri = '/mail/received/'; - - if (!empty($from)) { - $header_content['from'] = $from; - } else { - // If the user doesn't provide a "From" address, use their primary - // address. - $header_content['from'] = $user->loadPrimaryEmail()->getAddress(); - } - - if (preg_match('/.+@.+/', $to)) { - $header_content['to'] = $to; - } else { - - // We allow the user to use an object name instead of a real address - // as a convenience. To build the mail, we build a similar message and - // look for a receiver which will accept it. - $pseudohash = PhabricatorObjectMailReceiver::computeMailHash('x', 'y'); - $pseudomail = id(new PhabricatorMetaMTAReceivedMail()) - ->setHeaders( - array( - 'to' => $to.'+1+'.$pseudohash, - )); - - $receivers = id(new PhutilSymbolLoader()) - ->setAncestorClass('PhabricatorMailReceiver') - ->loadObjects(); - - $receiver = null; - foreach ($receivers as $possible_receiver) { - if (!$possible_receiver->isEnabled()) { - continue; - } - if (!$possible_receiver->canAcceptMail($pseudomail)) { - continue; - } - $receiver = $possible_receiver; - break; - } - - if (!$receiver) { - throw new Exception( - "No configured mail receiver can accept mail to '{$to}'."); - } - - if (!($receiver instanceof PhabricatorObjectMailReceiver)) { - $class = get_class($receiver); - throw new Exception( - "Receiver '{$class}' accepts mail to '{$to}', but is not a ". - "subclass of PhabricatorObjectMailReceiver."); - } - - $object = $receiver->loadMailReceiverObject($to, $user); - if (!$object) { - throw new Exception("No such object '{$to}'!"); - } - - $hash = PhabricatorObjectMailReceiver::computeMailHash( - $object->getMailKey(), - $user->getPHID()); - - $header_content['to'] = $to.'+'.$user->getID().'+'.$hash.'@test.com'; - } - - $received->setHeaders($header_content); - $received->setBodies( - array( - 'text' => $request->getStr('body'), - )); - - $received->save(); - - $received->processReceivedMail(); - - return id(new AphrontRedirectResponse())->setURI($uri); - } - - $form = new AphrontFormView(); - $form->setUser($request->getUser()); - $form->setAction($this->getApplicationURI('/receive/')); - $form - ->appendChild(hsprintf( - '

%s

', - pht( - 'This form will simulate sending mail to an object '. - 'or an email address.'))) - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('From')) - ->setName('sender')) - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('To')) - ->setName('receiver') - ->setCaption(pht( - 'e.g. %s or %s', - phutil_tag('tt', array(), 'D1234'), - phutil_tag('tt', array(), 'bugs@example.com')))) - ->appendChild( - id(new AphrontFormTextAreaControl()) - ->setLabel(pht('Body')) - ->setName('body')) - ->appendChild( - id(new AphrontFormSubmitControl()) - ->setValue(pht('Receive Mail'))); - - $panel = new AphrontPanelView(); - $panel->setHeader(pht('Receive Email')); - $panel->appendChild($form); - $panel->setNoBackground(); - - $nav = $this->buildSideNavView(); - $nav->selectFilter('receive'); - $nav->appendChild($panel); - - return $this->buildApplicationPage( - $nav, - array( - 'title' => pht('Receive Test'), - 'device' => true, - )); - } - -} - diff --git a/src/applications/metamta/management/PhabricatorMailManagementReceiveTestWorkflow.php b/src/applications/metamta/management/PhabricatorMailManagementReceiveTestWorkflow.php new file mode 100644 index 0000000000..9e601b9264 --- /dev/null +++ b/src/applications/metamta/management/PhabricatorMailManagementReceiveTestWorkflow.php @@ -0,0 +1,143 @@ +setName('receive-test') + ->setSynopsis( + pht( + 'Simulate receiving mail. This is primarily useful if you are '. + 'developing new mail receivers.')) + ->setExamples( + "**receive-test** --as alincoln --to D123 < body.txt") + ->setArguments( + array( + array( + 'name' => 'as', + 'param' => 'user', + 'help' => 'Act as the specified user.', + ), + array( + 'name' => 'from', + 'param' => 'email', + 'help' => 'Simulate mail delivery "From:" the given user.', + ), + array( + 'name' => 'to', + 'param' => 'object', + 'help' => 'Simulate mail delivery "To:" the given object.', + ), + )); + } + + public function execute(PhutilArgumentParser $args) { + $console = PhutilConsole::getConsole(); + + $as = $args->getArg('as'); + if (!$as) { + throw new PhutilArgumentUsageException( + pht("Use '--as' to specify the acting user.")); + } + + $user = id(new PhabricatorPeopleQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withUsernames(array($as)) + ->executeOne(); + if (!$user) { + throw new PhutilArgumentUsageException( + pht("No such user '%s' exists.", $as)); + } + + $to = $args->getArg('to'); + if (!$to) { + throw new PhutilArgumentUsageException( + "Use '--to' to specify the receiving object or email address."); + } + + $from = $args->getArg('from'); + if (!$from) { + $from = $user->loadPrimaryEmail()->getAddress(); + } + + $console->writeErr("%s\n", pht('Reading message body from stdin...')); + $body = file_get_contents('php://stdin'); + + $received = new PhabricatorMetaMTAReceivedMail(); + $header_content = array( + 'Message-ID' => Filesystem::readRandomCharacters(12), + 'From' => $from, + ); + + if (preg_match('/.+@.+/', $to)) { + $header_content['to'] = $to; + } else { + // We allow the user to use an object name instead of a real address + // as a convenience. To build the mail, we build a similar message and + // look for a receiver which will accept it. + $pseudohash = PhabricatorObjectMailReceiver::computeMailHash('x', 'y'); + $pseudomail = id(new PhabricatorMetaMTAReceivedMail()) + ->setHeaders( + array( + 'to' => $to.'+1+'.$pseudohash, + )); + + $receivers = id(new PhutilSymbolLoader()) + ->setAncestorClass('PhabricatorMailReceiver') + ->loadObjects(); + + $receiver = null; + foreach ($receivers as $possible_receiver) { + if (!$possible_receiver->isEnabled()) { + continue; + } + if (!$possible_receiver->canAcceptMail($pseudomail)) { + continue; + } + $receiver = $possible_receiver; + break; + } + + if (!$receiver) { + throw new Exception( + pht("No configured mail receiver can accept mail to '%s'.", $to)); + } + + if (!($receiver instanceof PhabricatorObjectMailReceiver)) { + $class = get_class($receiver); + throw new Exception( + "Receiver '%s' accepts mail to '%s', but is not a ". + "subclass of PhabricatorObjectMailReceiver.", + $class, + $to); + } + + $object = $receiver->loadMailReceiverObject($to, $user); + if (!$object) { + throw new Exception(pht("No such object '%s'!", $to)); + } + + $hash = PhabricatorObjectMailReceiver::computeMailHash( + $object->getMailKey(), + $user->getPHID()); + + $header_content['to'] = $to.'+'.$user->getID().'+'.$hash.'@test.com'; + } + + $received->setHeaders($header_content); + $received->setBodies( + array( + 'text' => $body, + )); + + $received->save(); + $received->processReceivedMail(); + + $console->writeErr( + "%s\n\n phabricator/ $ ./bin/mail show-inbound --id %d\n\n", + pht("Mail received! You can view details by running this command:"), + $received->getID()); + } + +}