2011-05-05 08:09:42 +02:00
|
|
|
@title Configuring Inbound Email
|
|
|
|
@group config
|
|
|
|
|
|
|
|
This document contains instructions for configuring inbound email, so users
|
2011-07-04 18:45:42 +02:00
|
|
|
may update Differential and Maniphest by replying to messages and create
|
|
|
|
Maniphest tasks via email.
|
2011-05-05 08:09:42 +02:00
|
|
|
|
|
|
|
= Preamble =
|
|
|
|
|
2011-05-30 20:07:05 +02:00
|
|
|
This can be extremely difficult to configure correctly. This is doubly true if
|
2011-05-05 08:09:42 +02:00
|
|
|
you use sendmail.
|
|
|
|
|
2011-05-30 20:07:05 +02:00
|
|
|
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.
|
|
|
|
|
2011-08-16 11:31:51 +02:00
|
|
|
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'
|
|
|
|
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".
|
|
|
|
|
2011-07-04 18:45:42 +02:00
|
|
|
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
|
|
|
|
has some mild security implications, see below.
|
|
|
|
|
2011-05-30 20:07:05 +02:00
|
|
|
= 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.
|
|
|
|
|
Allow Phabricator to be configured to use a public Reply-To address
Summary:
We already support this (and Facebook uses it) but it is difficult to configure
and you have to write a bunch of code. Instead, provide a simple flag.
See the documentation changes for details, but when this flag is enabled we send
one email with a reply-to like "D2+public+23hf91fh19fh@phabricator.example.com".
Anyone can reply to this, and we figure out who they are based on their "From"
address instead of a unique hash. This is less secure, but a reasonable tradeoff
in many cases.
This also has the advantage over a naive implementation of at least doing object
hash validation.
@jungejason: I don't think this affects Facebook's implementation but this is an
area where we've had problems in the past, so watch out for it when you deploy.
Also note that you must set "metamta.public-replies" to true since Maniphest now
looks for that key specifically before going into public reply mode; it no
longer just tests for a public reply address being generateable (since it can
always generate one now).
Test Plan:
Swapped my local install in and out of public reply mode and commented on
objects. Got expected email behavior. Replied to public and private email
addresses.
Attacked public addresses by using them when the install was configured to
disallow them and by altering the hash and the from address. All this stuff was
rejected.
Reviewed By: jungejason
Reviewers: moskov, jungejason, tuomaspelkonen, aran
CC: aran, epriestley, moskov, jungejason
Differential Revision: 563
2011-06-30 22:01:35 +02:00
|
|
|
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
|
|
|
|
can act as another user, but increases convenience if you use mailing lists and,
|
|
|
|
practically, is a reasonable setting for many installs. The reply-to address
|
|
|
|
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.
|
|
|
|
|
2011-07-04 18:45:42 +02:00
|
|
|
If you enable ##metamta.maniphest.public-create-email##, that address also uses
|
|
|
|
the weaker "From" authentication mechanism.
|
|
|
|
|
2011-05-30 20:07:05 +02:00
|
|
|
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.
|
|
|
|
|
2011-05-05 08:09:42 +02:00
|
|
|
= Installing Mailparse =
|
|
|
|
|
2011-05-30 20:07:05 +02:00
|
|
|
If you're going to run your own MTA, you need to install the PECL mailparse
|
|
|
|
extension. In theory, you can do that with:
|
2011-05-05 08:09:42 +02:00
|
|
|
|
|
|
|
$ 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/##.
|
|
|
|
|
2011-05-30 20:07:05 +02:00
|
|
|
= MTA: Configuring Sendmail =
|
|
|
|
|
|
|
|
Before you can configure Sendmail, you need to install Mailparse. See the
|
|
|
|
section "Installing Mailparse" above.
|
2011-05-05 08:09:42 +02:00
|
|
|
|
|
|
|
Sendmail is very difficult to configure. First, you need to configure it for
|
2011-05-30 20:07:05 +02:00
|
|
|
your domain so that mail can be delivered correctly. In broad strokes, this
|
2011-05-05 08:09:42 +02:00
|
|
|
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:
|
|
|
|
|
2011-05-06 00:11:36 +02:00
|
|
|
phabricator: "| /path/to/phabricator/scripts/mail/mail_handler.php <ENV>"
|
2011-05-05 08:09:42 +02:00
|
|
|
|
|
|
|
...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
|
2011-05-30 20:07:05 +02:00
|
|
|
##sudo /etc/init.d/sendmail restart##.
|
2011-05-05 08:09:42 +02:00
|
|
|
|
2011-06-14 05:26:21 +02:00
|
|
|
= 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
|
Allow Phabricator to be configured to use a public Reply-To address
Summary:
We already support this (and Facebook uses it) but it is difficult to configure
and you have to write a bunch of code. Instead, provide a simple flag.
See the documentation changes for details, but when this flag is enabled we send
one email with a reply-to like "D2+public+23hf91fh19fh@phabricator.example.com".
Anyone can reply to this, and we figure out who they are based on their "From"
address instead of a unique hash. This is less secure, but a reasonable tradeoff
in many cases.
This also has the advantage over a naive implementation of at least doing object
hash validation.
@jungejason: I don't think this affects Facebook's implementation but this is an
area where we've had problems in the past, so watch out for it when you deploy.
Also note that you must set "metamta.public-replies" to true since Maniphest now
looks for that key specifically before going into public reply mode; it no
longer just tests for a public reply address being generateable (since it can
always generate one now).
Test Plan:
Swapped my local install in and out of public reply mode and commented on
objects. Got expected email behavior. Replied to public and private email
addresses.
Attacked public addresses by using them when the install was configured to
disallow them and by altering the hash and the from address. All this stuff was
rejected.
Reviewed By: jungejason
Reviewers: moskov, jungejason, tuomaspelkonen, aran
CC: aran, epriestley, moskov, jungejason
Differential Revision: 563
2011-06-30 22:01:35 +02:00
|
|
|
|
2011-06-14 05:26:21 +02:00
|
|
|
PHABRICATOR_ROOT = "/path/to/phabricator"
|
|
|
|
PHABRICATOR_ENV = "custom/myconf"
|
|
|
|
LOGGING_ENABLED = True
|
Allow Phabricator to be configured to use a public Reply-To address
Summary:
We already support this (and Facebook uses it) but it is difficult to configure
and you have to write a bunch of code. Instead, provide a simple flag.
See the documentation changes for details, but when this flag is enabled we send
one email with a reply-to like "D2+public+23hf91fh19fh@phabricator.example.com".
Anyone can reply to this, and we figure out who they are based on their "From"
address instead of a unique hash. This is less secure, but a reasonable tradeoff
in many cases.
This also has the advantage over a naive implementation of at least doing object
hash validation.
@jungejason: I don't think this affects Facebook's implementation but this is an
area where we've had problems in the past, so watch out for it when you deploy.
Also note that you must set "metamta.public-replies" to true since Maniphest now
looks for that key specifically before going into public reply mode; it no
longer just tests for a public reply address being generateable (since it can
always generate one now).
Test Plan:
Swapped my local install in and out of public reply mode and commented on
objects. Got expected email behavior. Replied to public and private email
addresses.
Attacked public addresses by using them when the install was configured to
disallow them and by altering the hash and the from address. All this stuff was
rejected.
Reviewed By: jungejason
Reviewers: moskov, jungejason, tuomaspelkonen, aran
CC: aran, epriestley, moskov, jungejason
Differential Revision: 563
2011-06-30 22:01:35 +02:00
|
|
|
|
2011-06-14 05:26:21 +02:00
|
|
|
@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)
|