Page MenuHomePhabricator

D8117.diff
No OneTemporary

D8117.diff

Index: src/__phutil_library_map__.php
===================================================================
--- src/__phutil_library_map__.php
+++ src/__phutil_library_map__.php
@@ -1648,6 +1648,7 @@
'PhabricatorMetaMTAMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAMailTestCase.php',
'PhabricatorMetaMTAMailgunReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAMailgunReceiveController.php',
'PhabricatorMetaMTAMailingList' => 'applications/mailinglists/storage/PhabricatorMetaMTAMailingList.php',
+ 'PhabricatorMetaMTAMemberQuery' => 'applications/metamta/query/PhabricatorMetaMTAMemberQuery.php',
'PhabricatorMetaMTAPermanentFailureException' => 'applications/metamta/exception/PhabricatorMetaMTAPermanentFailureException.php',
'PhabricatorMetaMTAReceivedMail' => 'applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php',
'PhabricatorMetaMTAReceivedMailProcessingException' => 'applications/metamta/exception/PhabricatorMetaMTAReceivedMailProcessingException.php',
@@ -4325,6 +4326,7 @@
0 => 'PhabricatorMetaMTADAO',
1 => 'PhabricatorPolicyInterface',
),
+ 'PhabricatorMetaMTAMemberQuery' => 'PhabricatorQuery',
'PhabricatorMetaMTAPermanentFailureException' => 'Exception',
'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTAReceivedMailProcessingException' => 'Exception',
Index: src/applications/metamta/query/PhabricatorMetaMTAMemberQuery.php
===================================================================
--- /dev/null
+++ src/applications/metamta/query/PhabricatorMetaMTAMemberQuery.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * Expands aggregate mail recipients into their component mailables. For
+ * example, a project currently expands into all of its members.
+ */
+final class PhabricatorMetaMTAMemberQuery extends PhabricatorQuery {
+
+ private $phids = array();
+ private $viewer;
+
+ public function setViewer(PhabricatorUser $viewer) {
+ $this->viewer = $viewer;
+ return $this;
+ }
+
+ public function getViewer() {
+ return $this->viewer;
+ }
+
+ public function withPHIDs(array $phids) {
+ $this->phids = $phids;
+ return $this;
+ }
+
+ public function execute() {
+ $phids = array_fuse($this->phids);
+ $actors = array();
+ $type_map = array();
+ foreach ($phids as $phid) {
+ $type_map[phid_get_type($phid)][] = $phid;
+ }
+
+ // TODO: Generalize this somewhere else.
+
+ $results = array();
+ foreach ($type_map as $type => $phids) {
+ switch ($type) {
+ case PhabricatorProjectPHIDTypeProject::TYPECONST:
+ // TODO: For now, project members are always on the "mailing list"
+ // implied by the project, but we should differentiate members and
+ // subscribers (i.e., allow you to unsubscribe from mail about
+ // a project).
+
+ $projects = id(new PhabricatorProjectQuery())
+ ->setViewer($this->getViewer())
+ ->needMembers(true)
+ ->withPHIDs($phids)
+ ->execute();
+
+ $projects = mpull($projects, null, 'getPHID');
+ foreach ($phids as $phid) {
+ $project = idx($projects, $phid);
+ if (!$project) {
+ $results[$phid] = array();
+ } else {
+ $results[$phid] = $project->getMemberPHIDs();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ return $results;
+ }
+
+}
Index: src/applications/metamta/replyhandler/PhabricatorMailReplyHandler.php
===================================================================
--- src/applications/metamta/replyhandler/PhabricatorMailReplyHandler.php
+++ src/applications/metamta/replyhandler/PhabricatorMailReplyHandler.php
@@ -198,6 +198,15 @@
}
}
+ // TODO: This is pretty messy. We should really be doing all of this
+ // multiplexing in the task queue, but that requires significant rewriting
+ // in the general case. ApplicationTransactions can do it fairly easily,
+ // but other mail sites currently can not, so we need to support this
+ // junky version until they catch up and we can swap things over.
+
+ $to_handles = $this->expandRecipientHandles($to_handles);
+ $cc_handles = $this->expandRecipientHandles($cc_handles);
+
$tos = mpull($to_handles, null, 'getPHID');
$ccs = mpull($cc_handles, null, 'getPHID');
@@ -219,6 +228,8 @@
$body .= $this->getRecipientsSummary($to_handles, $cc_handles);
foreach ($recipients as $phid => $recipient) {
+
+
$mail = clone $mail_template;
if (isset($to_handles[$phid])) {
$mail->addTos(array($phid));
@@ -332,4 +343,32 @@
return rtrim($body);
}
+ private function expandRecipientHandles(array $handles) {
+ if (!$handles) {
+ return array();
+ }
+
+ $phids = mpull($handles, 'getPHID');
+ $map = id(new PhabricatorMetaMTAMemberQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withPHIDs($phids)
+ ->execute();
+
+ $results = array();
+ foreach ($phids as $phid) {
+ if (isset($map[$phid])) {
+ foreach ($map[$phid] as $expanded_phid) {
+ $results[$expanded_phid] = $expanded_phid;
+ }
+ } else {
+ $results[$phid] = $phid;
+ }
+ }
+
+ return id(new PhabricatorHandleQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withPHIDs($results)
+ ->execute();
+ }
+
}
Index: src/applications/metamta/storage/PhabricatorMetaMTAMail.php
===================================================================
--- src/applications/metamta/storage/PhabricatorMetaMTAMail.php
+++ src/applications/metamta/storage/PhabricatorMetaMTAMail.php
@@ -19,6 +19,7 @@
private $excludePHIDs = array();
private $overrideNoSelfMail = false;
+ private $recipientExpansionMap;
public function __construct() {
@@ -379,7 +380,8 @@
$mailer->addReplyTo($value, $reply_to_name);
break;
case 'to':
- $to_actors = array_select_keys($deliverable_actors, $value);
+ $to_phids = $this->expandRecipients($value);
+ $to_actors = array_select_keys($deliverable_actors, $to_phids);
$add_to = array_merge(
$add_to,
mpull($to_actors, 'getEmailAddress'));
@@ -388,7 +390,8 @@
$add_to = array_merge($add_to, $value);
break;
case 'cc':
- $cc_actors = array_select_keys($deliverable_actors, $value);
+ $cc_phids = $this->expandRecipients($value);
+ $cc_actors = array_select_keys($deliverable_actors, $cc_phids);
$add_cc = array_merge(
$add_cc,
mpull($cc_actors, 'getEmailAddress'));
@@ -685,9 +688,54 @@
$this->getToPHIDs(),
$this->getCcPHIDs());
+ $this->loadRecipientExpansions($actor_phids);
+ $actor_phids = $this->expandRecipients($actor_phids);
+
return $this->loadActors($actor_phids);
}
+ private function loadRecipientExpansions(array $phids) {
+ $expansions = id(new PhabricatorMetaMTAMemberQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withPHIDs($phids)
+ ->execute();
+
+ $this->recipientExpansionMap = $expansions;
+
+ return $this;
+ }
+
+ /**
+ * Expand a list of recipient PHIDs (possibly including aggregate recipients
+ * like projects) into a deaggregated list of individual recipient PHIDs.
+ * For example, this will expand project PHIDs into a list of the project's
+ * members.
+ *
+ * @param list<phid> List of recipient PHIDs, possibly including aggregate
+ * recipients.
+ * @return list<phid> Deaggregated list of mailable recipients.
+ */
+ private function expandRecipients(array $phids) {
+ if ($this->recipientExpansionMap === null) {
+ throw new Exception(
+ pht(
+ 'Call loadRecipientExpansions() before expandRecipients()!'));
+ }
+
+ $results = array();
+ foreach ($phids as $phid) {
+ if (!isset($this->recipientExpansionMap[$phid])) {
+ $results[$phid] = $phid;
+ } else {
+ foreach ($this->recipientExpansionMap[$phid] as $recipient_phid) {
+ $results[$recipient_phid] = $recipient_phid;
+ }
+ }
+ }
+
+ return array_keys($results);
+ }
+
private function filterDeliverableActors(array $actors) {
assert_instances_of($actors, 'PhabricatorMetaMTAActor');
$deliverable_actors = array();

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 5, 7:38 AM (1 w, 4 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7706768
Default Alt Text
D8117.diff (8 KB)

Event Timeline