@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.

Rename "MetaMTA" mail attachments and add more mail message objects

Summary:
Depends on D19953. Ref T9141. We have a "MetaMTAAttachment" object, rename it to "MailAttachment".

Also add a "Header" object and an "EmailMessage" object. Currently, mail adapters have a large number of methods like `setSubject()`, `addTo()`, etc, that I would like to remove.

I'd like the API to be more like `sendMessage(PhabricatorMailExternalMessage $message)`. This is likely a significant simplification anyway, since the implementations of all these methods are just copy/pasted boilerplate anyway (lots of `$this->subject = $subject;`) and this will let Adapters support other message media (SMS, APNS, Whatsapp, etc.)

That's a larger change, but move toward a world where we can build a concrete `$message` object for "email" or "sms".

The `PhabricatorMailEmailMessage` object is just a dumb, flat object representation of the information an adapter needs to actually send mail. The existing `PhabricatorMetaMTAMail` is a much more complex object and has a lot of rich data (delivery status, related object PHIDs, etc) and is a storage object.

The new flow will be something like:

- `PhabricatorMetaMTAMail` (possibly renamed) is the storage object for any outbound message on this channel. It tracks message content, acceptable delivery media (SMS vs email), delivery status, related objects, has a PHID, and has a daemon worker associated with delivering it.
- It builds a `PhabricatorMailExternalMessage`, which is a simple, flat description of the message it wants to send. The subclass of this object depends on the message medium. For email, this will be an `EmailMessage`. This is just a "bag of strings" sort of object, with appropriate flattened values for the adapter to work with (e.g., Email has email addresses, SMS has phone numbers).
- It passes the `ExternalMessage` (which is a `MailMessage` or `SMSMessage` or whatever) to the adapter.
- The adapter reads the nice flat properties off it and turns them into an API request, SMTP call, etc.

This is sort of how things work today anyway. The major change is that I want to hand off a "bag of strings" object instead of calling `setX()`, `setY()`, `setZ()` with each individual value.

Test Plan: Grepped for `MetaMTAAttachment`. This doesn't change any behavior yet.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T9141

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

