Mailgun automatically handles bounced emails. The bounced addresses, are collected in a bounces list and subsequent delivery attempts are ignored to protect your sending reputation.
Mailgun can notify your application every time a message bounces.
The list of bounced addresses can be accessed programmatically:
GET /<domain>/bounces
Fetches the list of bounces.
| Parameter | Description |
|---|---|
| limit | Maximum number of records to return. (100 by default) |
| skip | Number of records to skip. (0 by default) |
GET /<domain>/bounces/<address>
Fetches a single bounce event by a given email address. This is useful to check if a given email address has bounced before.
DELETE /<domain>/bounces/<address>
“clears” a given bounce event.
POST /<domain>/bounces
Adds a permanent bounce to the bounces table. Updates the existing record if already here.
| Parameter | Description |
|---|---|
| address | Valid email address |
| code | Error code (default 550) |
| error | Error description, (default is empty) |
Fetch the full list of all recipient addresses that bounced:
def get_bounces
RestClient.get "https://api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0"\
"@api.mailgun.net/v2/samples.mailgun.org/bounces"
end
Response JSON is shown below. Notice the following:
- There was only one bounce
- Both SMTP error code and SMTP error message are preserved
{
"total_count": 4,
"items": [
{
"code": "550",
"created_at": "Wed, 15 Feb 2012 11:16:31 GMT",
"error": "",
"address": "ev@mgrules.com"
},
{
"code": 550,
"created_at": "Sun, 05 Feb 2012 21:36:26 GMT",
"error": "5.1.1 <void@guillaumeleveque.info>: Recipient address rejected: User unknown in virtual mailbox table",
"address": "void@guillaumeleveque.info"
},
{
"code": 550,
"created_at": "Mon, 09 Jan 2012 04:29:42 GMT",
"error": "5.1.1 <mastronardif@gmail.net>: Recipient address rejected: User unknown in virtual alias table",
"address": "mastronardif@gmail.net"
},
{
"code": 550,
"created_at": "Fri, 21 Oct 2011 11:02:55 GMT",
"error": "Message was not accepted -- invalid mailbox. Local mailbox 'serobnic@mail.ru is unavailable: user not found",
"address": "'serobnic@mail.ru"
}
]
}
Lets check if any messages sent to foo@bar.com have bounced before:
def check_address_for_bounces
RestClient.get("https://api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0"\
"@api.mailgun.net/v2/samples.mailgun.org/bounces"\
"/foo@bar.com"){|response, request, result| response }
end
Response:
{
"message": "Address not found in bounces table"
}
Add a bounce to the table:
def add_bounce
RestClient.post("https://api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0"\
"@api.mailgun.net/v2/samples.mailgun.org/bounces",
:address => 'ev@mgrules.com')
end
The response:
{
"message": "Address has been added to the bounces table",
"address": "ev@mgrules.com"
}
Fetch the full list of all recipient addresses that bounced:
public static ClientResponse GetBounces() {
Client client = new Client();
client.addFilter(new HTTPBasicAuthFilter("api",
"key-3ax6xnjp29jd6fds4gc373sgvjxteol0"));
WebResource webResource =
client.resource("https://api.mailgun.net/v2/samples.mailgun.org" +
"/bounces");
return webResource.get(ClientResponse.class);
}
Response JSON is shown below. Notice the following:
- There was only one bounce
- Both SMTP error code and SMTP error message are preserved
{
"total_count": 4,
"items": [
{
"code": "550",
"created_at": "Wed, 15 Feb 2012 11:29:13 GMT",
"error": "",
"address": "ev@mgrules.com"
},
{
"code": 550,
"created_at": "Sun, 05 Feb 2012 21:36:26 GMT",
"error": "5.1.1 <void@guillaumeleveque.info>: Recipient address rejected: User unknown in virtual mailbox table",
"address": "void@guillaumeleveque.info"
},
{
"code": 550,
"created_at": "Mon, 09 Jan 2012 04:29:42 GMT",
"error": "5.1.1 <mastronardif@gmail.net>: Recipient address rejected: User unknown in virtual alias table",
"address": "mastronardif@gmail.net"
},
{
"code": 550,
"created_at": "Fri, 21 Oct 2011 11:02:55 GMT",
"error": "Message was not accepted -- invalid mailbox. Local mailbox 'serobnic@mail.ru is unavailable: user not found",
"address": "'serobnic@mail.ru"
}
]
}
Lets check if any messages sent to foo@bar.com have bounced before:
public static ClientResponse CheckAddressForBounces() {
Client client = new Client();
client.addFilter(new HTTPBasicAuthFilter("api",
"key-3ax6xnjp29jd6fds4gc373sgvjxteol0"));
WebResource webResource =
client.resource("https://api.mailgun.net/v2/samples.mailgun.org/" +
"bounces/foo@bar.com");
return webResource.get(ClientResponse.class);
}
Response:
{
"message": "Address not found in bounces table"
}
Add a bounce to the table:
public static ClientResponse AddBounce() {
Client client = new Client();
client.addFilter(new HTTPBasicAuthFilter("api",
"key-3ax6xnjp29jd6fds4gc373sgvjxteol0"));
WebResource webResource =
client.resource("https://api.mailgun.net/v2/samples.mailgun.org/" +
"bounces");
MultivaluedMapImpl formData = new MultivaluedMapImpl();
formData.add("address", "ev@mailgun.net");
return webResource.type(MediaType.APPLICATION_FORM_URLENCODED).
post(ClientResponse.class, formData);
}
The response:
{
"message": "Address has been added to the bounces table",
"address": "ev@mailgun.net"
}
Fetch the full list of all recipient addresses that bounced:
function get_bounces() {
$request =
new HttpRequest('https://api.mailgun.net/v2/samples.mailgun.org/bounces',
HttpRequest::METH_GET);
$auth = base64_encode('api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0');
$request->setHeaders(array('Authorization' => 'Basic '.$auth));
$request->send();
return $request;
}
Response JSON is shown below. Notice the following:
- There was only one bounce
- Both SMTP error code and SMTP error message are preserved
{
"total_count": 5,
"items": [
{
"code": "550",
"created_at": "Wed, 15 Feb 2012 11:43:09 GMT",
"error": "",
"address": "ev@mailgun.net"
},
{
"code": "550",
"created_at": "Wed, 15 Feb 2012 11:29:13 GMT",
"error": "",
"address": "ev@mgrules.com"
},
{
"code": 550,
"created_at": "Sun, 05 Feb 2012 21:36:26 GMT",
"error": "5.1.1 <void@guillaumeleveque.info>: Recipient address rejected: User unknown in virtual mailbox table",
"address": "void@guillaumeleveque.info"
},
{
"code": 550,
"created_at": "Mon, 09 Jan 2012 04:29:42 GMT",
"error": "5.1.1 <mastronardif@gmail.net>: Recipient address rejected: User unknown in virtual alias table",
"address": "mastronardif@gmail.net"
},
{
"code": 550,
"created_at": "Fri, 21 Oct 2011 11:02:55 GMT",
"error": "Message was not accepted -- invalid mailbox. Local mailbox 'serobnic@mail.ru is unavailable: user not found",
"address": "'serobnic@mail.ru"
}
]
}
Lets check if any messages sent to foo@bar.com have bounced before:
function check_address_for_bounces() {
$request =
new HttpRequest('https://api.mailgun.net/v2/samples.mailgun.org/'
.'bounces/foo@bar.com',
HttpRequest::METH_GET);
$auth = base64_encode('api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0');
$request->setHeaders(array('Authorization' => 'Basic '.$auth));
$request->send();
return $request;
}
Response:
{
"message": "Address not found in bounces table"
}
Add a bounce to the table:
function add_bounce() {
$request =
new HttpRequest('https://api.mailgun.net/v2/samples.mailgun.org/'
.'bounces',
HttpRequest::METH_POST);
$auth = base64_encode('api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0');
$request->setHeaders(array('Authorization' => 'Basic '.$auth));
$request->setPostFields(array('address' => 'ev@mailgun.net'));
$request->send();
return $request;
}
The response:
{
"message": "Address has been added to the bounces table",
"address": "ev@mailgun.net"
}
Fetch the full list of all recipient addresses that bounced:
def get_bounces():
r = requests.\
get(("https://api.mailgun.net/v2/samples.mailgun.org/"
"bounces"),
auth=("api", "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"))
return r
Response JSON is shown below. Notice the following:
- There was only one bounce
- Both SMTP error code and SMTP error message are preserved
{
"total_count": 4,
"items": [
{
"code": "550",
"created_at": "Wed, 15 Feb 2012 11:13:39 GMT",
"error": "",
"address": "ev@mgrules.com"
},
{
"code": 550,
"created_at": "Sun, 05 Feb 2012 21:36:26 GMT",
"error": "5.1.1 <void@guillaumeleveque.info>: Recipient address rejected: User unknown in virtual mailbox table",
"address": "void@guillaumeleveque.info"
},
{
"code": 550,
"created_at": "Mon, 09 Jan 2012 04:29:42 GMT",
"error": "5.1.1 <mastronardif@gmail.net>: Recipient address rejected: User unknown in virtual alias table",
"address": "mastronardif@gmail.net"
},
{
"code": 550,
"created_at": "Fri, 21 Oct 2011 11:02:55 GMT",
"error": "Message was not accepted -- invalid mailbox. Local mailbox 'serobnic@mail.ru is unavailable: user not found",
"address": "'serobnic@mail.ru"
}
]
}
Lets check if any messages sent to foo@bar.com have bounced before:
def check_address_for_bounces():
r = requests.\
get(("https://api.mailgun.net/v2/samples.mailgun.org/"
"bounces/foo@bar.com"),
auth=("api", "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"))
return r
Response:
{
"message": "Address not found in bounces table"
}
Add a bounce to the table:
def add_bounce():
r = requests.\
post(("https://api.mailgun.net/v2/samples.mailgun.org/"
"bounces"),
auth=("api", "key-3ax6xnjp29jd6fds4gc373sgvjxteol0"),
data={'address':'ev@mgrules.com'})
return r
The response:
{
"message": "Address has been added to the bounces table",
"address": "ev@mgrules.com"
}
Fetch the full list of all recipient addresses that bounced:
public static RestResponse GetBounces() {
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}/bounces";
return client.Execute(request);
}
Response JSON is shown below. Notice the following:
- There was only one bounce
- Both SMTP error code and SMTP error message are preserved
{
"total_count": 5,
"items": [
{
"code": "550",
"created_at": "Wed, 15 Feb 2012 11:35:43 GMT",
"error": "",
"address": "ev@mailgun.net"
},
{
"code": "550",
"created_at": "Wed, 15 Feb 2012 11:29:13 GMT",
"error": "",
"address": "ev@mgrules.com"
},
{
"code": 550,
"created_at": "Sun, 05 Feb 2012 21:36:26 GMT",
"error": "5.1.1 <void@guillaumeleveque.info>: Recipient address rejected: User unknown in virtual mailbox table",
"address": "void@guillaumeleveque.info"
},
{
"code": 550,
"created_at": "Mon, 09 Jan 2012 04:29:42 GMT",
"error": "5.1.1 <mastronardif@gmail.net>: Recipient address rejected: User unknown in virtual alias table",
"address": "mastronardif@gmail.net"
},
{
"code": 550,
"created_at": "Fri, 21 Oct 2011 11:02:55 GMT",
"error": "Message was not accepted -- invalid mailbox. Local mailbox 'serobnic@mail.ru is unavailable: user not found",
"address": "'serobnic@mail.ru"
}
]
}
Lets check if any messages sent to foo@bar.com have bounced before:
public static RestResponse CheckAddressForBounces() {
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}/bounces/foo@bar.com";
return client.Execute(request);
}
Response:
{
"message": "Address not found in bounces table"
}
Add a bounce to the table:
public static RestResponse AddBounce() {
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}/bounces";
request.AddParameter("domain",
"samples.mailgun.org", ParameterType.UrlSegment);
request.AddParameter("address", "ev@mailgun.net");
request.Method = Method.POST;
return client.Execute(request);
}
The response:
{
"message": "Address has been added to the bounces table",
"address": "ev@mailgun.net"
}
Fetch the full list of all recipient addresses that bounced:
curl -s -k --user api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0 -G \
https://api.mailgun.net/v2/samples.mailgun.org/bounces
Response JSON is shown below. Notice the following:
- There was only one bounce
- Both SMTP error code and SMTP error message are preserved
{
"total_count": 5,
"items": [
{
"created_at": "Wed, 15 Feb 2012 12:35:56 GMT",
"code": "550",
"address": "ev@mgrules.com",
"error": ""
},
{
"created_at": "Wed, 15 Feb 2012 12:30:17 GMT",
"code": "550",
"address": "ev@mailgun.net",
"error": ""
},
{
"created_at": "Sun, 05 Feb 2012 21:36:26 GMT",
"code": 550,
"address": "void@guillaumeleveque.info",
"error": "5.1.1 <void@guillaumeleveque.info>: Recipient address rejected: User unknown in virtual mailbox table"
},
{
"created_at": "Mon, 09 Jan 2012 04:29:42 GMT",
"code": 550,
"address": "mastronardif@gmail.net",
"error": "5.1.1 <mastronardif@gmail.net>: Recipient address rejected: User unknown in virtual alias table"
},
{
"created_at": "Fri, 21 Oct 2011 11:02:55 GMT",
"code": 550,
"address": "'serobnic@mail.ru",
"error": "Message was not accepted -- invalid mailbox. Local mailbox 'serobnic@mail.ru is unavailable: user not found"
}
]
}
Lets check if any messages sent to foo@bar.com have bounced before:
curl -s -k --user api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0 -G \
https://api.mailgun.net/v2/samples.mailgun.org/bounces/foo@bar.com
Response:
{
"message": "Address not found in bounces table"
}
Add a bounce to the table:
curl -s -k --user api:key-3ax6xnjp29jd6fds4gc373sgvjxteol0 \
https://api.mailgun.net/v2/samples.mailgun.org/bounces \
-F address='ev@mgrules.com'
The response:
{
"message": "Address has been added to the bounces table",
"address": "ev@mgrules.com"
}