mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 06:42:42 +01:00
Introduce basic bin/mail
with a resend
workflow
Summary: Fixes T2458. Ref T2843. @tido's email from T2843 has exhausted its retries and failed, but we want to try it again with the patch from D5464 to capture the actual error. This sort of thing has come up a few times in debugging, too. Also fixed some stuff that came up while debugging this. Test Plan: - Ran command with no args. - Ran resend with no args. - Ran resend with bad IDs. - Ran resend with already-queued messages, got "already queued" error. - Ran resend with already-sent message, got requeue. Reviewers: btrahan, tido Reviewed By: tido CC: aran Maniphest Tasks: T2458, T2843 Differential Revision: https://secure.phabricator.com/D5493
This commit is contained in:
parent
9ca2bb991c
commit
e80c59cbc6
8 changed files with 140 additions and 34 deletions
1
bin/mail
Symbolic link
1
bin/mail
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../scripts/mail/manage_mail.php
|
|
@ -1,29 +0,0 @@
|
||||||
#!/usr/bin/env php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* After upgrading to/past D1723, the handling of messages queued for delivery
|
|
||||||
* is a bit different. Running this script will take any messages that are
|
|
||||||
* queued for delivery, but don't have a worker task created, and create that
|
|
||||||
* worker task. Without the worker task, the message will just sit at "queued
|
|
||||||
* for delivery" and nothing will happen to it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
$root = dirname(dirname(dirname(__FILE__)));
|
|
||||||
require_once $root.'/scripts/__init_script__.php';
|
|
||||||
|
|
||||||
$messages = id(new PhabricatorMetaMTAMail())->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";
|
|
||||||
}
|
|
||||||
}
|
|
22
scripts/mail/manage_mail.php
Executable file
22
scripts/mail/manage_mail.php
Executable file
|
@ -0,0 +1,22 @@
|
||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$root = dirname(dirname(dirname(__FILE__)));
|
||||||
|
require_once $root.'/scripts/__init_script__.php';
|
||||||
|
|
||||||
|
$args = new PhutilArgumentParser($argv);
|
||||||
|
$args->setTagline('manage mail');
|
||||||
|
$args->setSynopsis(<<<EOSYNOPSIS
|
||||||
|
**mail** __command__ [__options__]
|
||||||
|
Manage Phabricator mail stuff.
|
||||||
|
|
||||||
|
EOSYNOPSIS
|
||||||
|
);
|
||||||
|
$args->parseStandardArguments();
|
||||||
|
|
||||||
|
$workflows = array(
|
||||||
|
new PhabricatorMailManagementResendWorkflow(),
|
||||||
|
new PhutilHelpArgumentWorkflow(),
|
||||||
|
);
|
||||||
|
|
||||||
|
$args->parseWorkflows($workflows);
|
|
@ -1048,6 +1048,8 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerLiteAdapter.php',
|
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerLiteAdapter.php',
|
||||||
'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationSendGridAdapter.php',
|
'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationSendGridAdapter.php',
|
||||||
'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationTestAdapter.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',
|
'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php',
|
||||||
'PhabricatorMailingListsController' => 'applications/mailinglists/controller/PhabricatorMailingListsController.php',
|
'PhabricatorMailingListsController' => 'applications/mailinglists/controller/PhabricatorMailingListsController.php',
|
||||||
'PhabricatorMailingListsEditController' => 'applications/mailinglists/controller/PhabricatorMailingListsEditController.php',
|
'PhabricatorMailingListsEditController' => 'applications/mailinglists/controller/PhabricatorMailingListsEditController.php',
|
||||||
|
@ -2714,6 +2716,8 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter',
|
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||||
'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter',
|
'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||||
'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter',
|
'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter',
|
||||||
|
'PhabricatorMailManagementResendWorkflow' => 'PhabricatorSearchManagementWorkflow',
|
||||||
|
'PhabricatorMailManagementWorkflow' => 'PhutilArgumentWorkflow',
|
||||||
'PhabricatorMailingListsController' => 'PhabricatorController',
|
'PhabricatorMailingListsController' => 'PhabricatorController',
|
||||||
'PhabricatorMailingListsEditController' => 'PhabricatorMailingListsController',
|
'PhabricatorMailingListsEditController' => 'PhabricatorMailingListsController',
|
||||||
'PhabricatorMailingListsListController' => 'PhabricatorMailingListsController',
|
'PhabricatorMailingListsListController' => 'PhabricatorMailingListsController',
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorMailManagementResendWorkflow
|
||||||
|
extends PhabricatorSearchManagementWorkflow {
|
||||||
|
|
||||||
|
protected function didConstruct() {
|
||||||
|
$this
|
||||||
|
->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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PhabricatorMailManagementWorkflow
|
||||||
|
extends PhutilArgumentWorkflow {
|
||||||
|
|
||||||
|
final public function isExecutable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -37,4 +37,20 @@ final class PhabricatorMetaMTAAttachment {
|
||||||
$this->mimetype = $mimetype;
|
$this->mimetype = $mimetype;
|
||||||
return $this;
|
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'));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,17 +165,23 @@ final class PhabricatorMetaMTAMail extends PhabricatorMetaMTADAO {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addAttachment(PhabricatorMetaMTAAttachment $attachment) {
|
public function addAttachment(PhabricatorMetaMTAAttachment $attachment) {
|
||||||
$this->parameters['attachments'][] = $attachment;
|
$this->parameters['attachments'][] = $attachment->toDictionary();
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAttachments() {
|
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) {
|
public function setAttachments(array $attachments) {
|
||||||
assert_instances_of($attachments, 'PhabricatorMetaMTAAttachment');
|
assert_instances_of($attachments, 'PhabricatorMetaMTAAttachment');
|
||||||
$this->setParam('attachments', $attachments);
|
$this->setParam('attachments', mpull($attachments, 'toDictionary'));
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,6 +436,7 @@ final class PhabricatorMetaMTAMail extends PhabricatorMetaMTADAO {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'attachments':
|
case 'attachments':
|
||||||
|
$value = $this->getAttachments();
|
||||||
foreach ($value as $attachment) {
|
foreach ($value as $attachment) {
|
||||||
$mailer->addAttachment(
|
$mailer->addAttachment(
|
||||||
$attachment->getData(),
|
$attachment->getData(),
|
||||||
|
@ -715,13 +722,13 @@ final class PhabricatorMetaMTAMail extends PhabricatorMetaMTADAO {
|
||||||
$is_mailable = false;
|
$is_mailable = false;
|
||||||
switch ($value) {
|
switch ($value) {
|
||||||
case PhabricatorPHIDConstants::PHID_TYPE_USER:
|
case PhabricatorPHIDConstants::PHID_TYPE_USER:
|
||||||
$user = $users[$phid];
|
$user = idx($users, $phid);
|
||||||
if ($user) {
|
if ($user) {
|
||||||
$name = $this->getUserName($user);
|
$name = $this->getUserName($user);
|
||||||
$is_mailable = !$user->getIsDisabled()
|
$is_mailable = !$user->getIsDisabled()
|
||||||
&& !$user->getIsSystemAgent();
|
&& !$user->getIsSystemAgent();
|
||||||
}
|
}
|
||||||
$email = $user_emails[$phid] ?
|
$email = isset($user_emails[$phid]) ?
|
||||||
$user_emails[$phid]->getAddress() :
|
$user_emails[$phid]->getAddress() :
|
||||||
$default;
|
$default;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue