Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14013821
D8832.id20965.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
23 KB
Referenced Files
None
Subscribers
None
D8832.id20965.diff
View Options
diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -144,7 +144,7 @@
'rsrc/css/phui/phui-status.css' => '2f562399',
'rsrc/css/phui/phui-tag-view.css' => '295d81c4',
'rsrc/css/phui/phui-text.css' => '23e9b4b7',
- 'rsrc/css/phui/phui-timeline-view.css' => '17905388',
+ 'rsrc/css/phui/phui-timeline-view.css' => '18035042',
'rsrc/css/phui/phui-workboard-view.css' => '84f2c272',
'rsrc/css/phui/phui-workpanel-view.css' => '97b69459',
'rsrc/css/sprite-actions.css' => '969ad0e5',
@@ -767,7 +767,7 @@
'phui-status-list-view-css' => '2f562399',
'phui-tag-view-css' => '295d81c4',
'phui-text-css' => '23e9b4b7',
- 'phui-timeline-view-css' => '17905388',
+ 'phui-timeline-view-css' => '18035042',
'phui-workboard-view-css' => '84f2c272',
'phui-workpanel-view-css' => '97b69459',
'policy-css' => '957ea14c',
diff --git a/src/applications/metamta/PhabricatorMetaMTAWorker.php b/src/applications/metamta/PhabricatorMetaMTAWorker.php
--- a/src/applications/metamta/PhabricatorMetaMTAWorker.php
+++ b/src/applications/metamta/PhabricatorMetaMTAWorker.php
@@ -22,14 +22,11 @@
return;
}
- $id = $message->getID();
- $message->sendNow();
-
- // task failed if the message is still queued
- // (instead of sent, void, or failed)
- if ($message->getStatus() == PhabricatorMetaMTAMail::STATUS_QUEUE) {
- throw new Exception(
- pht('Failed to send message.'));
+ try {
+ $message->sendNow();
+ } catch (PhabricatorMetaMTAPermanentFailureException $ex) {
+ // If the mailer fails permanently, fail this task permanently.
+ throw new PhabricatorWorkerPermanentFailureException($ex->getMessage());
}
}
diff --git a/src/applications/metamta/adapter/PhabricatorMailImplementationMailgunAdapter.php b/src/applications/metamta/adapter/PhabricatorMailImplementationMailgunAdapter.php
--- a/src/applications/metamta/adapter/PhabricatorMailImplementationMailgunAdapter.php
+++ b/src/applications/metamta/adapter/PhabricatorMailImplementationMailgunAdapter.php
@@ -7,6 +7,7 @@
extends PhabricatorMailImplementationAdapter {
private $params = array();
+ private $attachments = array();
public function setFrom($email, $name = '') {
$this->params['from'] = $email;
@@ -37,9 +38,13 @@
}
public function addAttachment($data, $filename, $mimetype) {
- // TODO: implement attachments. Requires changes in HTTPSFuture
- throw new Exception(
- "Mailgun adapter does not currently support attachments.");
+ $this->attachments[] = array(
+ 'data' => $data,
+ 'name' => $filename,
+ 'type' => $mimetype,
+ );
+
+ return $this;
}
public function addHeader($header_name, $header_value) {
@@ -71,7 +76,7 @@
$domain = PhabricatorEnv::getEnvConfig('mailgun.domain');
$params = array();
- $params['to'] = idx($this->params, 'tos', array());
+ $params['to'] = implode(', ', idx($this->params, 'tos', array()));
$params['subject'] = idx($this->params, 'subject');
if (idx($this->params, 'is-html')) {
@@ -93,7 +98,7 @@
}
if (idx($this->params, 'ccs')) {
- $params['cc'] = $this->params['ccs'];
+ $params['cc'] = implode(', ', $this->params['ccs']);
}
foreach (idx($this->params, 'headers', array()) as $header) {
@@ -106,6 +111,14 @@
$params);
$future->setMethod('POST');
+ foreach ($this->attachments as $attachment) {
+ $future->attachFileData(
+ 'attachment',
+ $attachment['data'],
+ $attachment['name'],
+ $attachment['type']);
+ }
+
list($body) = $future->resolvex();
$response = json_decode($body, true);
diff --git a/src/applications/metamta/management/PhabricatorMailManagementResendWorkflow.php b/src/applications/metamta/management/PhabricatorMailManagementResendWorkflow.php
--- a/src/applications/metamta/management/PhabricatorMailManagementResendWorkflow.php
+++ b/src/applications/metamta/management/PhabricatorMailManagementResendWorkflow.php
@@ -44,15 +44,6 @@
}
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->save();
@@ -60,9 +51,6 @@
'PhabricatorMetaMTAWorker',
$message->getID());
- $message->setWorkerTaskID($mailer_task->getID());
- $message->save();
-
$console->writeOut(
"Queued message #%d for resend.\n",
$message->getID());
diff --git a/src/applications/metamta/management/PhabricatorMailManagementSendTestWorkflow.php b/src/applications/metamta/management/PhabricatorMailManagementSendTestWorkflow.php
--- a/src/applications/metamta/management/PhabricatorMailManagementSendTestWorkflow.php
+++ b/src/applications/metamta/management/PhabricatorMailManagementSendTestWorkflow.php
@@ -126,8 +126,16 @@
$mail->setFrom($from->getPHID());
}
+ foreach ($attach as $attachment) {
+ $data = Filesystem::readFile($attachment);
+ $name = basename($attachment);
+ $mime = Filesystem::getMimeType($attachment);
+ $file = new PhabricatorMetaMTAAttachment($data, $name, $mime);
+ $mail->addAttachment($file);
+ }
+
+ PhabricatorWorker::setRunAllTasksInProcess(true);
$mail->save();
- $mail->sendNow();
$console->writeErr(
"%s\n\n phabricator/ $ ./bin/mail show-outbound --id %d\n\n",
diff --git a/src/applications/metamta/storage/PhabricatorMetaMTAMail.php b/src/applications/metamta/storage/PhabricatorMetaMTAMail.php
--- a/src/applications/metamta/storage/PhabricatorMetaMTAMail.php
+++ b/src/applications/metamta/storage/PhabricatorMetaMTAMail.php
@@ -231,15 +231,6 @@
return $this->getParam('is-error', false);
}
- public function getWorkerTaskID() {
- return $this->getParam('worker-task');
- }
-
- public function setWorkerTaskID($id) {
- $this->setParam('worker-task', $id);
- return $this;
- }
-
public function getToPHIDs() {
return $this->getParam('to', array());
}
@@ -304,16 +295,13 @@
$this->openTransaction();
// Save to generate a task ID.
- parent::save();
+ $result = parent::save();
// Queue a task to send this mail.
$mailer_task = PhabricatorWorker::scheduleTask(
'PhabricatorMetaMTAWorker',
$this->getID());
- // Save again to update the task ID.
- $this->setWorkerTaskID($mailer_task->getID());
- $result = parent::save();
$this->saveTransaction();
return $result;
@@ -624,30 +612,41 @@
$mailer->addCCs($add_cc);
}
} catch (Exception $ex) {
- $this->setStatus(self::STATUS_FAIL);
- $this->setMessage($ex->getMessage());
- return $this->save();
+ $this
+ ->setStatus(self::STATUS_FAIL)
+ ->setMessage($ex->getMessage())
+ ->save();
+
+ throw $ex;
}
try {
$ok = $mailer->send();
- $error = null;
+ if (!$ok) {
+ // TODO: At some point, we should clean this up and make all mailers
+ // throw.
+ throw new Exception(
+ pht('Mail adapter encountered an unexpected, unspecified failure.'));
+ }
+
+ $this->setStatus(self::STATUS_SENT);
+ $this->save();
+
+ return $this;
} catch (PhabricatorMetaMTAPermanentFailureException $ex) {
- $this->setStatus(self::STATUS_FAIL);
- $this->setMessage($ex->getMessage());
- return $this->save();
+ $this
+ ->setStatus(self::STATUS_FAIL)
+ ->setMessage($ex->getMessage())
+ ->save();
+
+ throw $ex;
} catch (Exception $ex) {
- $ok = false;
- $error = $ex->getMessage()."\n".$ex->getTraceAsString();
- }
+ $this
+ ->setMessage($ex->getMessage()."\n".$ex->getTraceAsString())
+ ->save();
- if (!$ok) {
- $this->setMessage($error);
- } else {
- $this->setStatus(self::STATUS_SENT);
+ throw $ex;
}
-
- return $this->save();
}
public static function getReadableStatus($status_code) {
diff --git a/src/applications/metamta/storage/__tests__/PhabricatorMetaMTAMailTestCase.php b/src/applications/metamta/storage/__tests__/PhabricatorMetaMTAMailTestCase.php
--- a/src/applications/metamta/storage/__tests__/PhabricatorMetaMTAMailTestCase.php
+++ b/src/applications/metamta/storage/__tests__/PhabricatorMetaMTAMailTestCase.php
@@ -30,7 +30,11 @@
$mailer = new PhabricatorMailImplementationTestAdapter();
$mailer->setFailTemporarily(true);
- $mail->sendNow($force = true, $mailer);
+ try {
+ $mail->sendNow($force = true, $mailer);
+ } catch (Exception $ex) {
+ // Ignore.
+ }
$this->assertEqual(
PhabricatorMetaMTAMail::STATUS_QUEUE,
$mail->getStatus());
@@ -42,7 +46,11 @@
$mailer = new PhabricatorMailImplementationTestAdapter();
$mailer->setFailPermanently(true);
- $mail->sendNow($force = true, $mailer);
+ try {
+ $mail->sendNow($force = true, $mailer);
+ } catch (Exception $ex) {
+ // Ignore.
+ }
$this->assertEqual(
PhabricatorMetaMTAMail::STATUS_FAIL,
$mail->getStatus());
diff --git a/src/docs/user/configuration/configuring_inbound_email.diviner b/src/docs/user/configuration/configuring_inbound_email.diviner
--- a/src/docs/user/configuration/configuring_inbound_email.diviner
+++ b/src/docs/user/configuration/configuring_inbound_email.diviner
@@ -8,19 +8,24 @@
= Preamble =
This can be extremely difficult to configure correctly. This is doubly true if
-you use sendmail.
+you use a local MTA.
-There are basically a few approaches available:
+There are a few approaches available:
- - Use SendGrid (<http://sendgrid.com/>), which is very easy but is not free.
- - Run your own MTA, which can be quite harrowing to configure but is free.
- - Tell the Phabricator devteam about another service you'd like support for,
- this stuff is seriously terrible to configure on your own.
+| Receive Mail With | Setup | Cost | Notes |
+|--------|-------|------|-------|
+| Mailgun | Easy | Cheap | Recommended |
+| SendGrid | Easy | Cheap | |
+| Local MTA | Extremely Difficult | Free | Strongly discouraged! |
+
+The remainder of this document walks through configuring Phabricator to
+receive mail, and then configuring your chosen transport to deliver mail
+to Phabricator.
= Configuring Phabricator =
-By default, Phabricator uses a "noreply@phabricator.example.com" email address
-as the 'From' (configurable with ##metamta.default-address##) and sets
+By default, Phabricator uses a `noreply@phabricator.example.com` email address
+as the 'From' (configurable with `metamta.default-address`) and sets
'Reply-To' to the user generating the email (e.g., by making a comment), if the
mail was generated by a user action. This means that users can reply (or
reply-all) to email to discuss changes, but the conversation won't be recorded
@@ -36,24 +41,24 @@
Maniphest.
Set these keys to some domain which you configure according to the instructions
-below, e.g. "##phabricator.example.com##". You can set these both to the same
+below, e.g. `phabricator.example.com`. You can set these both to the same
domain, and will generally want to. Once you set these keys, emails will use a
-'Reply-To' like "##T123+273+af310f9220ad@example.com##", which -- when
+'Reply-To' like `T123+273+af310f9220ad@example.com`, which -- when
configured correctly, according to the instructions below -- will parse incoming
email and allow users to interact with Maniphest tasks and Differential
revisions over email.
-If you don't want phabricator to take up an entire domain (or subdomain) you
+If you don't want Phabricator to take up an entire domain (or subdomain) you
can configure a general prefix so you can use a single mailbox to receive mail
-on. To make use of this set ##metamta.single-reply-handler-prefix## to the
-prefix of your choice, and phabricator will prepend this to the 'Reply-To'
+on. To make use of this set `metamta.single-reply-handler-prefix` to the
+prefix of your choice, and Phabricator will prepend this to the 'Reply-To'
mail address. This works because everything up to the first (optional) '+'
character in an email-address is considered the receiver, and everything
-after is essentially "ignored".
+after is essentially ignored.
-You can also set up a task creation email address, like ##bugs@example.com##,
+You can also set up a task creation email address, like `bugs@example.com`,
which will create a Maniphest task out of any email which is set to it. To do
-this, set ##metamta.maniphest.public-create-email## in your configuration. This
+this, set `metamta.maniphest.public-create-email` in your configuration. This
has some mild security implications, see below.
= Security =
@@ -77,9 +82,9 @@
over).
If you leak a bunch of reply-to addresses by accident, you can change
-##phabricator.mail-key## in your configuration to invalidate all the old hashes.
+`phabricator.mail-key` in your configuration to invalidate all the old hashes.
-You can also set ##metamta.public-replies##, which will change how Phabricator
+You can also set `metamta.public-replies`, which will change how Phabricator
delivers email. Instead of sending each recipient a unique mail with a personal
reply-to address, it will send a single email to everyone with a public reply-to
address. This decreases security because anyone who can spoof a "From" address
@@ -88,7 +93,7 @@
will still contain a hash unique to the object it represents, so users who have
not received an email about an object can not blindly interact with it.
-If you enable ##metamta.maniphest.public-create-email##, that address also uses
+If you enable `metamta.maniphest.public-create-email`, that address also uses
the weaker "From" authentication mechanism.
NOTE: Phabricator does not currently attempt to verify "From" addresses because
@@ -116,7 +121,18 @@
Run `bin/mail help <command>` for detailed help on using these commands.
-= SendGrid =
+= Mailgun Setup =
+
+To use Mailgun, you need a Mailgun account. You can sign up at
+<http://www.mailgun.com>. Provided you have such an account, configure it
+like this:
+
+ - Configure a mail domain according to Mailgun's instructions.
+ - Add a Mailgun route with a `catch_all()` rule which takes the action
+ `forward("https://phabricator.example.com/mail/mailgun/")`. Replace the
+ example domain with your actual domain.
+
+= SendGrid Setup =
To use SendGrid, you need a SendGrid account with access to the "Parse API" for
inbound email. Provided you have such an account, configure it like this:
@@ -142,7 +158,7 @@
to ##anything@phabricator.example.com## and it should appear in
`bin/mail list-inbound` within a few seconds.
-= Installing Mailparse =
+= Local MTA: Installing Mailparse =
If you're going to run your own MTA, you need to install the PECL mailparse
extension. In theory, you can do that with:
@@ -165,7 +181,7 @@
mailparse.so. This is not the default if you have individual files in
##php.d/##.
-= MTA: Configuring Sendmail =
+= Local MTA: Configuring Sendmail =
Before you can configure Sendmail, you need to install Mailparse. See the
section "Installing Mailparse" above.
@@ -199,7 +215,7 @@
script. Run ##sudo /etc/mail/make## or similar and then restart sendmail with
##sudo /etc/init.d/sendmail restart##.
-= MTA: Configuring Lamson =
+= Local MTA: Configuring Lamson =
Before you can configure Lamson, you need to install Mailparse. See the section
"Installing Mailparse" above.
diff --git a/src/docs/user/configuration/configuring_outbound_email.diviner b/src/docs/user/configuration/configuring_outbound_email.diviner
--- a/src/docs/user/configuration/configuring_outbound_email.diviner
+++ b/src/docs/user/configuration/configuring_outbound_email.diviner
@@ -5,53 +5,60 @@
= Overview =
-Phabricator can send outbound email via several different adapters:
-
- - by running ##sendmail## on the local host with SMTP; or
- - by running postfix on the local host with SMTP; or
- - by using Amazon SES (Simple Email Service); or
- - by using SendGrid's REST API; or
- - via a custom adapter you write; or
- - by dropping email into a hole and not delivering it.
-
-Of these, ##sendmail## is the default but requires some configuration. SES and
-SendGrid are easier, but cost money and have some limitations. Writing a custom
-solution requires digging into the code. See below for details on how to set up
-each method.
-
-Phabricator can also send outbound email in two ways:
-
- - immediately, when messages are generated (default); or
- - in the background, via a daemon.
-
-Sending mail in the background requires that you be running the Phabricator
-daemons, but can greatly improve the performance of the application if your mail
-handler is slow. For more information on using daemons, see
+Phabricator can send outbound email via several different providers, called
+"Adapters".
+
+| Send Mail With | Setup | Cost | Inbound | Notes |
+|---------|-------|------|---------|-------|
+| Mailgun | Easy | Cheap | Yes | Recommended |
+| Amazon SES | Easy | Cheap | No | Recommended |
+| SendGrid | Easy | Cheap | Yes | |
+| External SMTP | Medium | Varies | No | Gmail, etc. |
+| Local SMTP | Hard | Free | No | (Default) sendmail, postfix, etc |
+| Custom | Hard | Free | No | Write an adapter for some other service. |
+| Drop in a Hole | Easy | Free | No | Drops mail in a deep, dark hole. |
+
+Of these options, sending mail via local SMTP is the default, but usually
+requires some configuration to get working. See below for details on how to
+select and configure a delivery method.
+
+Overall, Mailgun and SES are much easier to set up, and using one of them is
+recommended. In particular, Mailgun will also let you set up inbound email
+easily.
+
+If you have some internal mail service you'd like to use you can also
+write a custom adapter, but this requires digging into the code.
+
+Phabricator sends mail in the background, so the daemons need to be running for
+it to be able to deliver mail. You should receive setup warnings if they are
+not. For more information on using daemons, see
@{article:Managing Daemons with phd}.
= Basics =
Regardless of how outbound email is delivered, you should configure these keys
-in your configuration file:
+in your configuration:
- **metamta.default-address** determines where mail is sent "From" by
- default. If your domain is ##example.org##, set this to something like
- "##noreply@example.org##".
- - **metamta.domain** should be set to your domain, e.g. "##example.org##".
+ default. If your domain is `example.org`, set this to something like
+ `noreply@example.org`.
+ - **metamta.domain** should be set to your domain, e.g. `example.org`.
- **metamta.can-send-as-user** should be left as ##false## in most cases,
- but see the documentation in ##default.conf.php## for details.
+ but see the documentation for details.
= Configuring Mail Adapters =
-To choose how mail will be sent, change the **metamta.mail-adapter** key in
-your configuration. Possible values are:
+To choose how mail will be sent, change the `metamta.mail-adapter` key in
+your configuration. Possible values are listed in the UI:
+ - ##PhabricatorMailImplementationAmazonMailgunAdapter##: use Mailgun, see
+ "Adapter: Mailgun".
+ - ##PhabricatorMailImplementationAmazonSESAdapter##: use Amazon SES, see
+ "Adapter: Amazon SES".
- ##PhabricatorMailImplementationPHPMailerLiteAdapter##: default, uses
"sendmail", see "Adapter: Sendmail".
- ##PhabricatorMailImplementationPHPMailerAdapter##: uses SMTP, see
"Adapter: SMTP".
- - ##PhabricatorMailImplementationAmazonSESAdapter##: use Amazon SES, see
- "Adapter: Amazon SES".
- ##PhabricatorMailImplementationSendGridAdapter##: use SendGrid, see
"Adapter: SendGrid".
- ##Some Custom Class You Write##: use a custom adapter you write, see
@@ -64,8 +71,8 @@
= Adapter: Sendmail =
This is the default, and selected by choosing
-##PhabricatorMailImplementationPHPMailerLiteAdapter## as the value for
-**metamta.mail-adapter**. This requires a 'sendmail' binary to be installed on
+`PhabricatorMailImplementationPHPMailerLiteAdapter` as the value for
+**metamta.mail-adapter**. This requires a `sendmail` binary to be installed on
the system. Most MTAs (e.g., sendmail, qmail, postfix) should do this, but your
machine may not have one installed by default. For install instructions, consult
the documentation for your favorite MTA.
@@ -74,25 +81,35 @@
rules, blackholes, and MTA configuration which are beyond the scope of this
document. If you can already send outbound email from the command line or know
how to configure it, this option is straightforward. If you have no idea how to
-do any of this, consider using Amazon SES.
+do any of this, strongly consider using Mailgun or Amazon SES instead.
= Adapter: SMTP =
-For most situations of using SMTP to send email, you could actually use
-'sendmail' or 'postfix' to do it. But some SMTP server requires authentication
-and the 'sendmail' mailer doesn't work. If you want to try with postfix, for
-install instructions, consult the documentation for postfix as MTA and you
-could configure to use SMTP then.
-
-To configure Phabricator to use SMTP, set these configuration keys:
+You can use this adapter to send mail via an external SMTP server, like Gmail.
+To do this, set these configuration keys:
- **metamta.mail-adapter**: set to
- "PhabricatorMailImplementationPHPMailerAdapter".
- - **phpmailer.mailer**: set to "smtp".
- - **phpmailer.smtp-host**: set to hostname of your smtp server.
- - **phpmailer.smtp-port**: set to port of your smtp server.
+ `PhabricatorMailImplementationPHPMailerAdapter`.
+ - **phpmailer.mailer**: set to `smtp`.
+ - **phpmailer.smtp-host**: set to hostname of your SMTP server.
+ - **phpmailer.smtp-port**: set to port of your SMTP server.
- **phpmailer.smtp-user**: set to your username used for authentication.
- **phpmailer.smtp-password**: set to your password used for authentication.
+ - **phpmailer.smtp-protocol**: set to `tls` or `ssl` if necessary. Use
+ `ssl` for Gmail.
+
+= Adapter: Mailgun =
+
+Mailgun is an email delivery service. You can learn more at
+<http://www.mailgun.com>. Mailgun isn't free, but is very easy to configure
+and works well.
+
+To use Mailgun, sign up for an account, then set these configuration keys:
+
+ - **metamta.mail-adapter**: set to
+ `PhabricatorMailImplementationMailgunAdapter`.
+ - **mailgun.api-key**: set to your Mailgun API key.
+ - **mailgun.domain**: set to your Mailgun domain.
= Adapter: Amazon SES =
@@ -113,10 +130,6 @@
then follow the Amazon SES verification process to verify it. You won't be able
to send email until you do this!
-NOTE: Amazon SES is slow to accept mail (often 1-2 seconds) and application
-performance will improve greatly if you configure outbound email to send in
-the background.
-
= Adapter: SendGrid =
SendGrid is an email delivery service like Amazon SES. You can learn more at
@@ -140,9 +153,9 @@
You can provide a custom adapter by writing a concrete subclass of
@{class:PhabricatorMailImplementationAdapter} and setting it as the
-**metamta.mail-adapter**.
+`metamta.mail-adapter`.
-TODO: This needs to be better documented once extending Phabricator is better
+TODO: This should be better documented once extending Phabricator is better
documented.
= Adapter: Disable Outbound Mail =
@@ -150,7 +163,7 @@
You can use the @{class:PhabricatorMailImplementationTestAdapter} to completely
disable outbound mail, if you don't want to send mail or don't want to configure
it yet. Just set **metamta.mail-adapter** to
-"PhabricatorMailImplementationTestAdapter".
+`PhabricatorMailImplementationTestAdapter`.
= Testing and Debugging Outbound Email =
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Nov 3, 4:17 PM (1 w, 2 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6721461
Default Alt Text
D8832.id20965.diff (23 KB)
Attached To
Mode
D8832: Clean up numerous rough edges in Mail configuration
Attached
Detach File
Event Timeline
Log In to Comment