Quickstart Guide

Quickstart Guide

Authentication

Mailgun uses HTTP Basic Auth for API authentication. Use api as the user name and your API key is the password. You can manage your API key in the ‘My Account’ tab of the Control Panel.

For example:

curl --user api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0

Sending Messages

You can send messages via SMTP or via Mailgun HTTP API.

Sending Emails via SMTP

All mainstream programming languages have SMTP support. The examples below assume you have already assembed a proper MIME body of your message.

Send an email using Python standard SMTP library:

def send_message_via_smtp():
    smtp = SMTP("smtp.mailgun.org", 587)
    smtp.login(login, password)
    smtp.sendmail("sender@host", "recipient@host", mime_message_body)
    smtp.quit()

Using Ruby on Rails Action Mailer configuration:

config.action_mailer.delivery_method = :smtp
config.action_mailer.default_charset = "utf-8"
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.smtp_settings = {
     :authentication => :plain,
     :address => "smtp.mailgun.org",
     :port => 587,
     :domain => "my-mailgun-domain.com",
     :user_name => "postmaster@my-mailgun-domain.com",
     :password => "my-password"
}

Note

Your SMTP login and password can be found by clicking on your domain in the Domains tab of your Control Panel.

Warning

Avoid sending your SMTP password unencrypted: make sure to use SSL or STARTTLS SMTP facilities available for your framework/language.

Sending Messages using Mailgun HTTP API

This method is preferred because it doesn’t require any prior knowledge of email-specific protocols and data formats like MIME. It is also much faster and guarantees that your messages will be properly formatted.

The HTTP API uses familiar terms like from, to, cc, bcc, subject, body, attachments and so on. The API is RESTful so sending is as easy as making an HTTP POST request to Mailgun.

def post_simple_message
  RestClient.post "https://api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0"\
  "@api.mailgun.net/v2/samples.mailgun.org/messages",
  :from => "Excited User <me@samples.mailgun.org>",
  :to => "sergeyo@profista.com, serobnic@mail.ru",
  :subject => "Hello",
  :text => "Testing some Mailgun awesomness!"
end
public static ClientResponse PostMessage() {
       Client client = Client.create();
       client.addFilter(new HTTPBasicAuthFilter("api",
                       "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"));
       WebResource webResource =
               client.resource("https://api.mailgun.net/v2/samples.mailgun.org" +
                               "/messages");
       MultivaluedMapImpl formData = new MultivaluedMapImpl();
       formData.add("from", "Excited User <me@samples.mailgun.org>");
       formData.add("to", "sergeyo@profista.com");
       formData.add("to", "serobnic@mail.ru");
       formData.add("subject", "Hello");
       formData.add("text", "Testing some Mailgun awesomness!");
       return webResource.type(MediaType.APPLICATION_FORM_URLENCODED).
               post(ClientResponse.class, formData);
}
function post_simple_message() {
  $request =
    new HttpRequest('https://api.mailgun.net/v2/samples.mailgun.org/messages',
                    HttpRequest::METH_POST);
  $auth = base64_encode('api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0');
  $request->setHeaders(array('Authorization' => 'Basic '.$auth));
  $request
    ->setPostFields(array('from' => 'Excited User'.
                          ' <Excited User <me@samples.mailgun.org>>',
                          'to' => 'sergeyo@profista.com, serobnic@mail.ru',
                          'subject' => 'Hello',
                          'text' => 'Testing some Mailgun awesomness!'
                          ));
  $request->send();
  return $request;
}
def post_message():
    r = requests.\
        post(("https://api.mailgun.net/v2/samples.mailgun.org/"
              "messages"),
             auth=("api", "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"),
             data={
                 "from": "Excited User <me@samples.mailgun.org>",
                 "to": ["sergeyo@profista.com",
                        "serobnic@mail.ru"],
                 "subject": "Hello",
                 "text": "Testing some Mailgun awesomness!"
                 }
             )
    return r
