Spam Complaints¶
When recipients of your messages press “Spam” button, Mailgun receives those complaints from ESPs (email service providers).
Mailgun can notify your application every time a recipient flags your message as spam.
This API allows you to programmatically download the list of users who have complained, add a complaint, or delete a complaint.
GET /<domain>/complaints
Fetches the list of complaints.
Parameter | Description |
---|---|
limit | Maximum number of records to return. (100 by default) |
skip | Number of records to skip. (0 by default) |
GET /<domain>/complaints/<address>
Fetches a single spam complaint by a given email address. This is useful to check if a particular user has complained.
POST /<domain>/complaints
Adds an address to the complaints table.
Parameter | Description |
---|---|
address | Valid email address |
DELETE /<domain>/complaints/<address>
Removes a given spam complaint.
Examples¶
Fetch the full list of all recipients who have pressed their “Spam” buttons:
curl -s --user 'api:YOUR_API_KEY' -G \
https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/complaints
import com.mailgun.api.v3.suppression.MailgunSuppressionComplaintsApi;
import com.mailgun.model.suppression.complaints.ComplaintsItemResponse;
// ...
public ComplaintsItemResponse getComplaints() {
MailgunSuppressionComplaintsApi suppressionComplaintsApi = MailgunClient.config(API_KEY)
.createApi(MailgunSuppressionComplaintsApi.class);
return suppressionComplaintsApi.getAllComplaints(YOUR_DOMAIN_NAME, 2);
}
# Include the Autoloader (see "Libraries" for install instructions)
require 'vendor/autoload.php';
use Mailgun\Mailgun;
# Instantiate the client.
$mgClient = Mailgun::create('PRIVATE_API_KEY', 'https://API_HOSTNAME');
$domain = 'YOUR_DOMAIN_NAME';
# Issue the call to the client.
$result = $mgClient->suppressions()->complaints()->index($domain);
def get_complaints():
return requests.get(
"https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/complaints",
auth=("api", "YOUR_API_KEY"))
def get_complaints
RestClient.get "https://api:YOUR_API_KEY"\
"@api.mailgun.net/v3/YOUR_DOMAIN_NAME/complaints"
end
using System;
using System.IO;
using RestSharp;
using RestSharp.Authenticators;
public class GetComplaintsChunk
{
public static void Main (string[] args)
{
Console.WriteLine (GetComplaints ().Content.ToString ());
}
public static IRestResponse GetComplaints ()
{
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.AddParameter ("domain", "YOUR_DOMAIN_NAME", ParameterType.UrlSegment);
request.Resource = "{domain}/complaints";
return client.Execute (request);
}
}
import (
"context"
"github.com/mailgun/mailgun-go/v3"
"time"
)
func ListComplaints(domain, apiKey string) ([]mailgun.Complaint, error) {
mg := mailgun.NewMailgun(domain, apiKey)
it := mg.ListComplaints(nil)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
defer cancel()
var page, result []mailgun.Complaint
for it.Next(ctx, &page) {
result = append(result, page...)
}
if it.Err() != nil {
return nil, it.Err()
}
return result, nil
}
const DOMAIN = 'YOUR_DOMAIN_NAME';
const formData = require('form-data');
const Mailgun = require('mailgun.js');
const mailgun = new Mailgun(formData);
const client = mailgun.client({ username: 'api', key: 'YOUR_API_KEY' || '' });
(async () => {
try {
const complaints = await client.suppressions.list(DOMAIN, 'complaints');
console.log('complaints', complaints);
} catch (error) {
console.error(error);
}
})();
Sample JSON response is shown below. Notice the following:
- There was only one user who clicked “Spam” button.
- According to
count
value, he clicked twice. created_at
indicates the time when it happened.
{
"total_count": 1,
"items": [
{
"count": 2,
"created_at": "Tue, 15 Nov 2011 08:25:11 GMT",
"address": "baz@example.com"
}
]
}
Now lets check if baz@example.com
ever complained:
curl -s --user 'api:YOUR_API_KEY' -G \
https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/complaints/baz@example.com
import com.mailgun.api.v3.suppression.MailgunSuppressionComplaintsApi;
import com.mailgun.model.suppression.complaints.ComplaintsItem;
// ...
public ComplaintsItem getComplaint() {
MailgunSuppressionComplaintsApi suppressionComplaintsApi = MailgunClient.config(API_KEY)
.createApi(MailgunSuppressionComplaintsApi.class);
return suppressionComplaintsApi.getSingleComplaint(YOUR_DOMAIN_NAME, "baz@example.com");
}
# Include the Autoloader (see "Libraries" for install instructions)
require 'vendor/autoload.php';
use Mailgun\Mailgun;
# Instantiate the client.
$mgClient = Mailgun::create('PRIVATE_API_KEY', 'https://API_HOSTNAME');
$domain = 'YOUR_DOMAIN_NAME';
$recipient = 'bob@example.com';
# Issue the call to the client.
$result = $mgClient->suppressions()->complaints()->show($domain, $recipient);
def get_complaint():
return requests.get(
"https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/complaints/baz@example.com",
auth=("api", "YOUR_API_KEY"))
def get_complaint
RestClient.get("https://api:YOUR_API_KEY"\
"@api.mailgun.net/v3/YOUR_DOMAIN_NAME/complaints/"\
"baz@example.com"){|response, request, result| response }
end
using System;
using System.IO;
using RestSharp;
using RestSharp.Authenticators;
public class GetComplaintChunk
{
public static void Main (string[] args)
{
Console.WriteLine (GetComplaint ().Content.ToString ());
}
public static IRestResponse GetComplaint ()
{
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.AddParameter ("domain", "YOUR_DOMAIN_NAME", ParameterType.UrlSegment);
request.Resource = "{domain}/complaints/baz@example.com";
return client.Execute (request);
}
}
import (
"context"
"github.com/mailgun/mailgun-go/v3"
"time"
)
func GetComplaints(domain, apiKey string) (mailgun.Complaint, error) {
mg := mailgun.NewMailgun(domain, apiKey)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
defer cancel()
return mg.GetComplaint(ctx, "baz@example.com")
}
const DOMAIN = 'YOUR_DOMAIN_NAME';
const formData = require('form-data');
const Mailgun = require('mailgun.js');
const mailgun = new Mailgun(formData);
const client = mailgun.client({ username: 'api', key: 'YOUR_API_KEY' || '' });
(async () => {
try {
const complaintsForAddress = await client.suppressions.get(DOMAIN, 'complaints', 'baz@example.com');
console.log('complaintsForAddress', complaintsForAddress);
} catch (error) {
console.error(error);
}
})();
Of course he did. The response:
{
"complaint": {
"count": 2,
"created_at": "Tue, 15 Nov 2011 08:25:11 GMT",
"address": "baz@example.com"
}
}
Add a complaint to the table:
curl -s --user 'api:YOUR_API_KEY' \
https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/complaints \
-F address='bob@example.com'
import com.mailgun.api.v3.suppression.MailgunSuppressionComplaintsApi;
import com.mailgun.model.suppression.SuppressionResponse;
import com.mailgun.model.suppression.complaints.ComplaintsSingleItemRequest;
import java.time.ZonedDateTime;
// ...
public SuppressionResponse addComplaint() {
MailgunSuppressionComplaintsApi suppressionComplaintsApi = MailgunClient.config(API_KEY)
.createApi(MailgunSuppressionComplaintsApi.class);
ComplaintsSingleItemRequest complaintsSingleItemRequest = ComplaintsSingleItemRequest.builder()
.address( "bob@example.com")
.createdAt(ZonedDateTime.now())
.build();
return suppressionComplaintsApi.addAddressToComplaintsList(YOUR_DOMAIN_NAME, complaintsSingleItemRequest);
}
# Include the Autoloader (see "Libraries" for install instructions)
require 'vendor/autoload.php';
use Mailgun\Mailgun;
# Instantiate the client.
$mgClient = Mailgun::create('PRIVATE_API_KEY', 'https://API_HOSTNAME');
$domain = 'YOUR_DOMAIN_NAME';
$recipient = 'bob@example.com';
# Issue the call to the client.
$result = $mgClient->suppressions()->complaints()->create($domain, $recipient);
def add_complaint():
return requests.post(
"https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/complaints",
auth=("api", "YOUR_API_KEY"),
data={'address': 'bob@example.com'})
def add_complaint
RestClient.post "https://api:YOUR_API_KEY"\
"@api.mailgun.net/v3/YOUR_DOMAIN_NAME/complaints",
:address => 'bob@example.com'
end
using System;
using System.IO;
using RestSharp;
using RestSharp.Authenticators;
public class AddComplaintChunk
{
public static void Main (string[] args)
{
Console.WriteLine (AddComplaint ().Content.ToString ());
}
public static IRestResponse AddComplaint ()
{
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 = "{domain}/complaints";
request.AddParameter ("domain", "YOUR_DOMAIN_NAME", ParameterType.UrlSegment);
request.AddParameter ("address", "bob@example.com");
request.Method = Method.POST;
return client.Execute (request);
}
}
import (
"context"
"github.com/mailgun/mailgun-go/v3"
"time"
)
func CreateComplaint(domain, apiKey string) error {
mg := mailgun.NewMailgun(domain, apiKey)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
defer cancel()
return mg.CreateComplaint(ctx, "bob@example.com")
}
const DOMAIN = 'YOUR_DOMAIN_NAME';
const formData = require('form-data');
const Mailgun = require('mailgun.js');
const mailgun = new Mailgun(formData);
const client = mailgun.client({ username: 'api', key: 'YOUR_API_KEY' || '' });
(async () => {
try {
const createdComplaint = await client.suppressions.create(DOMAIN, 'complaints', { address: 'bob@example.com' });
console.log('createdComplaint', createdComplaint);
} catch (error) {
console.error(error);
}
})();
Sample response:
{
"message": "Address has been added to the complaints table",
"address": "bob@example.com"
}