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.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 getComplaints() throws UnirestException {

        HttpResponse <JsonNode> request = Unirest.get("https://api.mailgun.net/v3/" + YOUR_DOMAIN_NAME + "/complaints")
            .basicAuth("api", API_KEY)
            .queryString("limit", "100")
            .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');
$domain = 'YOUR_DOMAIN_NAME';

# Issue the call to the client.
$result = $mgClient->get("$domain/complaints", array(
    'limit' => 10,
    'skip'  => 5
));
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);
    }

}
func GetComplaints(domain, apiKey string) (int, []mailgun.Complaint, error) {
  mg := mailgun.NewMailgun(domain, apiKey, "")
  return mg.GetComplaints()
}
var DOMAIN = 'YOUR_DOMAIN_NAME';
var mailgun = require('mailgun-js')({ apiKey: "YOUR_API_KEY", domain: DOMAIN });

mailgun.get(`/${DOMAIN}/complaints`, function (error, body) {
  console.log(body);
});

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 happend.
{
  "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.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 getComplaint() throws UnirestException {

        HttpResponse <JsonNode> request = Unirest.get("https://api.mailgun.net/v3/" + YOUR_DOMAIN_NAME + "/complaints/baz@example.com")
            .basicAuth("api", API_KEY)
            .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');
$domain = 'YOUR_DOMAIN_NAME';
$complaint = 'user@example.com';

# Issue the call to the client.
$result = $mgClient->get("$domain/complaints/$complaint");
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);
    }

}
func GetComplaints(domain, apiKey string) (mailgun.Complaint, error) {
  mg := mailgun.NewMailgun(domain, apiKey, "")
  return mg.GetSingleComplaint("baz@example.com")
}
var DOMAIN = 'YOUR_DOMAIN_NAME';
var mailgun = require('mailgun-js')({ apiKey: "YOUR_API_KEY", domain: DOMAIN });

mailgun.get(`/${DOMAIN}/complaints/baz@example.com`, function (error, body) {
  console.log(body);
});

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.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 addComplaint() throws UnirestException {

        HttpResponse <JsonNode> request = Unirest.post("https://api.mailgun.net/v3/" + YOUR_DOMAIN_NAME + "/complaints")
                       .basicAuth("api", API_KEY)
                       .field("address", "bob@example.com")
                       .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');
$domain = 'YOUR_DOMAIN_NAME';

# Issue the call to the client.
$result = $mgClient->post("$domain/complaints", array('address' => 'bob@example.com'));
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);
    }

}
func CreateComplaint(domain, apiKey, emailAddress string) error {
  mg := mailgun.NewMailgun(domain, apiKey, "")
  return mg.CreateComplaint("bob@example.com")
}

.. code-block:: node

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

mailgun.post(`/${DOMAIN}/complaints`, {"address" : "bob@example.com"}, function (error, body) {
  console.log(body);
});

Sample response:

{
  "message": "Address has been added to the complaints table",
  "address": "bob@example.com"
}