public static RestResponse PostMessage() {

       RestClient client = new RestClient();
       client.BaseUrl = "https://api.mailgun.net/v2";
       client.Authenticator =
               new HttpBasicAuthenticator("api",
                                          "key-3ax6xnjp29jd6fds4gc373sgvjxteol0");
       RestRequest request = new RestRequest();
       request.AddParameter("domain",
                            "samples.mailgun.org", ParameterType.UrlSegment);
       request.Resource = "{domain}/messages";
       request.AddParameter("from", "Excited User <me@samples.mailgun.org>");
       request.AddParameter("to", "sergeyo@profista.com");
       request.AddParameter("to", "serobnic@mail.ru");
       request.AddParameter("subject", "Hello");
       request.AddParameter("text", "Testing some Mailgun awesomness!");
       request.Method = Method.POST;
       return client.Execute(request);
}
curl -s -k --user api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0 \
    https://api.mailgun.net/v2/samples.mailgun.org/messages \
    -F from='Excited User <me@samples.mailgun.org>' \
    -F to=serobnic@mail.ru\
    -F to=sergeyo@profista.com \
    -F subject='Hello' \
    -F text='Testing some Mailgun awesomness!'

This will send a simple text message to two recipients. Notice how POST parameters mimic what you would typically see in your email client.

Lets send a more complicated message, with HTML body, two attachments and “cc” and “bcc” recipients:

def post_complex_message
  data = Multimap.new
  data[:from] = "Excited User <me@samples.mailgun.org>"
  data[:to] = "obukhov.sergey.nickolayevich@yandex.ru"
  data[:cc] = "serobnic@mail.ru"
  data[:bcc] = "sergeyo@profista.com"
  data[:subject] = "Hello"
  data[:text] = "Testing some Mailgun awesomness!"
  data[:html] = "<html>HTML version of the body</html>"
  data[:attachment] = File.new(File.join("files", "test.jpg"))
  data[:attachment] = File.new(File.join("files", "test.txt"))
  RestClient.post "https://api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0"\
  "@api.mailgun.net/v2/samples.mailgun.org/messages", data
end
public static ClientResponse PostTextAndHtmlAndFilesWithCcAndBcc() {
       Client client = Client.create();
       client.addFilter(new HTTPBasicAuthFilter("api",
                       "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"));
       WebResource webResource =
               client.resource("https://api.mailgun.net/v2/samples.mailgun.org/" +
                               "messages");
       FormDataMultiPart form = new FormDataMultiPart();
       form.field("from", "Excited User <me@samples.mailgun.org>");
       form.field("to", "obukhov.sergey.nickolayevich@yandex.ru");
       form.field("bcc", "sergeyo@profista.com");
       form.field("cc", "serobnic@mail.ru");
       form.field("subject", "Hello");
       form.field("text", "Testing some Mailgun awesomness!");
       String file_separator = System.getProperty("file.separator");
       File txtFile = new File("." + file_separator +
                       "files" + file_separator + "test.txt");
       form.bodyPart(new FileDataBodyPart("attachment",txtFile,
                       MediaType.TEXT_PLAIN_TYPE));
       File jpgFile = new File("." + file_separator +
                       "files" + file_separator + "test.jpg");
       form.bodyPart(new FileDataBodyPart("attachment",jpgFile,
                       MediaType.APPLICATION_OCTET_STREAM_TYPE));
       return webResource.type(MediaType.MULTIPART_FORM_DATA_TYPE).
               post(ClientResponse.class, form);
}
function post_complex_message() {
  $request =
    new HttpRequest('https://api.mailgun.net/v2/samples.mailgun.org/messages',
                    HttpRequest::METH_POST);
  $auth = base64_encode('api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0');
  $request->setHeaders(array('Authorization' => 'Basic '.$auth));
  $request
    ->setPostFields(array('from' => 'Excited User <me@samples.mailgun.org>',
                          'to' => 'obukhov.sergey.nickolayevich@yandex.ru',
                          'cc' => 'serobnic@mail.ru',
                          'bcc' => 'sergeyo@profista.com',
                          'subject' => 'Hello',
                          'text' => 'Testing some Mailgun awesomness!',
                          'html' => '<html>HTML version of the body</html>'
                          ));
  $request->addPostFile('attachment', 'files/test.txt');
  $request->addPostFile('attachment', 'files/test.jpg');
  $request->send();
  return $request;
}
def post_text_and_html_and_files_with_cc_and_bcc():
    r = requests.\
        post(("https://api.mailgun.net/v2/samples.mailgun.org/"
              "messages"),
             auth=("api", "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"),
             files=MultiDict([
                 ("attachment", open(os.path.join("files",
                                                  "test.jpg"))),
                 ("attachment", open(os.path.join("files",
                                                  "test.txt"))),
                 ]),
             data={
                 "from": "Excited User <me@samples.mailgun.org>",
                 "to": "obukhov.sergey.nickolayevich@yandex.ru",
                 "cc": "serobnic@mail.ru",
                 "bcc": "sergeyo@profista.com",
                 "subject": "Hello",
                 "text": "Testing some Mailgun awesomness!",
                 "html": "<html>HTML version of the body</html>"
                 }
             )
    return r
public static RestResponse PostTextAndHtmlAndFilesWithCcAndBcc() {

       RestClient client = new RestClient();
       client.BaseUrl = "https://api.mailgun.net/v2";
       client.Authenticator =
               new HttpBasicAuthenticator("api",
                                          "key-3ax6xnjp29jd6fds4gc373sgvjxteol0");
       RestRequest request = new RestRequest();
       request.AddParameter("domain",
                            "samples.mailgun.org", ParameterType.UrlSegment);
       request.Resource = "{domain}/messages";
       request.AddParameter("from", "Excited User <me@samples.mailgun.org>");
       request.AddParameter("to", "obukhov.sergey.nickolayevich@yandex.ru");
       request.AddParameter("cc", "serobnic@mail.ru");
       request.AddParameter("bcc", "sergeyo@profista.com");
       request.AddParameter("subject", "Hello");
       request.AddParameter("text", "Testing some Mailgun awesomness!");
       request.AddParameter("html", "<html>HTML version of the body</html>");
       request.AddFile("attachment", Path.Combine("files", "test.jpg"));
       request.AddFile("attachment", Path.Combine("files","test.txt"));
       request.Method = Method.POST;
       return client.Execute(request);
}
curl -s -k --user api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0 \
    https://api.mailgun.net/v2/samples.mailgun.org/messages \
    -F from='Excited User <me@samples.mailgun.org>' \
    -F to='obukhov.sergey.nickolayevich@yandex.ru' \
    -F cc='sergeyo@profista.com' \
    -F bcc='serobnic@mail.ru' \
    -F subject='Hello' \
    -F text='Testing some Mailgun awesomness!' \
    -F html='\<html\>HTML version of the body\<\html>' \
    -F attachment=@files/cartman.jpg' \
    -F attachment=@files/cartman.png'

HTTP allows you to specify multiple pairs of each parameter, hence by repeating “cc” or “to” or “attachment” parameters you specify multiple recipients, attached files and so on.

You can find more information in the Sending Messages section of the User Manual.

Mailing Lists

Mailing Lists provide an easy and convenient way to send to multiple recipients via single call to the API or a single SMTP session. You can create and maintain your Mailing Lists using the API or in the Mailing Lists tab of the Control Panel.

Create a Mailing List:

def create_mailing_list
  RestClient.post("https://api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0" \
                  "@api.mailgun.net/v2/lists",
                  :address => 'dev@samples.mailgun.org',
                  :description => "Mailgun developers list")
end
public static ClientResponse CreateMailingList() {
       Client client = Client.create();
       client.addFilter(new HTTPBasicAuthFilter("api",
                       "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"));
       WebResource webResource =
               client.resource("https://api.mailgun.net/v2/lists");
       MultivaluedMapImpl formData = new MultivaluedMapImpl();
       formData.add("address", "dev@samples.mailgun.org");
       formData.add("description", "Mailgun developers list");
       return webResource.type(MediaType.APPLICATION_FORM_URLENCODED).
               post(ClientResponse.class, formData);

}
function new_mailing_list() {
  $request =
    new HttpRequest("https://api.mailgun.net/v2/lists",
                    HttpRequest::METH_POST);
  $auth = base64_encode('api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0');
  $request->setHeaders(array('Authorization' => 'Basic '.$auth));
  $request->setPostFields(array('address' => 'dev@samples.mailgun.org',
                                'description' => "Mailgun developers list"));
  $request->setOptions(array('connecttimeout' => 15));
  $request->send();
  return $request;
}
def create_mailing_list():
    return requests.post(
        "https://api.mailgun.net/v2/lists",
        auth=('api', 'key-3ax6xnjp29jd6fds4gc373sgvjxteol0'),
        data={'address': 'dev@samples.mailgun.org',
              'description': "Mailgun developers list"})
public static RestResponse CreateMailingList() {

       RestClient client = new RestClient();
       client.BaseUrl = "https://api.mailgun.net/v2";
       client.Authenticator =
               new HttpBasicAuthenticator("api",
                                          "key-3ax6xnjp29jd6fds4gc373sgvjxteol0");
       RestRequest request = new RestRequest();
       request.Resource = "lists";
       request.AddParameter("address", "dev@samples.mailgun.org");
       request.AddParameter("description", "Mailgun developers list");
       request.Method = Method.POST;
       return client.Execute(request);
}
curl -s -k --user api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0 \
    https://api.mailgun.net/v2/lists \
    -F address='dev@samples.mailgun.org' \
    -F description='Sample mailing list'

Add a member to the Mailing List:

def add_member
  RestClient.post("https://api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0" \
                  "@api.mailgun.net/v2/lists/dev@samples.mailgun.org/members",
                  :subscribed => true,
                  :address => 'bob@gmail.com',
                  :name => 'Bob Bar',
                  :description => 'Developer',
                  :vars => '{"age": 26}')
end
public static ClientResponse AddNewMember() {
       Client client = Client.create();
       client.addFilter(new HTTPBasicAuthFilter("api",
                       "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"));
       WebResource webResource =
               client.resource("https://api.mailgun.net/v2/lists/" +
                               "dev@samples.mailgun.org/members");
       MultivaluedMapImpl formData = new MultivaluedMapImpl();
       formData.add("address", "bob@gmail.com");
       formData.add("subscribed", true);
       formData.add("name", "Bob Bar");
       formData.add("description", "Developer");
       formData.add("vars", "{\"age\": 26}");
       return webResource.type(MediaType.APPLICATION_FORM_URLENCODED).
               post(ClientResponse.class, formData);

}
function add_list_member() {
  $request =
    new HttpRequest("https://api.mailgun.net/v2/lists/dev@samples.mailgun.org"
                    ."/members",
                    HttpRequest::METH_POST);
  $auth = base64_encode('api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0');
  $request->setHeaders(array('Authorization' => 'Basic '.$auth));
  $request->setPostFields(array('subscribed' => true,
                                'address' => 'bob@gmail.com',
                                'name' => 'Bob Bar',
                                'description' => "Developer",
                                'vars' => '{"age": 26}'));
  $request->setOptions(array('connecttimeout' => 15));
  $request->send();
  return $request;
}
def add_member():
    return requests.post(
        "https://api.mailgun.net/v2/lists/dev@samples.mailgun.org/members",
        auth=('api', 'key-3ax6xnjp29jd6fds4gc373sgvjxteol0'),
        data={'subscribed': True,
              'address': 'bob@gmail.com',
              'name': 'Bob Bar',
              'description': 'Developer',
              'vars': '{"age": 26}'})
public static RestResponse AddNewMember() {
       RestClient client = new RestClient();
       client.BaseUrl = "https://api.mailgun.net/v2";
       client.Authenticator =
               new HttpBasicAuthenticator("api",
                                          "key-3ax6xnjp29jd6fds4gc373sgvjxteol0");
       RestRequest request = new RestRequest();
       request.Resource = "lists/{list}/members";
       request.AddParameter("list", "dev@samples.mailgun.org", ParameterType.UrlSegment);
       request.AddParameter("address", "bob@gmail.com");
       request.AddParameter("subscribed", true);
       request.AddParameter("name", "Bob Bar");
       request.AddParameter("description", "Developer");
       request.AddParameter("vars", "{\"age\": 26}");
       request.Method = Method.POST;
       return client.Execute(request);
}
curl -s -k --user api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0 \
    https://api.mailgun.net/v2/lists/dev@samples.mailgun.org/members \
    -F subscribed=True \
    -F address='bob@gmail.com' \
    -F name='Bob Bar' \
    -F description='Developer' \
    -F vars='{"age": 26}'

Cheers! Your mailing list is ready to go. Send a message to its address and the message will be copied and sent to each recipient in the list. You can also use template variables to personalize the message.

