Page MenuHomePhorge

No OneTemporary

diff --git a/src/applications/config/management/PhabricatorConfigManagementSetWorkflow.php b/src/applications/config/management/PhabricatorConfigManagementSetWorkflow.php
index 9f50d2eeed..22b760872e 100644
--- a/src/applications/config/management/PhabricatorConfigManagementSetWorkflow.php
+++ b/src/applications/config/management/PhabricatorConfigManagementSetWorkflow.php
@@ -1,130 +1,150 @@
<?php
final class PhabricatorConfigManagementSetWorkflow
extends PhabricatorConfigManagementWorkflow {
protected function didConstruct() {
$this
->setName('set')
- ->setExamples('**set** __key__ __value__')
+ ->setExamples(
+ "**set** __key__ __value__\n".
+ "**set** __key__ --stdin < value.json")
->setSynopsis(pht('Set a local configuration value.'))
->setArguments(
array(
array(
'name' => 'database',
'help' => pht(
'Update configuration in the database instead of '.
'in local configuration.'),
),
+ array(
+ 'name' => 'stdin',
+ 'help' => pht('Read option value from stdin.'),
+ ),
array(
'name' => 'args',
'wildcard' => true,
),
));
}
public function execute(PhutilArgumentParser $args) {
$console = PhutilConsole::getConsole();
$argv = $args->getArg('args');
if (count($argv) == 0) {
throw new PhutilArgumentUsageException(
pht('Specify a configuration key and a value to set it to.'));
}
+ $is_stdin = $args->getArg('stdin');
+
$key = $argv[0];
- if (count($argv) == 1) {
- throw new PhutilArgumentUsageException(
- pht(
- "Specify a value to set the key '%s' to.",
- $key));
- }
+ if ($is_stdin) {
+ if (count($argv) > 1) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Too many arguments: expected only a key when using "--stdin".'));
+ }
- $value = $argv[1];
+ fprintf(STDERR, tsprintf("%s\n", pht('Reading value from stdin...')));
+ $value = file_get_contents('php://stdin');
+ } else {
+ if (count($argv) == 1) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ "Specify a value to set the key '%s' to.",
+ $key));
+ }
- if (count($argv) > 2) {
- throw new PhutilArgumentUsageException(
- pht(
- 'Too many arguments: expected one key and one value.'));
+ if (count($argv) > 2) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Too many arguments: expected one key and one value.'));
+ }
+
+ $value = $argv[1];
}
+
$options = PhabricatorApplicationConfigOptions::loadAllOptions();
if (empty($options[$key])) {
throw new PhutilArgumentUsageException(
pht(
"No such configuration key '%s'! Use `%s` to list all keys.",
$key,
'config list'));
}
$option = $options[$key];
$type = $option->newOptionType();
if ($type) {
try {
$value = $type->newValueFromCommandLineValue(
$option,
$value);
$type->validateStoredValue($option, $value);
} catch (PhabricatorConfigValidationException $ex) {
throw new PhutilArgumentUsageException($ex->getMessage());
}
} else {
// NOTE: For now, this handles both "wild" values and custom types.
$type = $option->getType();
switch ($type) {
default:
$value = json_decode($value, true);
if (!is_array($value)) {
switch ($type) {
default:
$message = pht(
'Config key "%s" is of type "%s". Specify it in JSON.',
$key,
$type);
break;
}
throw new PhutilArgumentUsageException($message);
}
break;
}
}
$use_database = $args->getArg('database');
if ($option->getLocked() && $use_database) {
throw new PhutilArgumentUsageException(
pht(
'Config key "%s" is locked and can only be set in local '.
'configuration. To learn more, see "%s" in the documentation.',
$key,
pht('Configuration Guide: Locked and Hidden Configuration')));
}
try {
$option->getGroup()->validateOption($option, $value);
} catch (PhabricatorConfigValidationException $validation) {
// Convert this into a usage exception so we don't dump a stack trace.
throw new PhutilArgumentUsageException($validation->getMessage());
}
if ($use_database) {
$config_type = 'database';
$config_entry = PhabricatorConfigEntry::loadConfigEntry($key);
$config_entry->setValue($value);
// If the entry has been deleted, resurrect it.
$config_entry->setIsDeleted(0);
$config_entry->save();
} else {
$config_type = 'local';
id(new PhabricatorConfigLocalSource())
->setKeys(array($key => $value));
}
$console->writeOut(
"%s\n",
pht("Set '%s' in %s configuration.", $key, $config_type));
}
}
diff --git a/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php b/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php
index 43734abea0..0b916150bc 100644
--- a/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php
+++ b/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php
@@ -1,335 +1,335 @@
<?php
final class PhabricatorMetaMTAConfigOptions
extends PhabricatorApplicationConfigOptions {
public function getName() {
return pht('Mail');
}
public function getDescription() {
return pht('Configure Mail.');
}
public function getIcon() {
return 'fa-send';
}
public function getGroup() {
return 'core';
}
public function getOptions() {
$send_as_user_desc = $this->deformat(pht(<<<EODOC
When a user takes an action which generates an email notification (like
commenting on a Differential revision), Phabricator can either send that mail
"From" the user's email address (like "alincoln@logcabin.com") or "From" the
'%s' address.
The user experience is generally better if Phabricator uses the user's real
address as the "From" since the messages are easier to organize when they appear
in mail clients, but this will only work if the server is authorized to send
email on behalf of the "From" domain. Practically, this means:
- If you are doing an install for Example Corp and all the users will have
corporate @corp.example.com addresses and any hosts Phabricator is running
on are authorized to send email from corp.example.com, you can enable this
to make the user experience a little better.
- If you are doing an install for an open source project and your users will
be registering via Facebook and using personal email addresses, you probably
should not enable this or all of your outgoing email might vanish into SFP
blackholes.
- If your install is anything else, you're safer leaving this off, at least
initially, since the risk in turning it on is that your outgoing mail will
never arrive.
EODOC
,
'metamta.default-address'));
$one_mail_per_recipient_desc = $this->deformat(pht(<<<EODOC
When a message is sent to multiple recipients (for example, several reviewers on
a code review), Phabricator can either deliver one email to everyone (e.g., "To:
alincoln, usgrant, htaft") or separate emails to each user (e.g., "To:
alincoln", "To: usgrant", "To: htaft"). The major advantages and disadvantages
of each approach are:
- One mail to everyone:
- This violates policy controls. The body of the mail is generated without
respect for object policies.
- Recipients can see To/Cc at a glance.
- If you use mailing lists, you won't get duplicate mail if you're
a normal recipient and also Cc'd on a mailing list.
- Getting threading to work properly is harder, and probably requires
making mail less useful by turning off options.
- Sometimes people will "Reply All", which can send mail to too many
recipients. Phabricator will try not to send mail to users who already
received a similar message, but can not prevent all stray email arising
from "Reply All".
- Not supported with a private reply-to address.
- Mails are sent in the server default translation.
- One mail to each user:
- Policy controls work correctly and are enforced per-user.
- Recipients need to look in the mail body to see To/Cc.
- If you use mailing lists, recipients may sometimes get duplicate
mail.
- Getting threading to work properly is easier, and threading settings
can be customzied by each user.
- "Reply All" will never send extra mail to other users involved in the
thread.
- Required if private reply-to addresses are configured.
- Mails are sent in the language of user preference.
EODOC
));
$herald_hints_description = $this->deformat(pht(<<<EODOC
You can disable the Herald hints in email if users prefer smaller messages.
These are the links under the header "WHY DID I GET THIS EMAIL?". If you set
this to `false`, they will not appear in any mail. Users can still navigate to
the links via the web interface.
EODOC
));
$reply_hints_description = $this->deformat(pht(<<<EODOC
You can disable the hints under "REPLY HANDLER ACTIONS" if users prefer
smaller messages. The actions themselves will still work properly.
EODOC
));
$recipient_hints_description = $this->deformat(pht(<<<EODOC
You can disable the "To:" and "Cc:" footers in mail if users prefer smaller
messages.
EODOC
));
$email_preferences_description = $this->deformat(pht(<<<EODOC
You can disable the email preference link in emails if users prefer smaller
emails.
EODOC
));
$re_prefix_description = $this->deformat(pht(<<<EODOC
Mail.app on OS X Lion won't respect threading headers unless the subject is
prefixed with "Re:". If you enable this option, Phabricator will add "Re:" to
the subject line of all mail which is expected to thread. If you've set
'metamta.one-mail-per-recipient', users can override this setting in their
preferences.
EODOC
));
$vary_subjects_description = $this->deformat(pht(<<<EODOC
If true, allow MetaMTA to change mail subjects to put text like '[Accepted]' and
'[Commented]' in them. This makes subjects more useful, but might break
threading on some clients. If you've set '%s', users can override this setting
in their preferences.
EODOC
,
'metamta.one-mail-per-recipient'));
$reply_to_description = $this->deformat(pht(<<<EODOC
If you enable `%s`, Phabricator uses "From" to authenticate users. You can
additionally enable this setting to try to authenticate with 'Reply-To'. Note
that this is completely spoofable and insecure (any user can set any 'Reply-To'
address) but depending on the nature of your install or other deliverability
conditions this might be okay. Generally, you can't do much more by spoofing
Reply-To than be annoying (you can write but not read content). But this is
still **COMPLETELY INSECURE**.
EODOC
,
'metamta.public-replies'));
$adapter_description = $this->deformat(pht(<<<EODOC
Adapter class to use to transmit mail to the MTA. The default uses
PHPMailerLite, which will invoke "sendmail". This is appropriate if sendmail
actually works on your host, but if you haven't configured mail it may not be so
great. A number of other mailers are available (e.g., SES, SendGrid, SMTP,
custom mailers). This option is deprecated in favor of 'cluster.mailers'.
EODOC
));
$placeholder_description = $this->deformat(pht(<<<EODOC
When sending a message that has no To recipient (i.e. all recipients are CC'd),
set the To field to the following value. If no value is set, messages with no
To will have their CCs upgraded to To.
EODOC
));
$public_replies_description = $this->deformat(pht(<<<EODOC
By default, Phabricator generates unique reply-to addresses and sends a separate
email to each recipient when you enable reply handling. This is more secure than
using "From" to establish user identity, but can mean users may receive multiple
emails when they are on mailing lists. Instead, you can use a single, non-unique
reply to address and authenticate users based on the "From" address by setting
this to 'true'. This trades away a little bit of security for convenience, but
it's reasonable in many installs. Object interactions are still protected using
hashes in the single public email address, so objects can not be replied to
blindly.
EODOC
));
$single_description = $this->deformat(pht(<<<EODOC
If you want to use a single mailbox for Phabricator reply mail, you can use this
and set a common prefix for reply addresses generated by Phabricator. It will
make use of the fact that a mail-address such as
`phabricator+D123+1hjk213h@example.com` will be delivered to the `phabricator`
user's mailbox. Set this to the left part of the email address and it will be
prepended to all generated reply addresses.
For example, if you want to use `phabricator@example.com`, this should be set
to `phabricator`.
EODOC
));
$address_description = $this->deformat(pht(<<<EODOC
When email is sent, what format should Phabricator use for user's email
addresses? Valid values are:
- `short`: 'gwashington <gwashington@example.com>'
- `real`: 'George Washington <gwashington@example.com>'
- `full`: 'gwashington (George Washington) <gwashington@example.com>'
The default is `full`.
EODOC
));
$mailers_description = $this->deformat(pht(<<<EODOC
Define one or more mail transmission services. For help with configuring
mailers, see **[[ %s | %s ]]** in the documentation.
EODOC
,
PhabricatorEnv::getDoclink('Configuring Outbound Email'),
pht('Configuring Outbound Email')));
return array(
$this->newOption('cluster.mailers', 'cluster.mailers', null)
- ->setLocked(true)
+ ->setHidden(true)
->setDescription($mailers_description),
$this->newOption(
'metamta.default-address',
'string',
'noreply@phabricator.example.com')
->setDescription(pht('Default "From" address.')),
$this->newOption(
'metamta.domain',
'string',
'phabricator.example.com')
->setDescription(pht('Domain used to generate Message-IDs.')),
$this->newOption(
'metamta.mail-adapter',
'class',
'PhabricatorMailImplementationPHPMailerLiteAdapter')
->setBaseClass('PhabricatorMailImplementationAdapter')
->setSummary(pht('Control how mail is sent.'))
->setDescription($adapter_description),
$this->newOption(
'metamta.one-mail-per-recipient',
'bool',
true)
->setLocked(true)
->setBoolOptions(
array(
pht('Send Mail To Each Recipient'),
pht('Send Mail To All Recipients'),
))
->setSummary(
pht(
'Controls whether Phabricator sends one email with multiple '.
'recipients in the "To:" line, or multiple emails, each with a '.
'single recipient in the "To:" line.'))
->setDescription($one_mail_per_recipient_desc),
$this->newOption('metamta.can-send-as-user', 'bool', false)
->setBoolOptions(
array(
pht('Send as User Taking Action'),
pht('Send as Phabricator'),
))
->setSummary(
pht(
'Controls whether Phabricator sends email "From" users.'))
->setDescription($send_as_user_desc),
$this->newOption(
'metamta.reply-handler-domain',
'string',
null)
->setLocked(true)
->setDescription(pht('Domain used for reply email addresses.'))
->addExample('phabricator.example.com', ''),
$this->newOption('metamta.herald.show-hints', 'bool', true)
->setBoolOptions(
array(
pht('Show Herald Hints'),
pht('No Herald Hints'),
))
->setSummary(pht('Show hints about Herald rules in email.'))
->setDescription($herald_hints_description),
$this->newOption('metamta.recipients.show-hints', 'bool', true)
->setBoolOptions(
array(
pht('Show Recipient Hints'),
pht('No Recipient Hints'),
))
->setSummary(pht('Show "To:" and "Cc:" footer hints in email.'))
->setDescription($recipient_hints_description),
$this->newOption('metamta.email-preferences', 'bool', true)
->setBoolOptions(
array(
pht('Show Email Preferences Link'),
pht('No Email Preferences Link'),
))
->setSummary(pht('Show email preferences link in email.'))
->setDescription($email_preferences_description),
$this->newOption('metamta.insecure-auth-with-reply-to', 'bool', false)
->setBoolOptions(
array(
pht('Allow Insecure Reply-To Auth'),
pht('Disallow Reply-To Auth'),
))
->setSummary(pht('Trust "Reply-To" headers for authentication.'))
->setDescription($reply_to_description),
$this->newOption('metamta.placeholder-to-recipient', 'string', null)
->setSummary(pht('Placeholder for mail with only CCs.'))
->setDescription($placeholder_description),
$this->newOption('metamta.public-replies', 'bool', false)
->setBoolOptions(
array(
pht('Use Public Replies (Less Secure)'),
pht('Use Private Replies (More Secure)'),
))
->setSummary(
pht(
'Phabricator can use less-secure but mailing list friendly public '.
'reply addresses.'))
->setDescription($public_replies_description),
$this->newOption('metamta.single-reply-handler-prefix', 'string', null)
->setSummary(
pht('Allow Phabricator to use a single mailbox for all replies.'))
->setDescription($single_description),
$this->newOption('metamta.user-address-format', 'enum', 'full')
->setEnumOptions(
array(
'short' => pht('Short'),
'real' => pht('Real'),
'full' => pht('Full'),
))
->setSummary(pht('Control how Phabricator renders user names in mail.'))
->setDescription($address_description)
->addExample('gwashington <gwashington@example.com>', 'short')
->addExample('George Washington <gwashington@example.com>', 'real')
->addExample(
'gwashington (George Washington) <gwashington@example.com>',
'full'),
$this->newOption('metamta.email-body-limit', 'int', 524288)
->setDescription(
pht(
'You can set a limit for the maximum byte size of outbound mail. '.
'Mail which is larger than this limit will be truncated before '.
'being sent. This can be useful if your MTA rejects mail which '.
'exceeds some limit (this is reasonably common). Specify a value '.
'in bytes.'))
->setSummary(pht('Global cap for size of generated emails (bytes).'))
->addExample(524288, pht('Truncate at 512KB'))
->addExample(1048576, pht('Truncate at 1MB')),
);
}
}
diff --git a/src/docs/user/configuration/configuration_locked.diviner b/src/docs/user/configuration/configuration_locked.diviner
index 040b838177..fff0da9bdc 100644
--- a/src/docs/user/configuration/configuration_locked.diviner
+++ b/src/docs/user/configuration/configuration_locked.diviner
@@ -1,101 +1,121 @@
@title Configuration Guide: Locked and Hidden Configuration
@group config
Details about locked and hidden configuration.
Overview
========
Some configuration options are **Locked** or **Hidden**. If an option has one
of these attributes, it means:
- **Locked Configuration**: This setting can not be written from the web UI.
- **Hidden Configuration**: This setting can not be read or written from
the web UI.
This document explains these attributes in more detail.
Locked Configuration
====================
**Locked Configuration** can not be edited from the web UI. In general, you
can edit it from the CLI instead, with `bin/config`:
```
phabricator/ $ ./bin/config set <key> <value>
```
+Some configuration options take complicated values which can be difficult
+to escape properly for the shell. The easiest way to set these options is
+to use the `--stdin` flag. First, put your desired value in a `config.json`
+file:
+
+```name=config.json, lang=json
+{
+ "duck": "quack",
+ "cow": "moo"
+}
+```
+
+Then, set it with `--stdin` like this:
+
+```
+phabricator/ $ ./bin/config set <key> --stdin < config.json
+```
+
A few settings have alternate CLI tools. Refer to the setting page for
details.
Note that these settings can not be written to the database, even from the
CLI.
Locked values can not be unlocked: they are locked because of what the setting
does or how the setting operates. Some of the reasons configuration options are
locked include:
**Required for bootstrapping**: Some options, like `mysql.host`, must be
available before Phabricator can read configuration from the database.
If you stored `mysql.host` only in the database, Phabricator would not know how
to connect to the database in order to read the value in the first place.
These options must be provided in a configuration source which is read earlier
in the bootstrapping process, before Phabricator connects to the database.
**Errors could not be fixed from the web UI**: Some options, like
`phabricator.base-uri`, can effectively disable the web UI if they are
configured incorrectly.
If these options could be configured from the web UI, you could not fix them if
you made a mistake (because the web UI would no longer work, so you could not
load the page to change the value).
We require these options to be edited from the CLI to make sure the editor has
access to fix any mistakes.
**Attackers could gain greater access**: Some options could be modified by an
attacker who has gained access to an administrator account in order to gain
greater access.
For example, an attacker who could modify `metamta.mail-adapter` (and other
similar options), could potentially reconfigure Phabricator to send mail
through an evil server they controlled, then trigger password resets on other
user accounts to compromise them.
We require these options to be edited from the CLI to make sure the editor
has full access to the install.
Hidden Configuration
====================
**Hidden Configuration** is similar to locked configuration, but also can not
be //read// from the web UI.
In almost all cases, configuration is hidden because it is some sort of secret
key or access token for an external service. These values are hidden from the
web UI to prevent administrators (or attackers who have compromised
administrator accounts) from reading them.
You can review (and edit) hidden configuration from the CLI:
```
phabricator/ $ ./bin/config get <key>
phabricator/ $ ./bin/config set <key> <value>
```
Next Steps
==========
Continue by:
+ - learning more about advanced options with
+ @{Configuration User Guide: Advanced Configuration}; or
- returning to the @{article: Configuration Guide}.
diff --git a/src/docs/user/configuration/configuring_outbound_email.diviner b/src/docs/user/configuration/configuring_outbound_email.diviner
index 0c7ef529fa..21abf92736 100644
--- a/src/docs/user/configuration/configuring_outbound_email.diviner
+++ b/src/docs/user/configuration/configuring_outbound_email.diviner
@@ -1,266 +1,300 @@
@title Configuring Outbound Email
@group config
Instructions for configuring Phabricator to send mail.
Overview
========
Phabricator can send outbound email through several different mail services,
including a local mailer or various third-party services. Options include:
| Send Mail With | Setup | Cost | Inbound | Notes |
|---------|-------|------|---------|-------|
| Mailgun | Easy | Cheap | Yes | Recommended |
| Amazon SES | Easy | Cheap | No | Recommended |
| SendGrid | Medium | Cheap | Yes | Discouraged |
| External SMTP | Medium | Varies | No | Gmail, etc. |
| Local SMTP | Hard | Free | No | sendmail, postfix, etc |
| Custom | Hard | Free | No | Write a custom mailer for some other service. |
| Drop in a Hole | Easy | Free | No | Drops mail in a deep, dark hole. |
See below for details on how to select and configure mail delivery for each
mailer.
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 mailer, 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:
- **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`.
- **metamta.can-send-as-user** should be left as `false` in most cases,
but see the documentation for details.
Configuring Mailers
===================
Configure one or more mailers by listing them in the the `cluster.mailers`
configuration option. Most installs only need to configure one mailer, but you
can configure multiple mailers to provide greater availability in the event of
a service disruption.
A valid `cluster.mailers` configuration looks something like this:
```lang=json
[
{
"key": "mycompany-mailgun",
"type": "mailgun",
"options": {
"domain": "mycompany.com",
"api-key": "..."
}
},
...
]
```
The supported keys for each mailer are:
- `key`: Required string. A unique name for this mailer.
- `type`: Required string. Identifies the type of mailer. See below for
options.
- `priority`: Optional string. Advanced option which controls load balancing
and failover behavior. See below for details.
- `options`: Optional map. Additional options for the mailer type.
The `type` field can be used to select these third-party mailers:
- `mailgun`: Use Mailgun.
- `ses`: Use Amazon SES.
- `sendgrid`: Use Sendgrid.
It also supports these local mailers:
- `sendmail`: Use the local `sendmail` binary.
- `smtp`: Connect directly to an SMTP server.
- `test`: Internal mailer for testing. Does not send mail.
You can also write your own mailer by extending
`PhabricatorMailImplementationAdapter`.
Once you've selected a mailer, find the corresponding section below for
instructions on configuring it.
+Setting Complex Configuration
+=============================
+
+Mailers can not be edited from the web UI. If mailers could be edited from
+the web UI, it would give an attacker who compromised an administrator account
+a lot of power: they could redirect mail to a server they control and then
+intercept mail for any other account, including password reset mail.
+
+For more information about locked configuration options, see
+@{article:Configuration Guide: Locked and Hidden Configuration}.
+
+Setting `cluster.mailers` from the command line using `bin/config set` can be
+tricky because of shell escaping. The easiest way to do it is to use the
+`--stdin` flag. First, put your desired configuration in a file like this:
+
+```lang=json, name=mailers.json
+[
+ {
+ "key": "test-mailer",
+ "type": "test"
+ }
+]
+```
+
+Then set the value like this:
+
+```
+phabricator/ $ ./bin/config set --stdin < mailers.json
+```
+
+For alternatives and more information on configuration, see
+@{article:Configuration User Guide: Advanced Configuration}
+
+
Mailer: Mailgun
===============
Mailgun is a third-party email delivery service. You can learn more at
<http://www.mailgun.com>. Mailgun is easy to configure and works well.
To use this mailer, set `type` to `mailgun`, then configure these `options`:
- `api-key`: Required string. Your Mailgun API key.
- `domain`: Required string. Your Mailgun domain.
Mailer: Amazon SES
==================
Amazon SES is Amazon's cloud email service. You can learn more at
<http://aws.amazon.com/ses/>.
To use this mailer, set `type` to `ses`, then configure these `options`:
- `access-key`: Required string. Your Amazon SES access key.
- `secret-key`: Required string. Your Amazon SES secret key.
- `endpoint`: Required string. Your Amazon SES endpoint.
NOTE: Amazon SES **requires you to verify your "From" address**. Configure
which "From" address to use by setting "`metamta.default-address`" in your
config, then follow the Amazon SES verification process to verify it. You
won't be able to send email until you do this!
Mailer: SendGrid
================
SendGrid is a third-party email delivery service. You can learn more at
<http://sendgrid.com/>.
You can configure SendGrid in two ways: you can send via SMTP or via the REST
API. To use SMTP, configure Phabricator to use an `smtp` mailer.
To use the REST API mailer, set `type` to `sendgrid`, then configure
these `options`:
- `api-user`: Required string. Your SendGrid login name.
- `api-key`: Required string. Your SendGrid API key.
NOTE: Users have experienced a number of odd issues with SendGrid, compared to
fewer issues with other mailers. We discourage SendGrid unless you're already
using it.
Mailer: Sendmail
================
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.
Since you'll be sending the mail yourself, you are subject to things like SPF
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, strongly consider using Mailgun or Amazon SES instead.
To use this mailer, set `type` to `sendmail`. There are no `options` to
configure.
Mailer: STMP
============
You can use this adapter to send mail via an external SMTP server, like Gmail.
To use this mailer, set `type` to `smtp`, then configure these `options`:
- `host`: Required string. The hostname of your SMTP server.
- `user`: Optional string. Username used for authentication.
- `password`: Optional string. Password for authentication.
- `protocol`: Optional string. Set to `tls` or `ssl` if necessary. Use
`ssl` for Gmail.
Disable Mail
============
To disable mail, just don't configure any mailers.
Testing and Debugging Outbound Email
====================================
You can use the `bin/mail` utility to test, debug, and examine outbound mail. In
particular:
phabricator/ $ ./bin/mail list-outbound # List outbound mail.
phabricator/ $ ./bin/mail show-outbound # Show details about messages.
phabricator/ $ ./bin/mail send-test # Send test messages.
Run `bin/mail help <command>` for more help on using these commands.
You can monitor daemons using the Daemon Console (`/daemon/`, or click
**Daemon Console** from the homepage).
Priorities
==========
By default, Phabricator will try each mailer in order: it will try the first
mailer first. If that fails (for example, because the service is not available
at the moment) it will try the second mailer, and so on.
If you want to load balance between multiple mailers instead of using one as
a primary, you can set `priority`. Phabricator will start with mailers in the
highest priority group and go through them randomly, then fall back to the
next group.
For example, if you have two SMTP servers and you want to balance requests
between them and then fall back to Mailgun if both fail, configure priorities
like this:
```lang=json
[
{
"key": "smtp-uswest",
"type": "smtp",
"priority": 300,
"options": "..."
},
{
"key": "smtp-useast",
"type": "smtp",
"priority": 300,
"options": "..."
},
{
"key": "mailgun-fallback",
"type": "mailgun",
"options": "..."
}
}
```
Phabricator will start with servers in the highest priority group (the group
with the **largest** `priority` number). In this example, the highest group is
`300`, which has the two SMTP servers. They'll be tried in random order first.
If both fail, Phabricator will move on to the next priority group. In this
example, there are no other priority groups.
If it still hasn't sent the mail, Phabricator will try servers which are not
in any priority group, in the configured order. In this example there is
only one such server, so it will try to send via Mailgun.
Next Steps
==========
Continue by:
- @{article:Configuring Inbound Email} so users can reply to email they
receive about revisions and tasks to interact with them; or
- learning about daemons with @{article:Managing Daemons with phd}; or
- returning to the @{article:Configuration Guide}.

File Metadata

Mime Type
text/x-diff
Expires
Jan 19 2025, 21:57 (6 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1129167
Default Alt Text
(33 KB)

Event Timeline