How to start receiving inbound email

_images/mx.png

Add Receiving MX Records

Your domain needs Mailgun MX records to handle inbound messages. Open up your DNS provider and add these. MX Information

Type Value Purpose
MX mxa.mailgun.org Receiving (Optional)
MX mxb.mailgun.org Receiving (Optional)

Warning

Do not configure Receiving MX DNS records if you already have another provider handling inbound mail delivery for your domain (e.g. Gmail). Instead we recommend using a subdomain on Mailgun (e.g. mg.yourdomain.com)

Inbound Routes and Parsing

You can define a list of routes to handle incoming emails and prioritize the sequence of their execution.

  • Each route consists of a filter expression and an action.
  • When a message is received, Mailgun evaluates the filter expression against it.
  • If the expression is true, the action is executed.

Regular expressions can be used to match against message recipients or arbitrary headers such as subject.

Examples of filter expressions for routes

Expression Description
match_recipient(“bob@myapp.com”) Returns true if the incoming message is going to bob@myapp.com.
match_recipient(”.*@myapp.com”) Returns true if the incoming message is going to any user at @myapp.com.
match_header(“subject”, “hello”) Returns true if the subject of the message contains word ‘hello’.
catch_all() Returns true if no other route matched, to implement catch-all behaviour.

Supported actions for routes

Action Description
forward(“http://myapp/post”) Parses the message and forwards it to a given URL.
forward(“support@myapp.com”) Forwards the message to a given email address.
store(notify=”http://myapp/post”) Stores the message temporarily to be retrieved later.
stop() Stops and doesn’t look at any other routes.

Routes can be defined and tested using the Mailgun API (in addition, to using the Control Panel).

curl -s --user 'api:YOUR_API_KEY' \
    https://api.mailgun.net/v3/routes \
    -F priority=0 \
    -F description='Sample route' \
    -F expression='match_recipient(".*@YOUR_DOMAIN_NAME")' \
    -F action='forward("http://myhost.com/messages/")' \
    -F action='stop()'
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;

public class MGSample {

    // ...

    public static JsonNode createRoute() throws UnirestException {

        HttpResponse <JsonNode> request = Unirest.post("https://api.mailgun.net/v3/routes")
            .basicAuth("api", API_KEY)
            .field("priority", "0")
            .field("description", "sample route")
            .field("expression", "match_recipient('.*@YOUR_DOMAIN_NAME')")
            .field("action", "forward('http://myhost.com/messages/')")
            .field("action", "stop()")
            .asJson();

        return request.getBody();
    }
}
# Include the Autoloader (see "Libraries" for install instructions)
require 'vendor/autoload.php';
use Mailgun\Mailgun;

# Instantiate the client.
$mgClient = new Mailgun('YOUR_API_KEY');

# Issue the call to the client.
$result = $mgClient->post("routes", array(
    'priority'    => 0,
    'expression'  => 'match_recipient(".*@YOUR_DOMAIN_NAME")',
    'action'      => array('forward("http://host.com/messages")', 'stop()'),
    'description' => 'Sample route'
));
def create_route():
    return requests.post(
        "https://api.mailgun.net/v3/routes",
        auth=("api", "YOUR_API_KEY"),
        data={"priority": 0,
              "description": "Sample route",
              "expression": "match_recipient('.*@YOUR_DOMAIN_NAME')",
              "action": ["forward('http://myhost.com/messages/')", "stop()"]})
def create_route
  data = {}
  data[:priority] = 0
  data[:description] = "Sample route"
  data[:expression] = "match_recipient('.*@YOUR_DOMAIN_NAME')"
  data[:action] = []
  data[:action] << "forward('http://myhost.com/messages/')"
  data[:action] << "stop()"
  RestClient.post "https://api:YOUR_API_KEY"\
  "@api.mailgun.net/v3/routes", data
end
using System;
using System.IO;
using RestSharp;
using RestSharp.Authenticators;

public class CreateRouteChunk
{

    public static void Main (string[] args)
    {
        Console.WriteLine (CreateRoute ().Content.ToString ());
    }

    public static IRestResponse CreateRoute ()
    {
        RestClient client = new RestClient ();
        client.BaseUrl = new Uri ("https://api.mailgun.net/v3");
        client.Authenticator =
            new HttpBasicAuthenticator ("api",
                                        "YOUR_API_KEY");
        RestRequest request = new RestRequest ();
        request.Resource = "routes";
        request.AddParameter ("priority", 0);
        request.AddParameter ("description", "Sample route");
        request.AddParameter ("expression", "match_recipient('.*@YOUR_DOMAIN_NAME')");
        request.AddParameter ("action",
                              "forward('http://myhost.com/messages/')");
        request.AddParameter ("action", "stop()");
        request.Method = Method.POST;
        return client.Execute (request);
    }

}
func CreateRoute(domain, apiKey string) (mailgun.Route, error) {
  mg := mailgun.NewMailgun(domain, apiKey, "")
  return mg.CreateRoute(mailgun.Route{
    Priority:    1,
    Description: "Sample Route",
    Expression:  "match_recipient(\".*@YOUR_DOMAIN_NAME\")",
    Actions: []string{
      "forward(\"http://example.com/messages/\")",
      "stop()",
    },
  })
}

.. code-block:: js

var DOMAIN = 'YOUR_DOMAIN_NAME';
var mailgun = require('mailgun-js')({ apiKey: "YOUR_API_KEY", domain: DOMAIN });

mailgun.post('/routes', {"priority": 0, "description": 'Sample route', "expression": 'match_recipient(".*@YOUR_DOMAIN_NAME")', "action": 'forward("http://myhost.com/messages/")', "action": 'stop()'}, function (error, body) {
  console.log(body);
});

The example above defines a new route which will forward all messages coming to @samples.mailgun.org to http://myhost.com/messages and will stop evaluating any other routes.

Now let’s look at how to build HTTP handlers for incoming messages, i.e. what needs to be done on your end to handle a message that Mailgun forwards to your URL.

Consider this Django code:

# Handler for HTTP POST to http://myhost.com/messages for the route defined above
def on_incoming_message(request):
     if request.method == 'POST':
         sender    = request.POST.get('sender')
         recipient = request.POST.get('recipient')
         subject   = request.POST.get('subject', '')

         body_plain = request.POST.get('body-plain', '')
         body_without_quotes = request.POST.get('stripped-text', '')
         # note: other MIME headers are also posted here...

         # attachments:
         for key in request.FILES:
             file = request.FILES[key]
             # do something with the file

     # Returned text is ignored but HTTP status code matters:
     # Mailgun wants to see 2xx, otherwise it will make another attempt in 5 minutes
     return HttpResponse('OK')

Mailgun routes are very powerful. For example, you can use regular expression captures and refer to captured values in your destination.

To learn more about Routes, check out the Routes section of the User Manual.