Note

We will only accept messages to your mailing list if they arrive via API or authenticated (connection using MG username and pass) SMTP sessions. Strangers are not allowed to send messages to your beloved mailing list

You can find more information in the Mailing Lists section of the User Manual.

Receiving and Parsing Email

There are two ways to handle incoming email using Mailgun:

  • Forward incoming messages using Mailgun Routes to a URL in your app or to another email address.
  • Store incoming messages in mailboxes.

Using Routes

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, and 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. Below are some examples of filter expressions:

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:

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.
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).

def create_new_route
  data = Multimap.new
  data[:priority] = 1
  data[:description] = "Sample route"
  data[:expression] = "match_recipient('.*@samples.mailgun.org')"
  data[:action] = "forward('http://myhost.com/messages/')"
  data[:action] = "stop()"
  RestClient.post "https://api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0"\
  "@api.mailgun.net/v2/routes", data
end
public static ClientResponse CreateRoute() {
       Client client = Client.create();
       client.addFilter(new HTTPBasicAuthFilter("api",
                       "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"));
       WebResource webResource =
               client.resource("https://api.mailgun.net/v2/routes");
       MultivaluedMapImpl formData = new MultivaluedMapImpl();
       formData.add("priority", 1);
       formData.add("description", "Sample route");
       formData.add("expression", "match_recipient('.*@samples.mailgun.org')");
       formData.add("action", "forward('http://myhost.com/messages/')");
       formData.add("action", "stop()");
       return webResource.type(MediaType.APPLICATION_FORM_URLENCODED).
               post(ClientResponse.class, formData);
}
function create_new_route() {
  $request =
    new HttpRequest('https://api.mailgun.net/v2/routes',
                    HttpRequest::METH_POST);
  $auth = base64_encode('api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0');
  $request->setHeaders(array('Authorization' => 'Basic '.$auth));
  $data = array(
                'priority' => 1,
                'description' => 'Sample route',
                'expression' => 'match_recipient(".*@samples.mailgun.org")',
                'action' => array('forward("http://myhost.com/messages/")',
                                  'action' => 'stop()')
                );
  $dataString = '';
  foreach ($data as $key => $val) {
    if (is_array($val)) {
      foreach ($val as $v) {
        $dataString .= urlencode($key).'='.urlencode($v).'&';
      }
    } else {
      $dataString .= urlencode($key).'='.urlencode($val).'&';
    }
  }
  $request->setRawPostData(substr($dataString, 0, -1));
  $request->send();
  return $request;
}
def create_route():
    r = requests.\
        post("https://api.mailgun.net/v2/routes",
             auth=("api", "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"),
             data=MultiDict([
                 ("priority", 1),
                 ("description", "Sample route"),
                 ("expression",
                  "match_recipient('.*@samples.mailgun.org')"),
                 ("action",
                  "forward('http://myhost.com/messages/')"),
                 ("action", "stop()")
                 ]))
    return r
public static RestResponse CreateRoute() {

       RestClient client = new RestClient();
       client.BaseUrl = "https://api.mailgun.net/v2";
       client.Authenticator =
               new HttpBasicAuthenticator("api",
                                          "key-3ax6xnjp29jd6fds4gc373sgvjxteol0");
       RestRequest request = new RestRequest();
       request.Resource = "routes";
       request.AddParameter("priority", 1);
       request.AddParameter("description", "Sample route");
       request.AddParameter("expression",
                            "match_recipient('.*@samples.mailgun.org')");
       request.AddParameter("action",
                            "forward('http://myhost.com/messages/')");
       request.AddParameter("action", "stop()");
       request.Method = Method.POST;
       return client.Execute(request);
}
curl -s -k --user api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0 \
    https://api.mailgun.net/v2/routes \
    -F priority=1 \
    -F description='Sample route' \
    -F expression='match_recipient(".*@samples.mailgun.org")' \
    -F action='forward("http://myhost.com/messages/")'\
    -F action='stop()'

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.

Using Mailboxes

With Mailgun you can create as many mailboxes as you want - go nuts and give every page/feature/object in your app its own email address!

Mailboxes support IMAP and POP3 protocols so you can use any email client to fetch messages from them. Go ahead and build your own Gmail on top of Mailgun - you build the UI, we take care of the back end!

