diff --git a/bin/mail b/bin/mail new file mode 120000 index 0000000000..d75b7b811d --- /dev/null +++ b/bin/mail @@ -0,0 +1 @@ +../scripts/mail/manage_mail.php \ No newline at end of file diff --git a/scripts/mail/create_worker_tasks.php b/scripts/mail/create_worker_tasks.php deleted file mode 100755 index 1e0c0a3b99..0000000000 --- a/scripts/mail/create_worker_tasks.php +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env php -loadAllWhere( - 'status = %s', PhabricatorMetaMTAMail::STATUS_QUEUE); - -foreach ($messages as $message) { - if (!$message->getWorkerTaskID()) { - $mailer_task = PhabricatorWorker::scheduleTask( - 'PhabricatorMetaMTAWorker', - $message->getID()); - - $message->setWorkerTaskID($mailer_task->getID()); - $message->save(); - $id = $message->getID(); - echo "#$id\n"; - } -} diff --git a/scripts/mail/manage_mail.php b/scripts/mail/manage_mail.php new file mode 100755 index 0000000000..253629655d --- /dev/null +++ b/scripts/mail/manage_mail.php @@ -0,0 +1,22 @@ +#!/usr/bin/env php +setTagline('manage mail'); +$args->setSynopsis(<<parseStandardArguments(); + +$workflows = array( + new PhabricatorMailManagementResendWorkflow(), + new PhutilHelpArgumentWorkflow(), +); + +$args->parseWorkflows($workflows); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index afaf6a9cb9..cba5036a38 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1048,6 +1048,8 @@ phutil_register_library_map(array( 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerLiteAdapter.php', 'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationSendGridAdapter.php', 'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationTestAdapter.php', + 'PhabricatorMailManagementResendWorkflow' => 'applications/metamta/management/PhabricatorMailManagementResendWorkflow.php', + 'PhabricatorMailManagementWorkflow' => 'applications/metamta/management/PhabricatorMailManagementWorkflow.php', 'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php', 'PhabricatorMailingListsController' => 'applications/mailinglists/controller/PhabricatorMailingListsController.php', 'PhabricatorMailingListsEditController' => 'applications/mailinglists/controller/PhabricatorMailingListsEditController.php', @@ -2714,6 +2716,8 @@ phutil_register_library_map(array( 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter', + 'PhabricatorMailManagementResendWorkflow' => 'PhabricatorSearchManagementWorkflow', + 'PhabricatorMailManagementWorkflow' => 'PhutilArgumentWorkflow', 'PhabricatorMailingListsController' => 'PhabricatorController', 'PhabricatorMailingListsEditController' => 'PhabricatorMailingListsController', 'PhabricatorMailingListsListController' => 'PhabricatorMailingListsController', diff --git a/src/applications/metamta/management/PhabricatorMailManagementResendWorkflow.php b/src/applications/metamta/management/PhabricatorMailManagementResendWorkflow.php new file mode 100644 index 0000000000..ff9e0559a5 --- /dev/null +++ b/src/applications/metamta/management/PhabricatorMailManagementResendWorkflow.php @@ -0,0 +1,75 @@ +setName('resend') + ->setSynopsis('Send mail again.') + ->setExamples( + "**resend** --id 1 --id 2") + ->setArguments( + array( + array( + 'name' => 'id', + 'param' => 'id', + 'help' => 'Send mail with a given ID again.', + 'repeat' => true, + ), + )); + } + + public function execute(PhutilArgumentParser $args) { + $console = PhutilConsole::getConsole(); + + $ids = $args->getArg('id'); + if (!$ids) { + throw new PhutilArgumentUsageException( + "Use the '--id' flag to specify one or more messages to resend."); + } + + $messages = id(new PhabricatorMetaMTAMail())->loadAllWhere( + 'id IN (%Ld)', + $ids); + + if ($ids) { + $ids = array_fuse($ids); + $missing = array_diff_key($ids, $messages); + if ($missing) { + throw new PhutilArgumentUsageException( + "Some specified messages do not exist: ". + implode(', ', array_keys($missing))); + } + } + + foreach ($messages as $message) { + if ($message->getStatus() == PhabricatorMetaMTAMail::STATUS_QUEUE) { + if ($message->getWorkerTaskID()) { + $console->writeOut( + "Message #%d is already queued with an assigned send task.\n", + $message->getID()); + continue; + } + } + + $message->setStatus(PhabricatorMetaMTAMail::STATUS_QUEUE); + $message->setRetryCount(0); + $message->setNextRetry(time()); + + $message->save(); + + $mailer_task = PhabricatorWorker::scheduleTask( + 'PhabricatorMetaMTAWorker', + $message->getID()); + + $message->setWorkerTaskID($mailer_task->getID()); + $message->save(); + + $console->writeOut( + "Queued message #%d for resend.\n", + $message->getID()); + } + } + +} diff --git a/src/applications/metamta/management/PhabricatorMailManagementWorkflow.php b/src/applications/metamta/management/PhabricatorMailManagementWorkflow.php new file mode 100644 index 0000000000..ddd4811ae7 --- /dev/null +++ b/src/applications/metamta/management/PhabricatorMailManagementWorkflow.php @@ -0,0 +1,10 @@ +mimetype = $mimetype; return $this; } + + public function toDictionary() { + return array( + 'filename' => $this->getFilename(), + 'mimetype' => $this->getMimetype(), + 'data' => $this->getData(), + ); + } + + public static function newFromDictionary(array $dict) { + return new PhabricatorMetaMTAAttachment( + idx($dict, 'data'), + idx($dict, 'filename'), + idx($dict, 'mimetype')); + } + } diff --git a/src/applications/metamta/storage/PhabricatorMetaMTAMail.php b/src/applications/metamta/storage/PhabricatorMetaMTAMail.php index 7289a4132e..d70b6bedb0 100644 --- a/src/applications/metamta/storage/PhabricatorMetaMTAMail.php +++ b/src/applications/metamta/storage/PhabricatorMetaMTAMail.php @@ -165,17 +165,23 @@ final class PhabricatorMetaMTAMail extends PhabricatorMetaMTADAO { } public function addAttachment(PhabricatorMetaMTAAttachment $attachment) { - $this->parameters['attachments'][] = $attachment; + $this->parameters['attachments'][] = $attachment->toDictionary(); return $this; } public function getAttachments() { - return $this->getParam('attachments'); + $dicts = $this->getParam('attachments'); + + $result = array(); + foreach ($dicts as $dict) { + $result[] = PhabricatorMetaMTAAttachment::newFromDictionary($dict); + } + return $result; } public function setAttachments(array $attachments) { assert_instances_of($attachments, 'PhabricatorMetaMTAAttachment'); - $this->setParam('attachments', $attachments); + $this->setParam('attachments', mpull($attachments, 'toDictionary')); return $this; } @@ -430,6 +436,7 @@ final class PhabricatorMetaMTAMail extends PhabricatorMetaMTADAO { } break; case 'attachments': + $value = $this->getAttachments(); foreach ($value as $attachment) { $mailer->addAttachment( $attachment->getData(), @@ -715,13 +722,13 @@ final class PhabricatorMetaMTAMail extends PhabricatorMetaMTADAO { $is_mailable = false; switch ($value) { case PhabricatorPHIDConstants::PHID_TYPE_USER: - $user = $users[$phid]; + $user = idx($users, $phid); if ($user) { $name = $this->getUserName($user); $is_mailable = !$user->getIsDisabled() && !$user->getIsSystemAgent(); } - $email = $user_emails[$phid] ? + $email = isset($user_emails[$phid]) ? $user_emails[$phid]->getAddress() : $default; break;