mailsac

Private email domain for testing

For QA and engineering teams

A private email domain for testing

Give your staging environment and CI its own email domain. Your tests make up any address on it, your app sends the sign-up or password-reset email there, and only your team can read it through the Mailsac website or API.

Short answer. On any paid Mailsac plan you can add a custom domain in one of two ways:

1. A Mailsac subdomain, no DNS: pick a name such as yourteam.msdc.co and it receives mail straight away.

2. Your own domain or subdomain, such as qa.example.com: add one TXT record to prove ownership and two MX records, 1 in.mailsac.com and 5 alt.mailsac.com.

Either way, every address on the domain works without being created first. Mail is private to your account, and it has higher throttling limits than the public @mailsac.com inboxes. Plans start at $18 a month with one domain included.

Why not use the public @mailsac.com inboxes?

Any address at @mailsac.com receives mail with no sign-up, which is handy for a quick manual check. For a test suite that runs every day, it causes three problems.

  • Anyone can read them. Public inboxes have no password. If your staging app emails real-looking names, one-time codes or reset links, anyone who guesses or reuses the address can see them. Use made-up data in public inboxes.
  • They are shared and throttled. Mail to public addresses has a lower throttling threshold than mail to private addresses or verified custom domains. When a CI run sends a burst of email, delivery can first slow down and then be refused with an SMTP 421 error, so tests fail or time out.
  • Other people use the same addresses. A public inbox keeps only the latest 6 messages, for up to 4 days, and someone else’s mail can land in it. Some senders also refuse to deliver to @mailsac.com at all.

A private domain avoids all three. Mail on it is visible only to your account and team, is throttled at a much higher threshold (most customers never hit it), and is kept until you delete it or reach your plan’s storage limit.

Sources: Email throttling, Message storage and Missing email in the Mailsac docs.

Two ways to get a private test domain

Both count as one custom domain on your plan and behave the same once set up. Add them from the Custom Domains page in the dashboard; domains can’t be added with an API key.

Option 1: a Mailsac subdomain

Best if you don’t own a domain, or can’t get DNS changes made quickly.

  1. In the dashboard, open Custom Domains and choose Setup a Custom Domain.
  2. Enter a subdomain name, for example yourteam. You get yourteam.msdc.co.
  3. Send a test email to any address on it, such as hello@yourteam.msdc.co, and check it arrived.

Mailsac publishes the MX records for you, so there is nothing to verify and no waiting for DNS.

Option 2: your own domain or subdomain

Best if you want test addresses that look like your product, for example signup-123@qa.example.com, or your app only accepts your own domain.

A subdomain you use only for testing is the usual choice. The records go on that subdomain, so the MX records for your company’s main domain are not touched.

Setup takes three DNS records. DNS changes can take up to 24 hours to propagate.

Set up your own domain: exact DNS records

  1. In the dashboard, open Custom Domains, choose Setup a Custom Domain and enter the full domain name, for example qa.example.com.
  2. Open the domain’s DNS Setup tab. It shows a TXT value unique to your domain that starts with mailsac_.
  3. Add these records at your DNS host:
TypeName (host)ValuePriority
TXTqa.example.commailsac_xxxxxxxx (copy yours from the DNS Setup tab)–
MXqa.example.comin.mailsac.com1
MXqa.example.comalt.mailsac.com5
  1. Back on the DNS Setup tab, click Query My DNS Settings Now. Each record shows OK once Mailsac can see it. Both MX records are required.

The MX values are the same for every domain hosted at Mailsac; only the TXT value is unique. Many DNS hosts want the name without your root domain (for example just qa), or @ for the root domain itself.

Amazon Route 53

Create one MX record set for the name with both values on separate lines: 1 in.mailsac.com and 5 alt.mailsac.com. For the TXT record, wrap the value in double quotes. If the name already has a TXT record (an SPF record, for example), add the Mailsac value as another quoted line in the same record set rather than creating a second record.

Cloudflare

Add two MX records with the name qa (or your subdomain), mail servers in.mailsac.com and alt.mailsac.com, and priorities 1 and 5. Add a TXT record with the same name and your mailsac_ value. MX and TXT records aren’t proxied, so there is no orange-cloud setting to change.

Check from a terminal

dig TXT qa.example.com +short
dig MX qa.example.com +short
# expected MX answer:
# 1 in.mailsac.com.
# 5 alt.mailsac.com.

Until the TXT record verifies, Mailsac treats the domain as unverified: mail to it is handled like public mail, with the lower throttling threshold and the 4-day limit. Finish verification before you rely on it in CI.

Full guides: Custom domains and DNS verification.

Any address works: use a new one for every test

You don’t create addresses on a custom domain. The first email sent to an address creates it, so a test can generate a fresh address each run, such as signup-1739912345@qa.example.com, and read only its own mail. Parallel tests then never pick up each other’s messages, and you don’t need to clean up between runs.

All of the domain’s mail is also available in one place:

  • API: list the newest messages across every address on the domain with GET /api/domains/{domain}/messages (verified domains only).
  • Catch-All address: turn it on from the domain’s Forwarding tab to get one inbox, *@qa.example.com, for the whole domain. Like a private address, it can forward mail to another private address, a webhook, a WebSocket or Slack.
  • Website and POP3: read the mail in the Unified Inbox or an email client.

See Catch-All domain forwarding and the API reference.

Using the domain from your tests

Authenticate every API request with your API key in the Mailsac-Key header. Here is a Playwright test that signs up on staging with a unique address, waits for the confirmation email and opens its link. Each message in the list includes a links array with the URLs found in the email.

import { test, expect } from '@playwright/test';

