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 javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;

import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;

import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;

public class MGSample {

    // ...

    public static ClientResponse GetComplaints() {

        Client client = ClientBuilder.newClient();
        client.register(HttpAuthenticationFeature.basic(
            "api",
            "YOUR_API_KEY"
        ));

        WebTarget mgRoot = client.target("https://api.mailgun.net/v3");

        return mgRoot
            .path("/{domain}/complaints")
            .resolveTemplate("domain", "YOUR_DOMAIN_NAME")
            .request()
            .buildGet()
            .invoke(ClientResponse.class);
    }
}
# 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()
}

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 javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;

import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;

import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;

public class MGSample {

    // ...

    public static ClientResponse GetComplaint() {

        Client client = ClientBuilder.newClient();
        client.register(HttpAuthenticationFeature.basic(
            "api",
            "YOUR_API_KEY"
        ));

        WebTarget mgRoot = client.target("https://api.mailgun.net/v3");

        return mgRoot
            .path("/{domain}/complaints/{address}")
            .resolveTemplate("domain", "YOUR_DOMAIN_NAME")
            .resolveTemplate("address", "bob@example.com")
            .request()
            .buildGet()
            .invoke(ClientResponse.class);
    }
}
# 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")
}

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 javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;

import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;

import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;

public class MGSample {

    // ...

    public static ClientResponse AddComplaint() {

        Client client = ClientBuilder.newClient();
        client.register(HttpAuthenticationFeature.basic(
            "api",
            "YOUR_API_KEY"
        ));

        WebTarget mgRoot = client.target("https://api.mailgun.net/v3");

        Form reqData = new Form();
        reqData.param("address", "bob@example.com");

        return mgRoot
            .path("/{domain}/complaints")
            .resolveTemplate("domain", "YOUR_DOMAIN_NAME")
            .request(MediaType.APPLICATION_FORM_URLENCODED)
            .buildPost(Entity.entity(reqData, MediaType.APPLICATION_FORM_URLENCODED))
            .invoke(ClientResponse.class);
    }
}
# 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")
}

Sample response:

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