Creating Mailboxes and Fetching Email

Here is how you can create a real POP3/IMAP mailbox via an API and start collecting incoming messages in it:

def create_new_mailbox
  RestClient.post "https://api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0"\
  "@api.mailgun.net/v2/samples.mailgun.org/mailboxes",
  :mailbox => "sergeyo@samples.mailgun.org",
  :password => "secret"
end
public static ClientResponse CreateMailbox() {
       Client client = Client.create();
       client.addFilter(new HTTPBasicAuthFilter("api",
                       "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"));
       WebResource webResource =
               client.resource("https://api.mailgun.net/v2/samples.mailgun.org" +
                               "/mailboxes");
       MultivaluedMapImpl formData = new MultivaluedMapImpl();
       formData.add("mailbox", "sergeyo@samples.mailgun.org");
       formData.add("password", "secret");
       return webResource.type(MediaType.APPLICATION_FORM_URLENCODED).
               post(ClientResponse.class, formData);
}
function create_new_mailbox() {
  $request =
    new HttpRequest('https://api.mailgun.net/v2/samples.mailgun.org/mailboxes',
                    HttpRequest::METH_POST);
  $auth = base64_encode('api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0');
  $request->setHeaders(array('Authorization' => 'Basic '.$auth));
  $request->setPostFields(array('mailbox' => 'sergeyo@samples.mailgun.org',
                                'password' => 'secret'));
  $request->send();
  return $request;
}
def create_mailbox():
    r = requests.\
        post(("https://api.mailgun.net/v2/samples.mailgun.org/"
              "mailboxes"),
             auth=("api", "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"),
             data={"mailbox": "sergeyo@samples.mailgun.org",
                   "password": "secret"}
             )
    return r
public static RestResponse CreateMailbox() {
       RestClient client = new RestClient();
       client.BaseUrl = "https://api.mailgun.net/v2";
       client.Authenticator =
               new HttpBasicAuthenticator("api",
                                          "key-3ax6xnjp29jd6fds4gc373sgvjxteol0");
       RestRequest request = new RestRequest();
       request.AddParameter("domain",
                            "samples.mailgun.org", ParameterType.UrlSegment);
       request.Resource = "{domain}/mailboxes";
       request.AddParameter("mailbox", "sergeyo@samples.mailgun.org");
       request.AddParameter("password", "secret");
       request.Method = Method.POST;
       return client.Execute(request);
}
curl -s -k --user api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0 \
    https://api.mailgun.net/v2/samples.mailgun.org/mailboxes \
    -F mailbox='user@samples.mailgun.org' \
    -F password='supasecret'

Use any commercial POP3 (or IMAP) library for your programming language to access the content of this mailbox.

Using POP3 in Python:

import poplib

# login:
M = poplib.POP3('pop3.mailgun.org')
M.user('user@samples.mailgun.org')
M.pass_('supasecret')

# enumerate all messages in the inbox:
numMessages = len(M.list()[1])
for i in range(numMessages):
    for msg in M.retr(i+1)[1]:
        print msg

You can find more information in the Mailboxes section of the User Manual.

Campaign Analytics

Mailgun allows you to easily create Campaigns either using the API or the Campaigns Tab in the Control Panel. Campaigns are basically just groupings of messages by an ID. When you include a message in a Campaign, Mailgun tracks those messages and creates detailed analytics on those messages.

Campaign Analytics allow you to do things like:

  • Track events down to the individual recipient.
  • Compare Campaigns for A/B testing.
  • Optimize segmentation of Mailing Lists and content by geo location and recipient domain (Gmail, Hotmail, etc.).
  • Optimize delivery times by seeing engagement levels (opens & clicks) throughout the day.

Warning

Due to the increased cost of storing analytics, the cost of sending a message with a Campaign ID is twice the normal Mailgun rate. For example, if you are using the Pro Plan, sending a message with a Campaign ID will cost an additional $0.50 per 1,000 messages.

To create a campaign using the API:

def new_campaign
  RestClient.post("https://api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0" \
                  "@api.mailgun.net/v2/samples.mailgun.org/campaigns",
                  :name => 'Newsletter',
                  :id => 'my_campaign_id') {
    |response, request, result| response
  }