const DOMAIN = 'qa.example.com'; // or yourteam.msdc.co
const headers = { 'Mailsac-Key': process.env.MAILSAC_API_KEY! };

test('sign-up sends a confirmation link', async ({ page, request }) => {
  const email = `signup-${Date.now()}@${DOMAIN}`;

  await page.goto('https://staging.example.com/register');
  await page.getByLabel('Email').fill(email);
  await page.getByRole('button', { name: 'Sign up' }).click();

  let messages: any[] = [];
  await expect.poll(async () => {
    const res = await request.get(
      `https://mailsac.com/api/addresses/${email}/messages`, { headers });
    messages = await res.json();
    return messages.length;
  }, { timeout: 60_000 }).toBeGreaterThan(0);

  const link = messages[0].links.find((url: string) => url.includes('/confirm'));
  expect(link).toBeTruthy();
  await page.goto(link!);
});

The same check with curl, for example in a shell step in CI:

# newest messages for one address
curl -s -H "Mailsac-Key: $MAILSAC_API_KEY" \
  "https://mailsac.com/api/addresses/signup-123@qa.example.com/messages"

# newest 10 messages across the whole domain
curl -s -H "Mailsac-Key: $MAILSAC_API_KEY" \
  "https://mailsac.com/api/domains/qa.example.com/messages?limit=10"

Polling costs one operation per request. For large suites, a webhook or WebSocket delivers each email with a single operation instead. Business and higher plans can open a WebSocket for a whole domain. More on writing these tests: Email testing API.

Team access and your security review

  • Private by default. New custom domains are private. Only the account holder and the account’s team users can read the mail. (Enterprise plans can choose to make a domain public.)
  • Team logins and SSO. Business ($89 a month) includes 5 users with SAML single sign-on (Okta, Azure AD, Google) and multiple named API keys, so each pipeline can have its own key. Business+ includes 10 users and Enterprise 25. Indie is for one user.
  • Not archived. Unlike public inboxes, messages to private addresses and custom domains are never archived by Mailsac. Your test mail stays visible only to your team.
  • Hosting. Mailsac runs on AWS in the United States. Enterprise plans include help with security questionnaires such as SIG and CyberGRX.
  • Clearing out data. Delete single messages, or all of a domain’s mail at once, from the website or API at any time.

Troubleshooting

The domain won’t verify

  • Run dig TXT and dig MX on the exact name you added. The records must be on that name, for example qa.example.com, not on example.com.
  • Check that the TXT value matches the DNS Setup tab exactly, and that both MX records exist. Mailsac needs both in.mailsac.com and alt.mailsac.com.
  • Watch for DNS hosts that append the root domain automatically, which turns qa.example.com into qa.example.com.example.com.
  • New records can take up to 24 hours to propagate. Click Query My DNS Settings Now again later; the tab lists what it found.

Mail isn’t arriving

  • Messages over 2.5 MB are not accepted.
  • Your sending service may be queuing mail. SendGrid and Mandrill often delay sends; with SendGrid, set up sender authentication so mail doesn’t come from a shared sendgrid.net address.
  • Check the message isn’t in the spam folder of the Unified Inbox. You can turn the spam filter off in Account Settings.
  • If your app sends thousands of messages a minute, you can still be throttled. On Business and higher plans you can request an IP allowlist from the dashboard so your senders are never throttled.

A sender is blocked

Some services refuse to send to @mailsac.com, which is one reason to test on your own domain. Mailsac also blocks mail from social media and streaming services, and from senders that harm the service. If you test for one of those companies, contact support.

Older messages disappear

Messages on custom domains, private addresses and starred messages share your plan’s storage limit (1,000 messages on Indie, 5,000 on Business). When it is full, the oldest messages are recycled. Delete old test mail with the API, or add 5,000 more stored messages for $10 a month.

More help: Missing email.

Questions

How do I get a private email domain for automated tests?

Sign up for a paid Mailsac plan (from $18 a month), then add a custom domain from the dashboard. Either pick a subdomain of msdc.co, which works straight away, or add your own domain with one TXT record and two MX records (1 in.mailsac.com, 5 alt.mailsac.com). Your tests then send to any address on it and read the mail with the REST API.

Can I test email on staging without owning a domain or touching DNS?

Yes. A zero-setup subdomain such as yourteam.msdc.co receives mail immediately with no DNS changes, and it counts as your plan’s custom domain.

Will pointing qa.example.com at Mailsac affect our company email?

No. MX records apply to the exact name they are set on, so records on qa.example.com only route mail for addresses ending in @qa.example.com. Mail for @example.com keeps going to your existing provider.

Do I need to create each test address before using it?

No. Every address on a custom domain can receive mail; the first message creates it. Generate a unique address per test, for example with a timestamp, and read only that address’s messages.

Why are my test emails to @mailsac.com slow or failing in CI?

Public @mailsac.com addresses are shared and throttled at a lower threshold. Bursts from a test run are slowed and then refused with a 421 error. Sending to a verified custom domain or a private address raises the threshold enough that most customers never see throttling.

Can I point my domain’s MX records at Mailsac for free?

Yes, but without verification on a paid plan the mail is treated as public: anyone can read it, it is throttled like @mailsac.com and it is kept for at most 4 days. See free email for your domain. For private test mail, add the domain to a paid account and verify it.

How many test domains can we have?

Indie includes 1 custom domain, Business 5, Business+ 10 and Enterprise 12 or more. Extra domains cost $7 a month or $75 a year on any paid plan.

Give your tests their own domain

Start with a free account, then choose a plan with a custom domain when you’re ready. Indie is $18 a month for one developer; Business is $89 a month for a team, with SSO.