@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Make mail delivery reasons code-based; include positive and negative reasons

Summary:
Ref T7731. Looking forward to T5791, I eventually anticipate writing an interface which looks like a webmail UI where users can review mail they've been sent and understand why they recieved (or did not receive) the mail. Roughly like `bin/mail list-outbound` / `bin/mail show-outbound` work today, but policy-aware (so you can only see messages where delivery was attempted to you).

We currently record a list of "reasons" why a mail is undeliverable, but this list is string-based (so it can not be translated once we start persisting it) and has only negative reasons (so it can not be used to fully understand reasons for delivery or nondelivery).

Make it code-based (so it can be translated) and allow both positive and negative reasons to be listed (so positive reasons can be understood).

Test Plan: Used `bin/mail show-outbound` to review mail delivery reasons, including the positive reason we currently have (forced delivery of authentication mail).

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T7731

Differential Revision: https://secure.phabricator.com/D12297

+88 -43
+4 -3
src/applications/metamta/management/PhabricatorMailManagementShowOutboundWorkflow.php
··· 127 127 $info[] = ' '.coalesce($actor->getName(), $actor->getPHID()); 128 128 } else { 129 129 $info[] = '! '.coalesce($actor->getName(), $actor->getPHID()); 130 - foreach ($actor->getUndeliverableReasons() as $reason) { 131 - $info[] = ' - '.$reason; 132 - } 130 + } 131 + foreach ($actor->getDeliverabilityReasons() as $reason) { 132 + $desc = PhabricatorMetaMTAActor::getReasonDescription($reason); 133 + $info[] = ' - '.$desc; 133 134 } 134 135 } 135 136
+69 -2
src/applications/metamta/query/PhabricatorMetaMTAActor.php
··· 2 2 3 3 final class PhabricatorMetaMTAActor { 4 4 5 + const STATUS_DELIVERABLE = 'deliverable'; 6 + const STATUS_UNDELIVERABLE = 'undeliverable'; 7 + 8 + const REASON_UNLOADABLE = 'unloadable'; 9 + const REASON_UNMAILABLE = 'unmailable'; 10 + const REASON_NO_ADDRESS = 'noaddress'; 11 + const REASON_DISABLED = 'disabled'; 12 + const REASON_MAIL_DISABLED = 'maildisabled'; 13 + const REASON_EXTERNAL_TYPE = 'exernaltype'; 14 + const REASON_RESPONSE = 'response'; 15 + const REASON_SELF = 'self'; 16 + const REASON_MAILTAGS = 'mailtags'; 17 + const REASON_BOT = 'bot'; 18 + const REASON_FORCE = 'force'; 19 + 5 20 private $phid; 6 21 private $emailAddress; 7 22 private $name; 23 + private $status = self::STATUS_DELIVERABLE; 8 24 private $reasons = array(); 9 25 10 26 public function setName($name) { ··· 36 52 37 53 public function setUndeliverable($reason) { 38 54 $this->reasons[] = $reason; 55 + $this->status = self::STATUS_UNDELIVERABLE; 56 + return $this; 57 + } 58 + 59 + public function setDeliverable($reason) { 60 + $this->reasons[] = $reason; 61 + $this->status = self::STATUS_DELIVERABLE; 39 62 return $this; 40 63 } 41 64 42 65 public function isDeliverable() { 43 - return empty($this->reasons); 66 + return ($this->status === self::STATUS_DELIVERABLE); 44 67 } 45 68 46 - public function getUndeliverableReasons() { 69 + public function getDeliverabilityReasons() { 47 70 return $this->reasons; 48 71 } 72 + 73 + public static function getReasonDescription($reason) { 74 + $descriptions = array( 75 + self::REASON_DISABLED => pht( 76 + 'This user is disabled; disabled users do not receive mail.'), 77 + self::REASON_BOT => pht( 78 + 'This user is a bot; bot accounts do not receive mail.'), 79 + self::REASON_NO_ADDRESS => pht( 80 + 'Unable to load an email address for this PHID.'), 81 + self::REASON_EXTERNAL_TYPE => pht( 82 + 'Only external accounts of type "email" are deliverable; this '. 83 + 'account has a different type.'), 84 + self::REASON_UNMAILABLE => pht( 85 + 'This PHID type does not correspond to a mailable object.'), 86 + self::REASON_RESPONSE => pht( 87 + 'This message is a response to another email message, and this '. 88 + 'recipient received the original email message, so we are not '. 89 + 'sending them this substantially similar message (for example, '. 90 + 'the sender used "Reply All" instead of "Reply" in response to '. 91 + 'mail from Phabricator).'), 92 + self::REASON_SELF => pht( 93 + 'This recipient is the user whose actions caused delivery of '. 94 + 'this message, but they have set preferences so they do not '. 95 + 'receive mail about their own actions (Settings > Email '. 96 + 'Preferences > Self Actions).'), 97 + self::REASON_MAIL_DISABLED => pht( 98 + 'This recipient has disabled all email notifications '. 99 + '(Settings > Email Preferences > Email Notifications).'), 100 + self::REASON_MAILTAGS => pht( 101 + 'This mail has tags which control which users receive it, and '. 102 + 'this recipient has not elected to receive mail with any of '. 103 + 'the tags on this message (Settings > Email Preferences).'), 104 + self::REASON_UNLOADABLE => pht( 105 + 'Unable to load user record for this PHID.'), 106 + self::REASON_FORCE => pht( 107 + 'Delivery of this mail is forced and ignores deliver preferences. '. 108 + 'Mail which uses forced delivery is usually related to account '. 109 + 'management or authentication. For example, password reset email '. 110 + 'ignores mail preferences.'), 111 + ); 112 + 113 + return idx($descriptions, $reason, pht('Unknown Reason ("%s")', $reason)); 114 + } 115 + 49 116 50 117 }
+8 -18
src/applications/metamta/query/PhabricatorMetaMTAActorQuery.php
··· 70 70 71 71 $user = idx($users, $phid); 72 72 if (!$user) { 73 - $actor->setUndeliverable( 74 - pht('Unable to load user record for this PHID.')); 73 + $actor->setUndeliverable(PhabricatorMetaMTAActor::REASON_UNLOADABLE); 75 74 } else { 76 75 $actor->setName($this->getUserName($user)); 77 76 if ($user->getIsDisabled()) { 78 - $actor->setUndeliverable( 79 - pht('This user is disabled; disabled users do not receive mail.')); 77 + $actor->setUndeliverable(PhabricatorMetaMTAActor::REASON_DISABLED); 80 78 } 81 79 if ($user->getIsSystemAgent()) { 82 - $actor->setUndeliverable( 83 - pht('This user is a bot; bot accounts do not receive mail.')); 80 + $actor->setUndeliverable(PhabricatorMetaMTAActor::REASON_BOT); 84 81 } 85 82 86 83 // NOTE: We do send email to unapproved users, and to unverified users, ··· 91 88 92 89 $email = idx($emails, $phid); 93 90 if (!$email) { 94 - $actor->setUndeliverable( 95 - pht('Unable to load email record for this PHID.')); 91 + $actor->setUndeliverable(PhabricatorMetaMTAActor::REASON_NO_ADDRESS); 96 92 } else { 97 93 $actor->setEmailAddress($email->getAddress()); 98 94 } ··· 113 109 114 110 $xuser = idx($xusers, $phid); 115 111 if (!$xuser) { 116 - $actor->setUndeliverable( 117 - pht('Unable to load external user record for this PHID.')); 112 + $actor->setUndeliverable(PhabricatorMetaMTAActor::REASON_UNLOADABLE); 118 113 continue; 119 114 } 120 115 121 116 $actor->setName($xuser->getDisplayName()); 122 117 123 118 if ($xuser->getAccountType() != 'email') { 124 - $actor->setUndeliverable( 125 - pht( 126 - 'Only external accounts of type "email" are deliverable; this '. 127 - 'account has a different type.')); 119 + $actor->setUndeliverable(PhabricatorMetaMTAActor::REASON_EXTERNAL_TYPE); 128 120 continue; 129 121 } 130 122 ··· 146 138 147 139 $list = idx($lists, $phid); 148 140 if (!$list) { 149 - $actor->setUndeliverable( 150 - pht( 151 - 'Unable to load mailing list record for this PHID.')); 141 + $actor->setUndeliverable(PhabricatorMetaMTAActor::REASON_UNLOADABLE); 152 142 continue; 153 143 } 154 144 ··· 160 150 private function loadUnknownActors(array $actors, array $phids) { 161 151 foreach ($phids as $phid) { 162 152 $actor = $actors[$phid]; 163 - $actor->setUndeliverable(pht('This PHID type is not mailable.')); 153 + $actor->setUndeliverable(PhabricatorMetaMTAActor::REASON_UNMAILABLE); 164 154 } 165 155 } 166 156
+7 -20
src/applications/metamta/storage/PhabricatorMetaMTAMail.php
··· 852 852 853 853 if ($this->getForceDelivery()) { 854 854 // If we're forcing delivery, skip all the opt-out checks. 855 + foreach ($actors as $actor) { 856 + $actor->setDeliverable(PhabricatorMetaMTAActor::REASON_FORCE); 857 + } 855 858 return $actors; 856 859 } 857 860 ··· 861 864 if (!$actor) { 862 865 continue; 863 866 } 864 - $actor->setUndeliverable( 865 - pht( 866 - 'This message is a response to another email message, and this '. 867 - 'recipient received the original email message, so we are not '. 868 - 'sending them this substantially similar message (for example, '. 869 - 'the sender used "Reply All" instead of "Reply" in response to '. 870 - 'mail from Phabricator).')); 867 + $actor->setUndeliverable(PhabricatorMetaMTAActor::REASON_RESPONSE); 871 868 } 872 869 873 870 // Exclude the actor if their preferences are set. ··· 885 882 ->loadPreferences() 886 883 ->getPreference($pref_key); 887 884 if ($exclude_self) { 888 - $from_actor->setUndeliverable( 889 - pht( 890 - 'This recipient is the user whose actions caused delivery of '. 891 - 'this message, but they have set preferences so they do not '. 892 - 'receive mail about their own actions (Settings > Email '. 893 - 'Preferences > Self Actions).')); 885 + $from_actor->setUndeliverable(PhabricatorMetaMTAActor::REASON_SELF); 894 886 } 895 887 } 896 888 } ··· 907 899 false); 908 900 if ($exclude) { 909 901 $actors[$phid]->setUndeliverable( 910 - pht( 911 - 'This recipient has disabled all email notifications '. 912 - '(Settings > Email Preferences > Email Notifications).')); 902 + PhabricatorMetaMTAActor::REASON_MAIL_DISABLED); 913 903 } 914 904 } 915 905 ··· 937 927 938 928 if (!$send) { 939 929 $actors[$phid]->setUndeliverable( 940 - pht( 941 - 'This mail has tags which control which users receive it, and '. 942 - 'this recipient has not elected to receive mail with any of '. 943 - 'the tags on this message (Settings > Email Preferences).')); 930 + PhabricatorMetaMTAActor::REASON_MAILTAGS); 944 931 } 945 932 } 946 933 }