+159 -13
+8 -2
src/__phutil_library_map__.php
··· 3373 3373 'PhabricatorMacroTransactionQuery' => 'applications/macro/query/PhabricatorMacroTransactionQuery.php', 3374 3374 'PhabricatorMacroTransactionType' => 'applications/macro/xaction/PhabricatorMacroTransactionType.php', 3375 3375 'PhabricatorMacroViewController' => 'applications/macro/controller/PhabricatorMacroViewController.php', 3376 + 'PhabricatorMailAttachment' => 'applications/metamta/message/PhabricatorMailAttachment.php', 3376 3377 'PhabricatorMailConfigTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMailConfigTestCase.php', 3377 3378 'PhabricatorMailEmailHeraldField' => 'applications/metamta/herald/PhabricatorMailEmailHeraldField.php', 3378 3379 'PhabricatorMailEmailHeraldFieldGroup' => 'applications/metamta/herald/PhabricatorMailEmailHeraldFieldGroup.php', 3380 + 'PhabricatorMailEmailMessage' => 'applications/metamta/message/PhabricatorMailEmailMessage.php', 3379 3381 'PhabricatorMailEmailSubjectHeraldField' => 'applications/metamta/herald/PhabricatorMailEmailSubjectHeraldField.php', 3380 3382 'PhabricatorMailEngineExtension' => 'applications/metamta/engine/PhabricatorMailEngineExtension.php', 3383 + 'PhabricatorMailExternalMessage' => 'applications/metamta/message/PhabricatorMailExternalMessage.php', 3384 + 'PhabricatorMailHeader' => 'applications/metamta/message/PhabricatorMailHeader.php', 3381 3385 'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAdapter.php', 3382 3386 'PhabricatorMailImplementationAmazonSESAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAmazonSESAdapter.php', 3383 3387 'PhabricatorMailImplementationMailgunAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationMailgunAdapter.php', ··· 3443 3447 'PhabricatorMetaMTAApplicationEmailQuery' => 'applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php', 3444 3448 'PhabricatorMetaMTAApplicationEmailTransaction' => 'applications/metamta/storage/PhabricatorMetaMTAApplicationEmailTransaction.php', 3445 3449 'PhabricatorMetaMTAApplicationEmailTransactionQuery' => 'applications/metamta/query/PhabricatorMetaMTAApplicationEmailTransactionQuery.php', 3446 - 'PhabricatorMetaMTAAttachment' => 'applications/metamta/storage/PhabricatorMetaMTAAttachment.php', 3447 3450 'PhabricatorMetaMTAConfigOptions' => 'applications/config/option/PhabricatorMetaMTAConfigOptions.php', 3448 3451 'PhabricatorMetaMTAController' => 'applications/metamta/controller/PhabricatorMetaMTAController.php', 3449 3452 'PhabricatorMetaMTADAO' => 'applications/metamta/storage/PhabricatorMetaMTADAO.php', ··· 9182 9185 'PhabricatorMacroTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 9183 9186 'PhabricatorMacroTransactionType' => 'PhabricatorModularTransactionType', 9184 9187 'PhabricatorMacroViewController' => 'PhabricatorMacroController', 9188 + 'PhabricatorMailAttachment' => 'Phobject', 9185 9189 'PhabricatorMailConfigTestCase' => 'PhabricatorTestCase', 9186 9190 'PhabricatorMailEmailHeraldField' => 'HeraldField', 9187 9191 'PhabricatorMailEmailHeraldFieldGroup' => 'HeraldFieldGroup', 9192 + 'PhabricatorMailEmailMessage' => 'PhabricatorMailExternalMessage', 9188 9193 'PhabricatorMailEmailSubjectHeraldField' => 'PhabricatorMailEmailHeraldField', 9189 9194 'PhabricatorMailEngineExtension' => 'Phobject', 9195 + 'PhabricatorMailExternalMessage' => 'Phobject', 9196 + 'PhabricatorMailHeader' => 'Phobject', 9190 9197 'PhabricatorMailImplementationAdapter' => 'Phobject', 9191 9198 'PhabricatorMailImplementationAmazonSESAdapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter', 9192 9199 'PhabricatorMailImplementationMailgunAdapter' => 'PhabricatorMailImplementationAdapter', ··· 9259 9266 'PhabricatorMetaMTAApplicationEmailQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 9260 9267 'PhabricatorMetaMTAApplicationEmailTransaction' => 'PhabricatorApplicationTransaction', 9261 9268 'PhabricatorMetaMTAApplicationEmailTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 9262 - 'PhabricatorMetaMTAAttachment' => 'Phobject', 9263 9269 'PhabricatorMetaMTAConfigOptions' => 'PhabricatorApplicationConfigOptions', 9264 9270 'PhabricatorMetaMTAController' => 'PhabricatorController', 9265 9271 'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO',
+1 -1
src/applications/audit/editor/PhabricatorAuditEditor.php
··· 611 611 $commit->getCommitIdentifier()); 612 612 613 613 $template->addAttachment( 614 - new PhabricatorMetaMTAAttachment( 614 + new PhabricatorMailAttachment( 615 615 $raw_patch, 616 616 $commit_name.'.patch', 617 617 'text/x-patch; charset='.$encoding));
+1 -1
src/applications/calendar/editor/PhabricatorCalendarEventEditor.php
··· 364 364 ->setEvents(array($event)) 365 365 ->writeICSDocument(); 366 366 367 - $ics_attachment = new PhabricatorMetaMTAAttachment( 367 + $ics_attachment = new PhabricatorMailAttachment( 368 368 $ics_data, 369 369 $event->getICSFilename(), 370 370 'text/calendar');
+1 -1
src/applications/differential/editor/DifferentialTransactionEditor.php
··· 715 715 $name = pht('D%s.%s.patch', $object->getID(), $diff->getID()); 716 716 $mime_type = 'text/x-patch; charset=utf-8'; 717 717 $body->addAttachment( 718 - new PhabricatorMetaMTAAttachment($patch, $name, $mime_type)); 718 + new PhabricatorMailAttachment($patch, $name, $mime_type)); 719 719 } 720 720 } 721 721 }
+1 -1
src/applications/metamta/management/PhabricatorMailManagementSendTestWorkflow.php
··· 193 193 $data = Filesystem::readFile($attachment); 194 194 $name = basename($attachment); 195 195 $mime = Filesystem::getMimeType($attachment); 196 - $file = new PhabricatorMetaMTAAttachment($data, $name, $mime); 196 + $file = new PhabricatorMailAttachment($data, $name, $mime); 197 197 $mail->addAttachment($file); 198 198 } 199 199
+103
src/applications/metamta/message/PhabricatorMailEmailMessage.php
··· 1 + <?php 2 + 3 + final class PhabricatorMailEmailMessage 4 + extends PhabricatorMailExternalMessage { 5 + 6 + const MESSAGETYPE = 'email'; 7 + 8 + private $fromAddress; 9 + private $replyToAddress; 10 + private $toAddresses = array(); 11 + private $ccAddresses = array(); 12 + private $headers = array(); 13 + private $attachments = array(); 14 + private $subject; 15 + private $textBody; 16 + private $htmlBody; 17 + 18 + public function setFromAddress(PhutilEmailAddress $from_address) { 19 + $this->fromAddress = $from_address; 20 + return $this; 21 + } 22 + 23 + public function getFromAddress() { 24 + return $this->fromAddress; 25 + } 26 + 27 + public function setReplyToAddress(PhutilEmailAddress $address) { 28 + $this->replyToAddress = $address; 29 + return $this; 30 + } 31 + 32 + public function getReplyToAddress() { 33 + return $this->replyToAddress; 34 + } 35 + 36 + public function setToAddresses(array $addresses) { 37 + assert_instances_of($addresses, 'PhutilEmailAddress'); 38 + $this->toAddresses = $addresses; 39 + return $this; 40 + } 41 + 42 + public function getToAddresses() { 43 + return $this->toAddresses; 44 + } 45 + 46 + public function setCCAddresses(array $addresses) { 47 + assert_instances_of($addresses, 'PhutilEmailAddress'); 48 + $this->ccAddresses = $addresses; 49 + return $this; 50 + } 51 + 52 + public function getCCAddresses() { 53 + return $this->ccAddresses; 54 + } 55 + 56 + public function setHeaders(array $headers) { 57 + assert_instances_of($headers, 'PhabricatorMailHeader'); 58 + $this->headers = $headers; 59 + return $this; 60 + } 61 + 62 + public function getHeaders() { 63 + return $this->headers; 64 + } 65 + 66 + public function setAttachments(array $attachments) { 67 + assert_instances_of($attachments, 'PhabricatorMailAttachment'); 68 + $this->attachments = $attachments; 69 + return $this; 70 + } 71 + 72 + public function getAttachments() { 73 + return $this->attachments; 74 + } 75 + 76 + public function setSubject($subject) { 77 + $this->subject = $subject; 78 + return $this; 79 + } 80 + 81 + public function getSubject() { 82 + return $this->subject; 83 + } 84 + 85 + public function setTextBody($text_body) { 86 + $this->textBody = $text_body; 87 + return $this; 88 + } 89 + 90 + public function getTextBody() { 91 + return $this->textBody; 92 + } 93 + 94 + public function setHTMLBody($html_body) { 95 + $this->htmlBody = $html_body; 96 + return $this; 97 + } 98 + 99 + public function getHTMLBody() { 100 + return $this->htmlBody; 101 + } 102 + 103 + }
+10
src/applications/metamta/message/PhabricatorMailExternalMessage.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorMailExternalMessage 4 + extends Phobject { 5 + 6 + final public function getMessageType() { 7 + return $this->getPhobjectClassConstant('MESSAGETYPE'); 8 + } 9 + 10 + }
+27
src/applications/metamta/message/PhabricatorMailHeader.php
··· 1 + <?php 2 + 3 + final class PhabricatorMailHeader 4 + extends Phobject { 5 + 6 + private $name; 7 + private $value; 8 + 9 + public function setName($name) { 10 + $this->name = $name; 11 + return $this; 12 + } 13 + 14 + public function getName() { 15 + return $this->name; 16 + } 17 + 18 + public function setValue($value) { 19 + $this->value = $value; 20 + return $this; 21 + } 22 + 23 + public function getValue() { 24 + return $this->value; 25 + } 26 + 27 + }
+1 -1
src/applications/metamta/storage/PhabricatorMetaMTAAttachment.php src/applications/metamta/message/PhabricatorMailAttachment.php
··· 1 1 <?php 2 2 3 - final class PhabricatorMetaMTAAttachment extends Phobject { 3 + final class PhabricatorMailAttachment extends Phobject { 4 4 5 5 private $data; 6 6 private $filename;
+3 -3
src/applications/metamta/storage/PhabricatorMetaMTAMail.php
··· 191 191 return $this; 192 192 } 193 193 194 - public function addAttachment(PhabricatorMetaMTAAttachment $attachment) { 194 + public function addAttachment(PhabricatorMailAttachment $attachment) { 195 195 $this->parameters['attachments'][] = $attachment->toDictionary(); 196 196 return $this; 197 197 } ··· 201 201 202 202 $result = array(); 203 203 foreach ($dicts as $dict) { 204 - $result[] = PhabricatorMetaMTAAttachment::newFromDictionary($dict); 204 + $result[] = PhabricatorMailAttachment::newFromDictionary($dict); 205 205 } 206 206 return $result; 207 207 } ··· 236 236 } 237 237 238 238 public function setAttachments(array $attachments) { 239 - assert_instances_of($attachments, 'PhabricatorMetaMTAAttachment'); 239 + assert_instances_of($attachments, 'PhabricatorMailAttachment'); 240 240 $this->setParam('attachments', mpull($attachments, 'toDictionary')); 241 241 return $this; 242 242 }
+3 -3
src/applications/metamta/view/PhabricatorMetaMTAMailBody.php
··· 155 155 /** 156 156 * Add an attachment. 157 157 * 158 - * @param PhabricatorMetaMTAAttachment Attachment. 158 + * @param PhabricatorMailAttachment Attachment. 159 159 * @return this 160 160 * @task compose 161 161 */ 162 - public function addAttachment(PhabricatorMetaMTAAttachment $attachment) { 162 + public function addAttachment(PhabricatorMailAttachment $attachment) { 163 163 $this->attachments[] = $attachment; 164 164 return $this; 165 165 } ··· 187 187 /** 188 188 * Retrieve attachments. 189 189 * 190 - * @return list<PhabricatorMetaMTAAttachment> Attachments. 190 + * @return list<PhabricatorMailAttachment> Attachments. 191 191 * @task render 192 192 */ 193 193 public function getAttachments() {