NAV Navbar

API Docs

testmail.app/docs

Introduction

The testmail GraphQL API is self-documenting! Check the schema and docs popovers on the right in the GraphQL playground.

The documentation here covers topics not addressed in the self-documenting schema.

API authentication

const GraphQLClient = require('graphql-request').GraphQLClient;
const testmailClient = new GraphQLClient(
  // API endpoint:
  'https://api.testmail.app/api/graphql',
  // Use your API key:
  { headers: { 'Authorization': 'Bearer API_KEY' } }
);

To use the API, you need a GraphQL (recommended) or HTTP client. We've included a Javascript example on the right using the graphql-request client.

The API endpoint: https://api.testmail.app/api/graphql

Access to the API is secured using API keys. You can get your API key or register a new API key in the developer console.

The API key must be included in all API requests to the server in an authorization header that looks like this:

Authorization: Bearer API_KEY

Querying the inbox

testmailClient.request(`{
  inbox (
    namespace:"YOUR_NAMESPACE"
  ) {
    result
    message
    count
  }
}`).then((data) => {
  console.log(data.inbox);
});

Expect something like this (example):

{
  "result": "success",
  "message": null,
  "count": 2
}

There's just one query you need: the inbox query.

In the example on the right (a very simple query), testmail will return a count for the total number of emails in the specified namespace. It specifies one argument - the namespace (always mandatory) - and asks for the result, message, and count.

Successful queries will return result: 'success'; unsuccessful queries will return result: 'fail'. In case of failure, the message will usually provide an explanation.

The count will return an integer. Of course: you can query for a lot more than the count. Please see the docs tab in the GraphQL playground for a full API reference.

If you're expecting the query to return many emails and you need pagination, you can use the limit (default is 10) and offset arguments.

"Live" queries

const timestamp = Date.now();
testmailClient.request(`{
  inbox (
    namespace:"YOUR_NAMESPACE"
    tag:"john.smith"
    timestamp_from:${timestamp}
    livequery:true
  ) {
    result
    message
    emails {
      from
      from_parsed {
        address
        name
      }
      subject
    }
  }
}`).then((data) => {
  console.log(data.inbox);
});

Expect something like this (example):

{
  "result": "success",
  "message": null,
  "emails": [{
    "from": "testmail app <[email protected]>",
    "from_parsed": {
      "address": "[email protected]",
      "name": "testmail app"
    },
    "subject": "Please confirm your email"
  }]
}

When you're expecting to receive an email, instead of repeatedly querying the inbox, use a "live" query.

"Live" queries wait until at least one email is matched before returning. In the example on the right, the testmail API will wait until a new email addressed to [email protected] is received before returning.

"Live" queries are implemented using HTTP 307 redirects. Here's how it works:

"Live" queries can return multiple emails. This happens either because there are already multiple emails matching the query (so the "live" query returns immediately) or because multiple new emails were received and processed at the same time (this is rare).

Sorting and filtering

testmailClient.request(`{
  inbox (
    namespace:"YOUR_NAMESPACE"
    tag_prefix:"peter"
    advanced_filters:[{
      field:subject
      match:exact
      action:include
      value:"Please confirm your email"
    }]
    advanced_sorts:[{
      field:tag,
      order:asc
    }, {
      field:timestamp,
      order:desc
    }]
  ) {
    result
    message
    count
    emails {
      tag
      timestamp
    }
  }
}`).then((data) => {
  console.log(data.inbox);
});

Expect something like this (example):

{
  "result": "success",
  "message": null,
  "count": 4,
  "emails": [{
    "tag": "peter.pan",
    "timestamp": 1565139749955
  }, {
    "tag": "peter.pan",
    "timestamp": 1565136514957
  }, {
    "tag": "peter.parker",
    "timestamp": 1565140065791
  }, {
    "tag": "peter.parker",
    "timestamp": 1565140041284
  }]
}

The testmail API has excellent options for sorting and filtering emails. A couple of typical use cases:

If you don't use sufficiently specific filters, the live query will return any new email that hits the inbox - not necessarily the email you're expecting. This is especially important when you have many back-to-back email tests (you could receive emails in an unexpected order) or when you have parallel builds in your CI pipelines (you could receive emails from another test).

If you want to check whether an email with <h1>Getting started</h1> in the html body just hit the inbox, you can use the wildcard filter on the html field and query the count of matched emails instead of downloading the full html content and searching for that string.

Note that the timestamp_from, timestamp_to, tag, and tag_prefix options are the most performant options for filtering emails.

Tags are indexed using n-grams - so tags and subsets of tags can be queried incredibly efficiently. Here is a typical usage pattern that takes advantage of this:

Send emails to: namespace.category.subcateg[email protected] (where the tag is category.subcategory), and then query for emails using the tag_prefix:

Nesting tags like this allows you to group/categorize inboxes, reduce conflicts, and use fewer advanced_filters (which are less performant).

Emails are sorted by the timestamp field in descending order by default (newest emails first). You can change this using advanced_sorts; you can also use multiple sorts (see the example on the right).

Troubleshooting

Timeouts are the most common issue. There are many reasons for this:

Email is fairly old technology (the first email was sent in 1971!) with many potential bottlenecks. While most emails are received within a few seconds, some emails can take 10 minutes or more, and on rare occasions emails can take days to deliver! When emails fail to deliver (e.g. because of a connection issue), the sending server usually makes a certain number of retry attempts with an increasing time interval between retries. So when you send many emails, and when you've integrated testmail in your CI/CD pipeline, you will inevitably encounter edge cases.

To minimize build timeouts while waiting to receive emails, make sure the timeout configured in your test environment is sufficiently high. We use 10 minutes in our pipeline, but we can't recommend this number for everyone. Here's the tradeoff: if the timeout is too low, you'll get more build failures (you'll just have to retry/restart these builds). If the timeout is too high, the edge cases can result in builds that take very long and clog your pipeline.

If your mail server IP address or ISP has a bad reputation, spam filters can reject or delay your emails. Misconfigurations on the sending server can cause delays, deliverability problems, and failures. One key benefit of end-to-end testing is discovering these problems in advance - before your users experience them.

Here's a real example: we signed up for Mailgun and started testing email sends. We noticed that many of our emails were not reaching the inbox. This was because, as a new customer, Mailgun had put us in a shared pool of IPs with a poor spam reputation. After reaching out to their support team and verifying our business (the types of emails we send, email list management policies, privacy policy, etc.), they upgraded us to an IP pool with a better reputation. This is not an endorsement or criticism of Mailgun; every good email provider has to do this (in some way) to prevent spammers from signing up and sending bulk emails from their quality IPs.

Of course: this is what we are testing in the first place! If your program is not sending the right emails or fails to send emails at all, the tests will naturally timeout or fail (as they should).

If you're struggling with troubleshooting timeouts or any other issues, please reach out - we're happy to help.

Getting help

If you're looking for the API reference, please see the schema and docs popovers on the right in the GraphQL playground.

We're happy to provide support over email and live chat. Pro and enterprise customers should use their registered emails or signin for priority support.