end
public static ClientResponse CreateCampaign() {
       Client client = new Client();
       client.addFilter(new HTTPBasicAuthFilter("api",
                       "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"));
       WebResource webResource =
               client.resource("https://api.mailgun.net/v2/samples.mailgun.org/campaigns");
       MultivaluedMapImpl formData = new MultivaluedMapImpl();
       formData.add("name", "Newsletter");
       formData.add("id", "my_campaign_id");
       return webResource.type(MediaType.APPLICATION_FORM_URLENCODED).
       post(ClientResponse.class, formData);
}
function new_campaign() {
  $request =
    new HttpRequest("https://api.mailgun.net/v2/samples.mailgun.org/campaigns",
                    HttpRequest::METH_POST);
  $auth = base64_encode('api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0');
  $request->setHeaders(array('Authorization' => 'Basic '.$auth));
  $request->setPostFields(array('name' => 'Newsletter',
                                'id' => 'my_campaign_id'));
  $request->setOptions(array('connecttimeout' => 15));
  $request->send();
  return $request;
}
def new_campaign():
    return requests.post(
        "https://api.mailgun.net/v2/samples.mailgun.org/campaigns",
        auth=('api', 'key-3ax6xnjp29jd6fds4gc373sgvjxteol0'),
        data={'name': 'Newsletter',
              'id': 'my_campaign_id'})
public static RestResponse CreateCampaign() {
       RestClient client = new RestClient();
       client.BaseUrl = "https://api.mailgun.net/v2";
       client.Authenticator =
               new HttpBasicAuthenticator("api",
                                          "key-3ax6xnjp29jd6fds4gc373sgvjxteol0");
       RestRequest request = new RestRequest();
       request.Resource = "{domain}/campaigns";
       request.AddParameter("domain", "samples.mailgun.org",
                            ParameterType.UrlSegment);
       request.AddParameter("name", "Newsletter");
       request.AddParameter("id", "my_campaign_id");
       request.Method = Method.POST;
       return client.Execute(request);
}
curl -s -k --user api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0 \
    https://api.mailgun.net/v2/samples.mailgun.org/campaigns \
    -F name='Newsletter' \
    -F id='my_campaign_id'

Provide o:campaign option to Mailgun’s sending API to include an email in a campaign. Use id of the created campaign as a value for this option (if you don’t provide an id above, Mailgun will generate one and return it to you):

def new_campaign_message
  RestClient.post("https://api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0" \
                  "@api.mailgun.net/v2/samples.mailgun.org/messages",
                  :from => "Excited User <me@samples.mailgun.org>",
                  :to => "roman@mailgun.net",
                  :subject => "Hello",
                  :text => "Testing some Mailgun awesomness!",
                  'o:campaign' => 'my_campaign_id')
end
public static ClientResponse PostMessage() {
       Client client = Client.create();
       client.addFilter(new HTTPBasicAuthFilter("api",
                       "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"));
       WebResource webResource =
               client.resource("https://api.mailgun.net/v2/samples.mailgun.org" +
                               "/messages");
       MultivaluedMapImpl formData = new MultivaluedMapImpl();
       formData.add("from", "Excited User <me@samples.mailgun.org>");
       formData.add("to", "sergeyo@profista.com");
       formData.add("to", "serobnic@mail.ru");
       formData.add("subject", "Hello");
       formData.add("text", "Testing some Mailgun awesomness!");
       formData.add("o:campaign", "my_campaign_id");
       return webResource.type(MediaType.APPLICATION_FORM_URLENCODED).
               post(ClientResponse.class, formData);
}
function new_campaign_message() {
  $request =
    new HttpRequest('https://api.mailgun.net/v2/samples.mailgun.org/messages',
                    HttpRequest::METH_POST);
  $auth = base64_encode('api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0');
  $request->setHeaders(array('Authorization' => 'Basic '.$auth));
  $request
    ->setPostFields(array('from' =>'Excited User'.
                          '<Excited User <me@samples.mailgun.org>>',
                          'to' => 'roman@mailgun.net',
                          'subject' => 'Hello',
                          'text' => 'Testing some Mailgun awesomness!',
                          'o:campaign' => 'my_campaign_id'
                          ));
  $request->send();
  return $request;
}
def new_campaign_message():
    return requests.post(
        "https://api.mailgun.net/v2/samples.mailgun.org/messages",
        auth=("api", "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"),
        data={"from": "Excited User <me@samples.mailgun.org>",
              "to": ["roman@mailgun.net"],
              "subject": "Hello",
              "text": "Testing some Mailgun awesomness!",
              "o:campaign": 'my_campaign_id'})
