mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-23 14:00:56 +01:00
Flesh out web UI for mail a bit to prepare for Herald outbound rules
Summary: Ref T9141. Ref T5791. Ref T7013. Major changes here is: - Currently, we don't store the headers we actually sent, or the reasons we actually did or did not deliver a mail. - Start storing these (as `headers.sent` and `actors.sent`). - Show them in the web UI. - Show them in `bin/mail show-outbound` (previously, we sort of re-computed them in a hacky way). - Take them into account in `bin/mail volume`. Then some minor changes: - Show mail bodies. - Show more mail information. - Start renaming "MetaMTA" to "Mail", at least in the web UI. Test Plan: {F707501} {F707502} {F707503} {F707504} {F707505} Reviewers: chad Reviewed By: chad Maniphest Tasks: T5791, T7013, T9141 Differential Revision: https://secure.phabricator.com/D13878
This commit is contained in:
parent
9a7beadd22
commit
8c06d89070
6 changed files with 390 additions and 120 deletions
|
@ -3,7 +3,7 @@
|
|||
final class PhabricatorMetaMTAApplication extends PhabricatorApplication {
|
||||
|
||||
public function getName() {
|
||||
return pht('MetaMTA');
|
||||
return pht('Mail');
|
||||
}
|
||||
|
||||
public function getBaseURI() {
|
||||
|
@ -15,11 +15,11 @@ final class PhabricatorMetaMTAApplication extends PhabricatorApplication {
|
|||
}
|
||||
|
||||
public function getShortDescription() {
|
||||
return pht('Delivers Mail');
|
||||
return pht('Send and Receive Mail');
|
||||
}
|
||||
|
||||
public function getFlavorText() {
|
||||
return pht('Yo dawg, we heard you like MTAs.');
|
||||
return pht('Every program attempts to expand until it can read mail.');
|
||||
}
|
||||
|
||||
public function getApplicationGroup() {
|
||||
|
@ -30,12 +30,8 @@ final class PhabricatorMetaMTAApplication extends PhabricatorApplication {
|
|||
return false;
|
||||
}
|
||||
|
||||
public function isLaunchable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getTypeaheadURI() {
|
||||
return null;
|
||||
return '/mail/';
|
||||
}
|
||||
|
||||
public function getRoutes() {
|
||||
|
|
|
@ -4,7 +4,7 @@ final class PhabricatorMetaMTAMailViewController
|
|||
extends PhabricatorMetaMTAController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getUser();
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$mail = id(new PhabricatorMetaMTAMailQuery())
|
||||
->setViewer($viewer)
|
||||
|
@ -19,17 +19,51 @@ final class PhabricatorMetaMTAMailViewController
|
|||
} else {
|
||||
$title = $mail->getSubject();
|
||||
}
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader($title)
|
||||
->setUser($this->getRequest()->getUser())
|
||||
->setUser($viewer)
|
||||
->setPolicyObject($mail);
|
||||
|
||||
switch ($mail->getStatus()) {
|
||||
case PhabricatorMetaMTAMail::STATUS_QUEUE:
|
||||
$icon = 'fa-clock-o';
|
||||
$color = 'blue';
|
||||
$name = pht('Queued');
|
||||
break;
|
||||
case PhabricatorMetaMTAMail::STATUS_SENT:
|
||||
$icon = 'fa-envelope';
|
||||
$color = 'green';
|
||||
$name = pht('Sent');
|
||||
break;
|
||||
case PhabricatorMetaMTAMail::STATUS_FAIL:
|
||||
$icon = 'fa-envelope';
|
||||
$color = 'red';
|
||||
$name = pht('Delivery Failed');
|
||||
break;
|
||||
case PhabricatorMetaMTAMail::STATUS_VOID:
|
||||
$icon = 'fa-envelope';
|
||||
$color = 'black';
|
||||
$name = pht('Voided');
|
||||
break;
|
||||
default:
|
||||
$icon = 'fa-question-circle';
|
||||
$color = 'yellow';
|
||||
$name = pht('Unknown');
|
||||
break;
|
||||
}
|
||||
|
||||
$header->setStatus($icon, $color, $name);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb(
|
||||
'Mail '.$mail->getID());
|
||||
->addTextCrumb(pht('Mail %d', $mail->getID()));
|
||||
|
||||
$object_box = id(new PHUIObjectBoxView())
|
||||
->setHeader($header)
|
||||
->addPropertyList($this->buildPropertyView($mail));
|
||||
->addPropertyList($this->buildMessageProperties($mail), pht('Message'))
|
||||
->addPropertyList($this->buildHeaderProperties($mail), pht('Headers'))
|
||||
->addPropertyList($this->buildDeliveryProperties($mail), pht('Delivery'))
|
||||
->addPropertyList($this->buildMetadataProperties($mail), pht('Metadata'));
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
array(
|
||||
|
@ -42,42 +76,13 @@ final class PhabricatorMetaMTAMailViewController
|
|||
));
|
||||
}
|
||||
|
||||
private function buildPropertyView(PhabricatorMetaMTAMail $mail) {
|
||||
private function buildMessageProperties(PhabricatorMetaMTAMail $mail) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$properties = id(new PHUIPropertyListView())
|
||||
->setUser($viewer)
|
||||
->setObject($mail);
|
||||
|
||||
$properties->addProperty(
|
||||
pht('ID'),
|
||||
$mail->getID());
|
||||
|
||||
$properties->addProperty(
|
||||
pht('Status'),
|
||||
$mail->getStatus());
|
||||
|
||||
if ($mail->getMessage()) {
|
||||
$properties->addProperty(
|
||||
pht('Status Details'),
|
||||
$mail->getMessage());
|
||||
}
|
||||
|
||||
if ($mail->getRelatedPHID()) {
|
||||
$properties->addProperty(
|
||||
pht('Related Object'),
|
||||
$viewer->renderHandle($mail->getRelatedPHID()));
|
||||
}
|
||||
|
||||
if ($mail->getActorPHID()) {
|
||||
$actor_str = $viewer->renderHandle($mail->getActorPHID());
|
||||
} else {
|
||||
$actor_str = pht('Generated by Phabricator');
|
||||
}
|
||||
$properties->addProperty(
|
||||
pht('Actor'),
|
||||
$actor_str);
|
||||
|
||||
if ($mail->getFrom()) {
|
||||
$from_str = $viewer->renderHandle($mail->getFrom());
|
||||
} else {
|
||||
|
@ -105,6 +110,167 @@ final class PhabricatorMetaMTAMailViewController
|
|||
pht('Cc'),
|
||||
$cc_list);
|
||||
|
||||
$properties->addSectionHeader(
|
||||
pht('Message'),
|
||||
PHUIPropertyListView::ICON_SUMMARY);
|
||||
|
||||
if ($mail->hasSensitiveContent()) {
|
||||
$body = phutil_tag(
|
||||
'em',
|
||||
array(),
|
||||
pht(
|
||||
'The content of this mail is sensitive and it can not be '.
|
||||
'viewed from the web UI.'));
|
||||
} else {
|
||||
$body = phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'style' => 'white-space: pre-wrap',
|
||||
),
|
||||
$mail->getBody());
|
||||
}
|
||||
|
||||
$properties->addTextContent($body);
|
||||
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
private function buildHeaderProperties(PhabricatorMetaMTAMail $mail) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$properties = id(new PHUIPropertyListView())
|
||||
->setUser($viewer)
|
||||
->setStacked(true);
|
||||
|
||||
$headers = $mail->getDeliveredHeaders();
|
||||
if ($headers === null) {
|
||||
$headers = $mail->generateHeaders();
|
||||
}
|
||||
|
||||
// Sort headers by name.
|
||||
$headers = isort($headers, 0);
|
||||
|
||||
foreach ($headers as $header) {
|
||||
list($key, $value) = $header;
|
||||
$properties->addProperty($key, $value);
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
private function buildDeliveryProperties(PhabricatorMetaMTAMail $mail) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$properties = id(new PHUIPropertyListView())
|
||||
->setUser($viewer);
|
||||
|
||||
$actors = $mail->getDeliveredActors();
|
||||
$reasons = null;
|
||||
if (!$actors) {
|
||||
// TODO: We can get rid of this special-cased message after these changes
|
||||
// have been live for a while, but provide a more tailored message for
|
||||
// now so things are a little less confusing for users.
|
||||
if ($mail->getStatus() == PhabricatorMetaMTAMail::STATUS_SENT) {
|
||||
$delivery = phutil_tag(
|
||||
'em',
|
||||
array(),
|
||||
pht(
|
||||
'This is an older message that predates recording delivery '.
|
||||
'information, so none is available.'));
|
||||
} else {
|
||||
$delivery = phutil_tag(
|
||||
'em',
|
||||
array(),
|
||||
pht(
|
||||
'This message has not been delivered yet, so delivery information '.
|
||||
'is not available.'));
|
||||
}
|
||||
} else {
|
||||
$actor = idx($actors, $viewer->getPHID());
|
||||
if (!$actor) {
|
||||
$delivery = phutil_tag(
|
||||
'em',
|
||||
array(),
|
||||
pht('This message was not delivered to you.'));
|
||||
} else {
|
||||
$deliverable = $actor['deliverable'];
|
||||
if ($deliverable) {
|
||||
$delivery = pht('Delivered');
|
||||
} else {
|
||||
$delivery = pht('Voided');
|
||||
}
|
||||
|
||||
$reasons = id(new PHUIStatusListView());
|
||||
|
||||
$reason_codes = $actor['reasons'];
|
||||
if (!$reason_codes) {
|
||||
$reason_codes = array(
|
||||
PhabricatorMetaMTAActor::REASON_NONE,
|
||||
);
|
||||
}
|
||||
|
||||
$icon_yes = 'fa-check green';
|
||||
$icon_no = 'fa-times red';
|
||||
|
||||
foreach ($reason_codes as $reason) {
|
||||
$target = phutil_tag(
|
||||
'strong',
|
||||
array(),
|
||||
PhabricatorMetaMTAActor::getReasonName($reason));
|
||||
|
||||
if (PhabricatorMetaMTAActor::isDeliveryReason($reason)) {
|
||||
$icon = $icon_yes;
|
||||
} else {
|
||||
$icon = $icon_no;
|
||||
}
|
||||
|
||||
$item = id(new PHUIStatusItemView())
|
||||
->setIcon($icon)
|
||||
->setTarget($target)
|
||||
->setNote(PhabricatorMetaMTAActor::getReasonDescription($reason));
|
||||
|
||||
$reasons->addItem($item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$properties->addProperty(pht('Delivery'), $delivery);
|
||||
if ($reasons) {
|
||||
$properties->addProperty(pht('Reasons'), $reasons);
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
private function buildMetadataProperties(PhabricatorMetaMTAMail $mail) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$properties = id(new PHUIPropertyListView())
|
||||
->setUser($viewer);
|
||||
|
||||
$details = $mail->getMessage();
|
||||
if (!strlen($details)) {
|
||||
$details = phutil_tag('em', array(), pht('None'));
|
||||
}
|
||||
$properties->addProperty(pht('Status Details'), $details);
|
||||
|
||||
$actor_phid = $mail->getActorPHID();
|
||||
if ($actor_phid) {
|
||||
$actor_str = $viewer->renderHandle($actor_phid);
|
||||
} else {
|
||||
$actor_str = pht('Generated by Phabricator');
|
||||
}
|
||||
$properties->addProperty(pht('Actor'), $actor_str);
|
||||
|
||||
$related_phid = $mail->getRelatedPHID();
|
||||
if ($related_phid) {
|
||||
$related = $viewer->renderHandle($mail->getRelatedPHID());
|
||||
} else {
|
||||
$related = phutil_tag('em', array(), pht('None'));
|
||||
}
|
||||
$properties->addProperty(pht('Related Object'), $related);
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,23 +76,20 @@ final class PhabricatorMailManagementShowOutboundWorkflow
|
|||
$info[] = pht('Related PHID: %s', $message->getRelatedPHID());
|
||||
$info[] = pht('Message: %s', $message->getMessage());
|
||||
|
||||
$ignore = array(
|
||||
'body' => true,
|
||||
'html-body' => true,
|
||||
'headers' => true,
|
||||
'attachments' => true,
|
||||
'headers.sent' => true,
|
||||
'authors.sent' => true,
|
||||
);
|
||||
|
||||
$info[] = null;
|
||||
$info[] = pht('PARAMETERS');
|
||||
$parameters = $message->getParameters();
|
||||
foreach ($parameters as $key => $value) {
|
||||
if ($key == 'body') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($key == 'html-body') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($key == 'headers') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($key == 'attachments') {
|
||||
if (isset($ignore[$key])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -105,7 +102,13 @@ final class PhabricatorMailManagementShowOutboundWorkflow
|
|||
|
||||
$info[] = null;
|
||||
$info[] = pht('HEADERS');
|
||||
foreach (idx($parameters, 'headers', array()) as $header) {
|
||||
|
||||
$headers = $message->getDeliveredHeaders();
|
||||
if (!$headers) {
|
||||
$headers = $message->generateHeaders();
|
||||
}
|
||||
|
||||
foreach ($headers as $header) {
|
||||
list($name, $value) = $header;
|
||||
$info[] = "{$name}: {$value}";
|
||||
}
|
||||
|
@ -119,21 +122,33 @@ final class PhabricatorMailManagementShowOutboundWorkflow
|
|||
}
|
||||
}
|
||||
|
||||
$actors = $message->loadAllActors();
|
||||
$actors = array_select_keys(
|
||||
$actors,
|
||||
array_merge($message->getToPHIDs(), $message->getCcPHIDs()));
|
||||
$info[] = null;
|
||||
$info[] = pht('RECIPIENTS');
|
||||
foreach ($actors as $actor) {
|
||||
if ($actor->isDeliverable()) {
|
||||
$info[] = ' '.coalesce($actor->getName(), $actor->getPHID());
|
||||
} else {
|
||||
$info[] = '! '.coalesce($actor->getName(), $actor->getPHID());
|
||||
}
|
||||
foreach ($actor->getDeliverabilityReasons() as $reason) {
|
||||
$desc = PhabricatorMetaMTAActor::getReasonDescription($reason);
|
||||
$info[] = ' - '.$desc;
|
||||
$all_actors = $message->loadAllActors();
|
||||
|
||||
$actors = $message->getDeliveredActors();
|
||||
if ($actors) {
|
||||
$info[] = null;
|
||||
$info[] = pht('RECIPIENTS');
|
||||
foreach ($actors as $actor_phid => $actor_info) {
|
||||
$actor = idx($all_actors, $actor_phid);
|
||||
if ($actor) {
|
||||
$actor_name = coalesce($actor->getName(), $actor_phid);
|
||||
} else {
|
||||
$actor_name = $actor_phid;
|
||||
}
|
||||
|
||||
$deliverable = $actor_info['deliverable'];
|
||||
if ($deliverable) {
|
||||
$info[] = ' '.$actor_name;
|
||||
} else {
|
||||
$info[] = '! '.$actor_name;
|
||||
}
|
||||
|
||||
$reasons = $actor_info['reasons'];
|
||||
foreach ($reasons as $reason) {
|
||||
$name = PhabricatorMetaMTAActor::getReasonName($reason);
|
||||
$desc = PhabricatorMetaMTAActor::getReasonDescription($reason);
|
||||
$info[] = ' - '.$name.': '.$desc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,8 +28,11 @@ final class PhabricatorMailManagementVolumeWorkflow
|
|||
->execute();
|
||||
|
||||
$unfiltered = array();
|
||||
$delivered = array();
|
||||
|
||||
foreach ($mails as $mail) {
|
||||
// Count messages we attempted to deliver. This includes messages which
|
||||
// were voided by preferences or other rules.
|
||||
$unfiltered_actors = mpull($mail->loadAllActors(), 'getPHID');
|
||||
foreach ($unfiltered_actors as $phid) {
|
||||
if (empty($unfiltered[$phid])) {
|
||||
|
@ -37,9 +40,26 @@ final class PhabricatorMailManagementVolumeWorkflow
|
|||
}
|
||||
$unfiltered[$phid]++;
|
||||
}
|
||||
|
||||
// Now, count mail we actually delivered.
|
||||
$result = $mail->getDeliveredActors();
|
||||
if ($result) {
|
||||
foreach ($result as $actor_phid => $actor_info) {
|
||||
if (!$actor_info['deliverable']) {
|
||||
continue;
|
||||
}
|
||||
if (empty($delivered[$actor_phid])) {
|
||||
$delivered[$actor_phid] = 0;
|
||||
}
|
||||
$delivered[$actor_phid]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort users by delivered mail, then unfiltered mail.
|
||||
arsort($delivered);
|
||||
arsort($unfiltered);
|
||||
$delivered = $delivered + array_fill_keys(array_keys($unfiltered), 0);
|
||||
|
||||
$table = id(new PhutilConsoleTable())
|
||||
->setBorders(true)
|
||||
|
@ -52,16 +72,23 @@ final class PhabricatorMailManagementVolumeWorkflow
|
|||
'unfiltered',
|
||||
array(
|
||||
'title' => pht('Unfiltered'),
|
||||
))
|
||||
->addColumn(
|
||||
'delivered',
|
||||
array(
|
||||
'title' => pht('Delivered'),
|
||||
));
|
||||
|
||||
$handles = $viewer->loadHandles(array_keys($unfiltered));
|
||||
$names = mpull(iterator_to_array($handles), 'getName', 'getPHID');
|
||||
|
||||
foreach ($unfiltered as $phid => $count) {
|
||||
foreach ($delivered as $phid => $delivered_count) {
|
||||
$unfiltered_count = idx($unfiltered, $phid, 0);
|
||||
$table->addRow(
|
||||
array(
|
||||
'user' => idx($names, $phid),
|
||||
'unfiltered' => $count,
|
||||
'unfiltered' => $unfiltered_count,
|
||||
'delivered' => $delivered_count,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -70,7 +97,9 @@ final class PhabricatorMailManagementVolumeWorkflow
|
|||
echo "\n";
|
||||
echo pht('Mail sent in the last 30 days.')."\n";
|
||||
echo pht(
|
||||
'"Unfiltered" is raw volume before preferences were applied.')."\n";
|
||||
'"Unfiltered" is raw volume before rules applied.')."\n";
|
||||
echo pht(
|
||||
'"Delivered" shows email actually sent.')."\n";
|
||||
echo "\n";
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -5,6 +5,7 @@ final class PhabricatorMetaMTAActor extends Phobject {
|
|||
const STATUS_DELIVERABLE = 'deliverable';
|
||||
const STATUS_UNDELIVERABLE = 'undeliverable';
|
||||
|
||||
const REASON_NONE = 'none';
|
||||
const REASON_UNLOADABLE = 'unloadable';
|
||||
const REASON_UNMAILABLE = 'unmailable';
|
||||
const REASON_NO_ADDRESS = 'noaddress';
|
||||
|
@ -71,8 +72,42 @@ final class PhabricatorMetaMTAActor extends Phobject {
|
|||
return $this->reasons;
|
||||
}
|
||||
|
||||
public static function isDeliveryReason($reason) {
|
||||
switch ($reason) {
|
||||
case self::REASON_NONE:
|
||||
case self::REASON_FORCE:
|
||||
case self::REASON_FORCE_HERALD:
|
||||
return true;
|
||||
default:
|
||||
// All other reasons cause the message to not be delivered.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getReasonName($reason) {
|
||||
$names = array(
|
||||
self::REASON_NONE => pht('None'),
|
||||
self::REASON_DISABLED => pht('Disabled Recipient'),
|
||||
self::REASON_BOT => pht('Bot Recipient'),
|
||||
self::REASON_NO_ADDRESS => pht('No Address'),
|
||||
self::REASON_EXTERNAL_TYPE => pht('External Recipient'),
|
||||
self::REASON_UNMAILABLE => pht('Not Mailable'),
|
||||
self::REASON_RESPONSE => pht('Similar Reply'),
|
||||
self::REASON_SELF => pht('Self Mail'),
|
||||
self::REASON_MAIL_DISABLED => pht('Mail Disabled'),
|
||||
self::REASON_MAILTAGS => pht('Mail Tags'),
|
||||
self::REASON_UNLOADABLE => pht('Bad Recipient'),
|
||||
self::REASON_FORCE => pht('Forced Mail'),
|
||||
self::REASON_FORCE_HERALD => pht('Forced by Herald'),
|
||||
);
|
||||
|
||||
return idx($names, $reason, pht('Unknown ("%s")', $reason));
|
||||
}
|
||||
|
||||
public static function getReasonDescription($reason) {
|
||||
$descriptions = array(
|
||||
self::REASON_NONE => pht(
|
||||
'No special rules affected this mail.'),
|
||||
self::REASON_DISABLED => pht(
|
||||
'This user is disabled; disabled users do not receive mail.'),
|
||||
self::REASON_BOT => pht(
|
||||
|
|
|
@ -436,6 +436,8 @@ final class PhabricatorMetaMTAMail
|
|||
}
|
||||
|
||||
try {
|
||||
$headers = $this->generateHeaders();
|
||||
|
||||
$params = $this->parameters;
|
||||
|
||||
$actors = $this->loadAllActors();
|
||||
|
@ -535,16 +537,6 @@ final class PhabricatorMetaMTAMail
|
|||
$add_cc,
|
||||
mpull($cc_actors, 'getEmailAddress'));
|
||||
break;
|
||||
case 'headers':
|
||||
foreach ($value as $pair) {
|
||||
list($header_key, $header_value) = $pair;
|
||||
|
||||
// NOTE: If we have \n in a header, SES rejects the email.
|
||||
$header_value = str_replace("\n", ' ', $header_value);
|
||||
|
||||
$mailer->addHeader($header_key, $header_value);
|
||||
}
|
||||
break;
|
||||
case 'attachments':
|
||||
$value = $this->getAttachments();
|
||||
foreach ($value as $attachment) {
|
||||
|
@ -593,11 +585,6 @@ final class PhabricatorMetaMTAMail
|
|||
|
||||
$mailer->setSubject(implode(' ', array_filter($subject)));
|
||||
break;
|
||||
case 'is-bulk':
|
||||
if ($value) {
|
||||
$mailer->addHeader('Precedence', 'bulk');
|
||||
}
|
||||
break;
|
||||
case 'thread-id':
|
||||
|
||||
// NOTE: Gmail freaks out about In-Reply-To and References which
|
||||
|
@ -608,7 +595,7 @@ final class PhabricatorMetaMTAMail
|
|||
$value = '<'.$value.'@'.$domain.'>';
|
||||
|
||||
if ($is_first && $mailer->supportsMessageIDHeader()) {
|
||||
$mailer->addHeader('Message-ID', $value);
|
||||
$headers[] = array('Message-ID', $value);
|
||||
} else {
|
||||
$in_reply_to = $value;
|
||||
$references = array($value);
|
||||
|
@ -620,21 +607,16 @@ final class PhabricatorMetaMTAMail
|
|||
$references[] = $parent_id;
|
||||
}
|
||||
$references = implode(' ', $references);
|
||||
$mailer->addHeader('In-Reply-To', $in_reply_to);
|
||||
$mailer->addHeader('References', $references);
|
||||
$headers[] = array('In-Reply-To', $in_reply_to);
|
||||
$headers[] = array('References', $references);
|
||||
}
|
||||
$thread_index = $this->generateThreadIndex($value, $is_first);
|
||||
$mailer->addHeader('Thread-Index', $thread_index);
|
||||
break;
|
||||
case 'mailtags':
|
||||
// Handled below.
|
||||
break;
|
||||
case 'subject-prefix':
|
||||
case 'vary-subject-prefix':
|
||||
// Handled above.
|
||||
$headers[] = array('Thread-Index', $thread_index);
|
||||
break;
|
||||
default:
|
||||
// Just discard.
|
||||
// Other parameters are handled elsewhere or are not relevant to
|
||||
// constructing the message.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -660,6 +642,25 @@ final class PhabricatorMetaMTAMail
|
|||
$mailer->setHTMLBody($params['html-body']);
|
||||
}
|
||||
|
||||
// Pass the headers to the mailer, then save the state so we can show
|
||||
// them in the web UI.
|
||||
foreach ($headers as $header) {
|
||||
list($header_key, $header_value) = $header;
|
||||
$mailer->addHeader($header_key, $header_value);
|
||||
}
|
||||
$this->setParam('headers.sent', $headers);
|
||||
|
||||
// Save the final deliverability outcomes and reasoning so we can
|
||||
// explain why things happened the way they did.
|
||||
$actor_list = array();
|
||||
foreach ($actors as $actor) {
|
||||
$actor_list[$actor->getPHID()] = array(
|
||||
'deliverable' => $actor->isDeliverable(),
|
||||
'reasons' => $actor->getDeliverabilityReasons(),
|
||||
);
|
||||
}
|
||||
$this->setParam('actors.sent', $actor_list);
|
||||
|
||||
if (!$add_to && !$add_cc) {
|
||||
$this->setStatus(self::STATUS_VOID);
|
||||
$this->setMessage(
|
||||
|
@ -692,24 +693,6 @@ final class PhabricatorMetaMTAMail
|
|||
return $this->save();
|
||||
}
|
||||
|
||||
$mailer->addHeader('X-Phabricator-Sent-This-Message', 'Yes');
|
||||
$mailer->addHeader('X-Mail-Transport-Agent', 'MetaMTA');
|
||||
|
||||
// Some clients respect this to suppress OOF and other auto-responses.
|
||||
$mailer->addHeader('X-Auto-Response-Suppress', 'All');
|
||||
|
||||
// If the message has mailtags, filter out any recipients who don't want
|
||||
// to receive this type of mail.
|
||||
$mailtags = $this->getParam('mailtags');
|
||||
if ($mailtags) {
|
||||
$tag_header = array();
|
||||
foreach ($mailtags as $mailtag) {
|
||||
$tag_header[] = '<'.$mailtag.'>';
|
||||
}
|
||||
$tag_header = implode(', ', $tag_header);
|
||||
$mailer->addHeader('X-Phabricator-Mail-Tags', $tag_header);
|
||||
}
|
||||
|
||||
// Some mailers require a valid "To:" in order to deliver mail. If we
|
||||
// don't have any "To:", try to fill it in with a placeholder "To:".
|
||||
// If that also fails, move the "Cc:" line to "To:".
|
||||
|
@ -1052,6 +1035,52 @@ final class PhabricatorMetaMTAMail
|
|||
return $ret;
|
||||
}
|
||||
|
||||
public function generateHeaders() {
|
||||
$headers = array();
|
||||
|
||||
$headers[] = array('X-Phabricator-Sent-This-Message', 'Yes');
|
||||
$headers[] = array('X-Mail-Transport-Agent', 'MetaMTA');
|
||||
|
||||
// Some clients respect this to suppress OOF and other auto-responses.
|
||||
$headers[] = array('X-Auto-Response-Suppress', 'All');
|
||||
|
||||
// If the message has mailtags, filter out any recipients who don't want
|
||||
// to receive this type of mail.
|
||||
$mailtags = $this->getParam('mailtags');
|
||||
if ($mailtags) {
|
||||
$tag_header = array();
|
||||
foreach ($mailtags as $mailtag) {
|
||||
$tag_header[] = '<'.$mailtag.'>';
|
||||
}
|
||||
$tag_header = implode(', ', $tag_header);
|
||||
$headers[] = array('X-Phabricator-Mail-Tags', $tag_header);
|
||||
}
|
||||
|
||||
$value = $this->getParam('headers', array());
|
||||
foreach ($value as $pair) {
|
||||
list($header_key, $header_value) = $pair;
|
||||
|
||||
// NOTE: If we have \n in a header, SES rejects the email.
|
||||
$header_value = str_replace("\n", ' ', $header_value);
|
||||
$headers[] = array($header_key, $header_value);
|
||||
}
|
||||
|
||||
$is_bulk = $this->getParam('is-bulk');
|
||||
if ($is_bulk) {
|
||||
$headers[] = array('Precedence', 'bulk');
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
public function getDeliveredHeaders() {
|
||||
return $this->getParam('headers.sent');
|
||||
}
|
||||
|
||||
public function getDeliveredActors() {
|
||||
return $this->getParam('actors.sent');
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
|
Loading…
Reference in a new issue