Organize, update, and improve some documentation.
This commit is contained in:
204
src/docs/configuration/configuring_inbound_email.diviner
Normal file
204
src/docs/configuration/configuring_inbound_email.diviner
Normal file
@@ -0,0 +1,204 @@
|
||||
@title Configuring Inbound Email
|
||||
@group config
|
||||
|
||||
This document contains instructions for configuring inbound email, so users
|
||||
may update Differential and Maniphest by replying to messages.
|
||||
|
||||
= Preamble =
|
||||
|
||||
This can be extremely difficult to configure correctly. This is doubly true if
|
||||
you use sendmail.
|
||||
|
||||
There are basically 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.
|
||||
|
||||
= Configuring Phabricator =
|
||||
|
||||
By default, Phabricator uses a "noreply@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 in Phabricator and users
|
||||
will not be able to take actions like claiming tasks or requesting changes to
|
||||
revisions.
|
||||
|
||||
To change this behavior so that users can interact with objects in Phabricator
|
||||
over email, set these configuration keys:
|
||||
|
||||
- ##metamta.differential.reply-handler-domain##: enables email replies for
|
||||
Differential.
|
||||
- ##metamta.maniphest.reply-handler-domain##: enables email replies for
|
||||
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
|
||||
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
|
||||
configured correctly, according to the instructions below -- will parse incoming
|
||||
email and allow users to interact with Maniphest tasks and Differential
|
||||
revisions over email.
|
||||
|
||||
= Security =
|
||||
|
||||
The email reply channel is "somewhat" authenticated. Each reply-to address is
|
||||
unique to the recipient and includes a hash of user information and a unique
|
||||
object ID, so it can only be used to update that object and only be used to act
|
||||
on behalf of the recipient.
|
||||
|
||||
However, if an address is leaked (which is fairly easy -- for instance,
|
||||
forwarding an email will leak a live reply address, or a user might take a
|
||||
screenshot), //anyone// who can send mail to your reply-to domain may interact
|
||||
with the object the email relates to as the user who leaked the mail. Because
|
||||
the authentication around email has this weakness, some actions (like accepting
|
||||
revisions) are not permitted over email.
|
||||
|
||||
This implementation is an attempt to balance utility and security, but makes
|
||||
some sacrifices on both sides to achieve it because of the difficulty of
|
||||
authenticating senders in the general case (e.g., where you are an open source
|
||||
project and need to interact with users whose email accounts you have no control
|
||||
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.
|
||||
|
||||
NOTE: Phabricator does not currently attempt to verify "From" addresses because
|
||||
this is technically complex, seems unreasonably difficult in the general case,
|
||||
and no installs have had a need for it yet. If you have a specific case where a
|
||||
reasonable mechanism exists to provide sender verification (e.g., DKIM
|
||||
signatures are sufficient to authenticate the sender under your configuration,
|
||||
or you are willing to require all users to sign their email), file a feature
|
||||
request.
|
||||
|
||||
= Testing =
|
||||
|
||||
You can view a log of received mail by going to MetaMTA -> Received in the
|
||||
Phabricator web interface. This can help you determine if mail is being
|
||||
delivered to Phabricator or not.
|
||||
|
||||
You can also use the "Test Receiver" button, but note that this just simulates
|
||||
receiving mail and doesn't send any information over the network. It is
|
||||
primarily aimed at developing email handlers: it will still work properly
|
||||
if your inbound email configuration is incorrect or even disabled.
|
||||
|
||||
= SendGrid =
|
||||
|
||||
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:
|
||||
|
||||
- Configure an MX record according to SendGrid's instructions, i.e. add
|
||||
##phabricator.example.com MX 10 mx.sendgrid.net.## or similar.
|
||||
- Go to the "Parse Incoming Emails" page on SendGrid
|
||||
(<http://sendgrid.com/developer/reply>) and add the domain as the
|
||||
"Hostname".
|
||||
- Add the URL ##https://phabricator.example.com/mail/sendgrid/## as the "Url",
|
||||
using your domain (and HTTP instead of HTTPS if you are not configured with
|
||||
SSL).
|
||||
- If you get an error that the hostname "can't be located or verified", it
|
||||
means your MX record is either incorrectly configured or hasn't propagated
|
||||
yet.
|
||||
- Set ##metamta.maniphest.reply-handler-domain## and/or
|
||||
##metamta.differential.reply-handler-domain## to
|
||||
"##phabricator.example.com##" (whatever you configured the MX record for),
|
||||
depending on whether you want to support email replies for Maniphest,
|
||||
Differential, or both.
|
||||
|
||||
That's it! If everything is working properly you should be able to send email
|
||||
to ##anything@phabricator.example.com## and it should appear in the "Received"
|
||||
tab of MetaMTA within a few seconds.
|
||||
|
||||
= 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:
|
||||
|
||||
$ sudo pecl install mailparse
|
||||
|
||||
You may run into an error like "needs mbstring". If so, try:
|
||||
|
||||
$ sudo yum install php-mbstring # or equivalent
|
||||
$ sudo pecl install -n mailparse
|
||||
|
||||
If you get a linker error like this:
|
||||
|
||||
COUNTEREXAMPLE
|
||||
PHP Warning: PHP Startup: Unable to load dynamic library
|
||||
'/usr/lib64/php/modules/mailparse.so' - /usr/lib64/php/modules/mailparse.so:
|
||||
undefined symbol: mbfl_name2no_encoding in Unknown on line 0
|
||||
|
||||
...you need to edit your php.ini file so that mbstring.so is loaded **before**
|
||||
mailparse.so. This is not the default if you have individual files in
|
||||
##php.d/##.
|
||||
|
||||
= MTA: Configuring Sendmail =
|
||||
|
||||
Before you can configure Sendmail, you need to install Mailparse. See the
|
||||
section "Installing Mailparse" above.
|
||||
|
||||
Sendmail is very difficult to configure. First, you need to configure it for
|
||||
your domain so that mail can be delivered correctly. In broad strokes, this
|
||||
probably means something like this:
|
||||
|
||||
- add an MX record;
|
||||
- make sendmail listen on external interfaces;
|
||||
- open up port 25 if necessary (e.g., in your EC2 security policy);
|
||||
- add your host to /etc/mail/local-host-names; and
|
||||
- restart sendmail.
|
||||
|
||||
Now, you can actually configure sendmail to deliver to Phabricator. In
|
||||
##/etc/aliases##, add an entry like this:
|
||||
|
||||
phabricator: "| /path/to/phabricator/scripts/mail/mail_handler.php <ENV>"
|
||||
|
||||
...where <ENV> is the PHABRICATOR_ENV the script should run under. Run
|
||||
##sudo newaliases##. Now you likely need to symlink this script into
|
||||
##/etc/smrsh/##:
|
||||
|
||||
sudo ln -s /path/to/phabricator/scripts/mail/mail_handler.php /etc/smrsh/
|
||||
|
||||
Finally, edit ##/etc/mail/virtusertable## and add an entry like this:
|
||||
|
||||
@yourdomain.com phabricator@localhost
|
||||
|
||||
That will forward all mail to @yourdomain.com to the Phabricator processing
|
||||
script. Run ##sudo /etc/mail/make## or similar and then restart sendmail with
|
||||
##sudo /etc/init.d/sendmail restart##.
|
||||
|
||||
= MTA: Configuring Lamson =
|
||||
|
||||
Before you can configure Lamson, you need to install Mailparse. See the section
|
||||
"Installing Mailparse" above.
|
||||
|
||||
In contrast to Sendmail, Lamson is relatively easy to configure. It is fairly
|
||||
minimal, and is suitable for a development or testing environment. Lamson
|
||||
listens for incoming SMTP mails and passes the content directly to Phabricator.
|
||||
|
||||
To get started, follow the provided instructions
|
||||
(<http://lamsonproject.org/docs/getting_started.html>) to set up an instance.
|
||||
One likely deployment issue is that binding to port 25 requires root
|
||||
privileges. Lamson is capable of starting as root then dropping privileges, but
|
||||
you must supply ##-uid## and ##-gid## arguments to do so, as demonstrated by
|
||||
Step 8 in Lamson's deployment tutorial (located here:
|
||||
<http://lamsonproject.org/docs/deploying_oneshotblog.html>).
|
||||
|
||||
The Lamson handler code itself is very concise; it merely needs to pass the
|
||||
content of the email to Phabricator:
|
||||
|
||||
import logging, subprocess
|
||||
from lamson.routing import route, stateless
|
||||
from lamson import view
|
||||
|
||||
PHABRICATOR_ROOT = "/path/to/phabricator"
|
||||
PHABRICATOR_ENV = "custom/myconf"
|
||||
LOGGING_ENABLED = True
|
||||
|
||||
@route("(address)@(host)", address=".+")
|
||||
@stateless
|
||||
def START(message, address=None, host=None):
|
||||
if LOGGING_ENABLED:
|
||||
logging.debug("%s", message.original)
|
||||
process = subprocess.Popen([PHABRICATOR_ROOT + "scripts/mail/mail_handler.php",PHABRICATOR_ENV],stdin=subprocess.PIPE)
|
||||
process.communicate(message.original)
|
||||
Reference in New Issue
Block a user