public static RestResponse PostMessage() {

       RestClient client = new RestClient();
       client.BaseUrl = "https://api.mailgun.net/v2";
       client.Authenticator =
               new HttpBasicAuthenticator("api",
                                          "key-3ax6xnjp29jd6fds4gc373sgvjxteol0");
       RestRequest request = new RestRequest();
       request.AddParameter("domain",
                            "samples.mailgun.org", ParameterType.UrlSegment);
       request.Resource = "{domain}/messages";
       request.AddParameter("from", "Excited User <me@samples.mailgun.org>");
       request.AddParameter("to", "sergeyo@profista.com");
       request.AddParameter("to", "serobnic@mail.ru");
       request.AddParameter("subject", "Hello");
       request.AddParameter("text", "Testing some Mailgun awesomness!");
       request.AddParameter("o:campaign", "my_campaign_id");
       request.Method = Method.POST;
       return client.Execute(request);
}
curl -s -k --user api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0 \
    https://api.mailgun.net/v2/samples.mailgun.org/messages \
    -F from='Excited User <me@samples.mailgun.org>' \
    -F to=roman@mailgun.net \
    -F subject='Hello' \
    -F text='Testing some Mailgun awesomness!' \
    -F o:campaign='my_campaign_id'

Mailgun will now track your messages for clicks, opens, bounces, complaints, unsubscribes and other events. You can view these detailed Analytics in the Campaigns Tab of the Control Panel or access the data via the API.

For example, to access the Analytics using the API:

def get_stats_campaigns
  RestClient.get("https://api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0"\
                 "@api.mailgun.net/v2/samples.mailgun.org/campaigns/"\
                 "my_campaign_id/stats")
end
public static ClientResponse GetStats() {
       Client client = new Client();
       client.addFilter(new HTTPBasicAuthFilter("api",
                       "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"));
       WebResource webResource =
               client.resource("https://api.mailgun.net/v2/samples.mailgun.org/campaigns/my_campaign_id/stats");
       return webResource.get(ClientResponse.class);
}
function get_campaign_stats() {
  $request =
    new HttpRequest("https://api.mailgun.net/v2/samples.mailgun.org/campaigns"
                    ."/my_campaign_id/stats",
                    HttpRequest::METH_GET);
  $auth = base64_encode('api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0');
  $request->setHeaders(array('Authorization' => 'Basic '.$auth));
  $request->setOptions(array('connecttimeout' => 15));
  $request->send();
  return $request;
}
def get_stats():
    return requests.get(
        ("https://api.mailgun.net/v2/samples.mailgun.org/campaigns"
         "/my_campaign_id/stats"),
        auth=('api', 'key-3ax6xnjp29jd6fds4gc373sgvjxteol0'))
public static RestResponse GetStats() {
       RestClient client = new RestClient();
       client.BaseUrl = "https://api.mailgun.net/v2";
       client.Authenticator =
               new HttpBasicAuthenticator("api",
                                          "key-3ax6xnjp29jd6fds4gc373sgvjxteol0");
       RestRequest request = new RestRequest();
       request.Resource = "{domain}/campaigns/my_campaign_id/stats";
       request.AddParameter("domain",
                            "samples.mailgun.org", ParameterType.UrlSegment);
       return client.Execute(request);
}
curl -s -k --user api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0 -G \
    https://api.mailgun.net/v2/samples.mailgun.org/campaigns/my_campaign_id/stats

You can find more information in the Campaign Analytics section of the User Manual.

Other Goodies

In addition to sending, receiving and storing mail, Mailgun can also help developers with the following:

  • Automatic “Unsubscribe me” functionality.
  • Support for email campaigns and tracking their performance.
  • Bounce handling.
  • Spam complaints handling.
  • Spam filtering for incoming messages.
  • Searchable email logs.

The list of what Mailgun can do for you is growing every day. Please take a look at our User Manual to learn more.