Mailsac vs Mailtrap
Mailsac vs Mailtrap
Mailtrap alternative for email testing
Mailtrap’s Email Sandbox traps the mail your app sends before it leaves. Mailsac receives real mail at real addresses, sent through your existing provider, and hands it to your tests over a REST API. Here is how the two compare on price, workflow and API, where Mailtrap is the better fit, and how to move existing tests.
Reviewed September 2026 against both vendors’ public pricing and documentation.
Free plan: an API key, public inboxes, one private address and 1,500 Ops a month, with no expiry. Jump to the full comparison, see how the workflow differs or move from Mailtrap Sandbox.
At a glance
What it is
Mailsac Hosted inboxes that receive real mail, plus SMTP capture
Mailtrap An SMTP sandbox that traps outgoing mail; sending and inbound are separate products
Tests the real delivery path
Mailsac Yes: your provider delivers to a Mailsac address
Mailtrap No: the sandbox stops the message at Mailtrap’s SMTP server
Free option
Mailsac Free plan, no expiry: 1,500 Ops a month
Mailtrap Sandbox Free: 50 test emails a month, one sandbox that keeps 10
Entry price
Mailsac Indie, $18 a month or $169 a year
Mailtrap Sandbox Basic, $17 a month or $168 a year
Your own test domain
Mailsac Every paid plan, from $18 a month
Mailtrap Not in Sandbox; a catch-all on your domain is part of the separate Inbound Email product
HTML check, spam score, previews
Mailsac Not offered
Mailtrap HTML Check and SpamAssassin report included; Device Previews as an add-on
SAML single sign-on
Mailsac Business, $89 a month
Mailtrap Sandbox Enterprise, $498 a month or $4,788 a year
Which should you choose?
Both let you see the email your app sends and check it from an automated test. They sit at different points in the path: Mailtrap Sandbox catches the message before it is sent anywhere, Mailsac receives it after your provider has delivered it. That difference decides most of what follows.
Choose Mailsac if
- You want end-to-end tests that prove the email was actually sent. Your app keeps its real provider and sends to a real address; if the provider rejects the message, the sending domain is wrong or the recipient is suppressed, the test fails. A sandbox that accepts everything cannot tell you that.
- Every test should get its own inbox with nothing to create first. Any
@mailsac.comaddress, and any address on your domain, receives mail and is read with one API call. Mailtrap gives you one shared sandbox on Free and Basic that you search by subject or recipient. - You want test addresses on your own domain, or on a subdomain you name such as
yourteam.msdc.cowith no DNS changes, from $18 a month. Mailtrap Sandbox has no custom domains; its sandbox addresses are atinbox.mailtrap.io. - Your suites receive a lot of mail. Business is $89 a month for 500,000 Ops (about 150,000 test emails), 5 users and 5 domains; Mailtrap Sandbox Team is $42 for 5,000 test emails and Business $123 for 50,000.
- You need SAML single sign-on at a published price. Business includes it with 5 team logins; Mailtrap Sandbox offers SSO only on Enterprise at $498 a month.
- Procurement wants published prices: Business+ at $1,900 a year or Enterprise from $7,500 a year, payable by invoice or purchase order, or through resellers SHI and SoftwareOne.
Choose Mailtrap if
- You want sending, testing and inbound email from one vendor. Mailtrap sells Email API/SMTP (transactional and bulk sending, with inbound email included), Email Sandbox and Email Marketing, and offers a bundle discount when you buy more than one. Mailsac only receives.
- You test templates, not just flows. The sandbox runs an HTML Check against email-client support data, a SpamAssassin spam report and a blacklist report on every captured message, shows headers and Bcc recipients, and can emulate bounces. Device Previews are a paid add-on on Business and Enterprise. Mailsac has none of these.
- You want an official SDK in your language that reads captured mail. Mailtrap lists SDKs for Node.js, Python, PHP, Ruby, Java, .NET, Go and Elixir. Mailsac has a JavaScript/TypeScript client and a Cypress plugin; other languages use the REST API.
- Your security review asks for SOC 2 or ISO 27001. Mailtrap states GDPR, ISO 27001 and SOC 2 Type II on every plan, including Free. Mailsac publishes no certification.
- Developers work offline. Mailtrap Local is a free, open-source sandbox that runs on your machine with SMTP, a web UI and a REST API. Mailsac is hosted only.
- Non-engineers review test mail. Sandboxes and projects are shared in the Mailtrap UI, and messages can be forwarded to whitelisted real inboxes on paid plans.
Mailsac vs Mailtrap: features and prices
Prices are list prices in US dollars, before tax, as each vendor shows them. Mailtrap prices are for the Email Sandbox product unless a row says otherwise. The two count usage in different units, so compare by the job you need done.
| Mailsac | Mailtrap | |
|---|---|---|
| Plans and prices | ||
| Free option | Free plan with no expiry: API key, public inboxes, 1 private address, 1,500 Ops a month, 50 stored messages | Sandbox Free, “free forever”: 50 test emails a month, 1 user, 1 sandbox that keeps 10 messages, 5 MB per message, no sandbox email address |
| Entry plan | Indie: $18 a month, or $169 a year. 25,000 Ops (about 7,500 test emails), 1 user, 1 custom domain, 1,000 stored messages | Sandbox Basic: $17 a month, or $14 a month billed yearly ($168). 500 test emails a month, 3 users, 1 sandbox that keeps 50 messages, sandbox email address, 100 forwards a month |
| Team plan | Business: $89 a month, or $840 a year. 500,000 Ops (about 150,000 test emails), 5 users, 5 domains, SAML single sign-on, 5,000 stored messages, load testing | Sandbox Team: $42 a month, or $34 billed yearly ($408). 5,000 test emails, 5 users, 5 sandboxes keeping 200 each. Sandbox Business: $123 a month, or $99 billed yearly ($1,188). 50,000 test emails, 50 users, 50 sandboxes keeping 600 each, sub-accounts |
| Top plans | Business+: $199 a month, or $1,900 a year. 2 million Ops, 10 users, 10 domains, 10,000 stored messages, invoice or purchase order on annual. Enterprise: from $7,500 a year (2 million Ops a month), or $799 a month by card. Published. 25 users, 12 or more domains; also sold by resellers SHI and SoftwareOne | Sandbox Enterprise: $498 a month, or $399 billed yearly ($4,788). Unlimited test emails and users, 300 sandboxes keeping 1,000 each, SSO, audit logs, 25 MB per message. Custom contracts and enterprise billing are offered to large senders through sales |
| Yearly billing | Yearly prices published; about 20% less than paying monthly | Yearly prices published for Sandbox; up to 20% less than monthly |
| What usage is counted | Ops. One Op is an API call, a message received at a private address or domain, or a webhook, Slack or WebSocket push. A polled test typically uses 3 to 6 Ops; pushed mail uses 1. Public @mailsac.com inboxes receive mail free |
Test emails captured a month, plus caps on sandboxes, messages kept per sandbox (oldest deleted first when full), messages per sandbox per 10 seconds (1, 10, 25, 50 or 150), forwards a month and message size. API calls are not metered; the general limit is 150 requests per 10 seconds per token |
| Inboxes and domains | ||
| How mail gets in | Your app sends through its own provider to a Mailsac address, and Mailsac receives it like any mail server. Or point a staging app’s SMTP at Email Capture and Mailsac keeps the mail instead of delivering it | Your app’s SMTP settings point at sandbox.smtp.mailtrap.io (ports 25, 465, 587 or 2525) with the sandbox’s own username and password, or your code POSTs to the Sandbox send API. From Basic, each sandbox also has an address such as myapp-12ab34@inbox.mailtrap.io that accepts mail from other systems, with +suffix aliases |
| Test address with no setup | Any @mailsac.com address (public) or any address on your custom domain (private). Each address is its own inbox; nothing to create before your app sends |
One sandbox on Free and Basic, 5 on Team, 50 on Business, 300 on Enterprise. Every recipient lands in the same sandbox; find your message with the list endpoint’s search on subject or recipient |
| Your own receiving domain | Indie and up: 1, 5, 10 or 12+ domains. Your own domain, or a yourteam.msdc.co subdomain that needs no DNS changes. Extra domains $7 a month |
Not in Sandbox. Mailtrap’s Inbound Email (included in Email API/SMTP plans, Free included) can create a catch-all inbox on a verified sending domain with an MX record; it shares the sending quota and is a separate API |
| Message retention | Public inbox mail is temporary and may be recycled quickly. Private addresses and domains keep mail up to the plan’s stored-message limit: 50 on Free, 1,000 on Indie, 5,000 on Business, 10,000 on Business+ | Each sandbox keeps 10, 50, 200, 600 or 1,000 messages by plan; when full, the oldest are deleted automatically |
| Who can read the mail | @mailsac.com inboxes: anyone. Private addresses, custom domains and private captured mail: your account and team only, in the Unified Inbox or over the API |
Your account. Sandboxes and projects can be shared with invited team members; messages can be forwarded to whitelisted real inboxes on paid plans |
| Test automation | ||
| API key header | Mailsac-Key |
Api-Token, or Authorization: Bearer |
| Official client libraries | @mailsac/api (JavaScript/TypeScript) and the @mailsac/cypress plugin. Any other language over REST |
SDKs for Node.js, Python, PHP, Ruby, Java, .NET, Go and Elixir; in Node, client.testing.messages lists messages and fetches text, HTML, raw, headers, spam report and HTML analysis |
| Waiting for new mail | Poll GET /api/addresses/{email}/messages (newest first) on any plan, or have a private address or domain push new mail to a WebSocket or webhook. The Cypress plugin waits for you |
Poll GET /api/sandboxes/{sandbox_id}/messages, 30 per page, with search, last_id and page. No wait endpoint or webhook is documented for Sandbox; webhooks are documented for the Inbound Email product |
| Message body and headers | /api/text/ for plain text, /api/body/ for sanitized HTML, /api/dirty/ for the original HTML, /api/raw/ for the SMTP message, /headers parsed as JSON |
Each message carries txt_path, html_path and raw_path; the SDKs fetch body.txt, body.html, body.raw, body.eml and mail_headers. SMTP transaction details and Bcc from Basic |
| Codes and links | Every message carries a links array of URLs found in its text and HTML. Codes are matched in your test, or with extractCode in the Cypress plugin |
Fetch the text or HTML body and match links and codes in your test |
| Webhooks and WebSockets | Webhooks and Slack forwarding on every plan. WebSockets per address on every plan; for a whole domain on Business and up | Sandbox: manual and automatic forwarding to whitelisted real addresses, 100 to 10,000 a month by plan. Inbound Email: signed webhooks on new messages |
| SMTP capture for staging | Email Capture on every plan: point a staging app’s SMTP at capture.mailsac.com:5587 (STARTTLS; your username and API key). Mail to any recipient lands in that recipient’s Mailsac inbox. Public unless private capture is on or the recipient is on your custom domain |
This is what Sandbox is: sandbox.smtp.mailtrap.io on ports 25, 465, 587 or 2525, with credentials per sandbox. Nothing is ever delivered |
| Sending mail | Receive only. New mail can be forwarded to a webhook, WebSocket, Slack or another Mailsac address | Email API/SMTP is a separate product: Free 4,000 emails a month (150 a day, shared between sending and receiving), Basic from $15 a month for 10,000, with transactional and bulk streams |
| Local, offline option | Hosted only | Mailtrap Local: free, open source, one binary with SMTP on localhost:3535, a web UI and a REST API; can push a captured message to the cloud sandbox |
| Beyond receiving email | ||
| HTML and CSS check | Not offered | HTML Check flags rules that email clients do not support and scores market support, using data from caniemail.com |
| Spam and blacklist reports | An experimental spam score from 0 to 1 on each message, and an API call to check whether a domain or IP is on a deny-list. No report |
SpamAssassin report with the score and the rules that fired (under 5 is considered good), plus a blacklist report for the sending domain and IP |
| Previews, bounces, load | Load testing on Business and up: mail sent at high rate is counted, not stored | Device Previews as a paid add-on on Business and Enterprise; Bounce Emulator; load testing documented on the Enterprise plan (150 messages per 10 seconds across 300 sandboxes) |
| Inbound email for apps and agents | This is the product: any address or domain in your account receives mail, read over the API, WebSockets or webhooks | Inbound Email, in Email API/SMTP plans: create an inbox at @inbound-mailtrap.io or a catch-all on your domain, then poll the API or receive webhooks. The docs say the UI is coming soon |
| Team, security and buying | ||
| Users | 1 on Free and Indie, 5 on Business, 10 on Business+, 25 or more on Enterprise | 1 on Free, 3 on Basic, 5 on Team, 50 on Business, unlimited on Enterprise |
| Single sign-on | SAML on Business and up (Okta, Azure AD, Google) | Sandbox Enterprise only |
| Certifications and hosting | None published. Runs on AWS in the United States. Enterprise includes help with SIG and CyberGRX security questionnaires | States GDPR, ISO 27001 and SOC 2 Type II on every plan, with a public trust center. Audit logs on Enterprise |
| Billing | Card. Invoice or purchase order on annual Business+ and Enterprise; resellers SHI and SoftwareOne | Card self-serve. Enterprise billing and custom contracts through sales. Bundle discount: 20% off the cheaper plan when you buy two products |
Reviewed September 28, 2026. Mailtrap Sandbox counts test emails, sandboxes and messages kept per sandbox; Mailsac counts Ops per month, including API calls. Check each vendor’s current pricing before you buy.
Sources: Mailtrap pricing, plan guide, Sandbox overview, Sandbox API, messages reference, sandbox email address, testing features, Inbound Email and Mailtrap Local. Mailsac pricing, API reference, custom domains and Email Capture.
How the workflow differs
Email testing is two questions: did the app produce the right message, and did the message actually go out? Mailtrap Sandbox answers the first. Mailsac answers both, because the message takes the same route it would take to a customer.
Mailtrap Sandbox
Trap the message before it is sent
- Change your app’s SMTP settings to
sandbox.smtp.mailtrap.iowith the sandbox’s username and password, or send through the Sandbox API. - The app sends to any address, real or made up. The message stops at Mailtrap and is never delivered.
- Your test lists the sandbox, finds the message by subject or recipient, and reads its text or HTML.
- The sandbox also reports HTML compatibility, spam score and headers, which is where Mailtrap earns its keep for template work.
What it cannot tell you: whether your provider would have sent the message, whether the sending domain and credentials in staging are right, or whether the recipient was suppressed, because none of that runs.
Mailsac
Receive the message after it is sent
- Leave your app’s email setup alone. It keeps sending through SES, SendGrid, Postmark or whatever it uses today.
- Your test picks a fresh recipient, such as
signup-1790000000000@yourteam.msdc.co, and triggers the sign-up, reset or one-time code. - The provider delivers to Mailsac, which is a normal mail server. Your test polls the address’s messages, or receives a WebSocket or webhook push.
- The test reads the text, follows the
linksarray or matches the code, then deletes the message.
What it proves: the message left your system and arrived, with the content and links it was supposed to have. These checks validate your application flow; they do not guarantee inbox placement at Gmail or Outlook.
Mailsac can also trap. When a staging build must never email anyone real, point its SMTP at Email Capture (capture.mailsac.com, port 5587) instead. Mailsac accepts the message and keeps it in the recipient’s inbox rather than delivering it, so the same tests read it the same way. That is the direct replacement for a Mailtrap sandbox; real delivery is the extra option. Mailsac does not send mail at all (it retired its outbound relay), so your existing provider stays in the picture.
Moving from Mailtrap Sandbox
Two things change: where the mail goes, and how the test reads it. Everything else in your app stays as it is. Here is the mapping for the SMTP settings and the Sandbox API calls most tests use.
| Mailsac | Mailtrap | |
|---|---|---|
| Where the mail goes | ||
| Real delivery | Keep your provider. Send to a Mailsac address: any @mailsac.com inbox, or anything@yourteam.msdc.co on your custom domain |
Not available in Sandbox; every message is trapped |
| SMTP capture settings | Host capture.mailsac.com, port 5587, STARTTLS, username = your Mailsac username, password = your API key. Some SMTP libraries require the From address to match the login; then use a private address or an address on your domain as the username |
Host sandbox.smtp.mailtrap.io, port 2525 (or 25, 465, 587), the sandbox’s username and password |
| Where the mail lands | In the inbox of each To address. Public unless you turn on Make Captured Email Private in account settings or the recipient is on your custom domain |
In the one sandbox whose credentials you used |
| Reading it from a test | ||
| Authenticate | Send Mailsac-Key: $MAILSAC_API_KEY on every request |
Api-Token: $MAILTRAP_TOKEN or Authorization: Bearer |
| Find the inbox | Nothing to look up: the address is the inbox | GET /api/sandboxes, or copy the sandbox ID from its URL |
| Wait for the message | Poll GET /api/addresses/{email}/messages every couple of seconds until it returns the message you expect, up to a deadline. The array is newest first |
Poll GET /api/sandboxes/{sandbox_id}/messages?search=… (matches subject, to_email, to_name; 30 per page, last_id or page for more) |
| Read one message | GET /api/addresses/{email}/messages/{messageId} |
GET /api/sandboxes/{sandbox_id}/messages/{message_id} |
| Read the body | GET /api/text/{email}/{messageId} for plain text; /api/body/ for sanitized HTML; /api/dirty/ for the original HTML; /api/raw/ for the whole SMTP message |
Follow the message’s txt_path, html_path or raw_path; in the SDKs, getTextMessage, getHtmlMessage, getRawMessage (body.txt, body.html, body.raw) |
| Headers | GET /api/addresses/{email}/messages/{messageId}/headers, parsed as JSON |
getMailHeaders (mail_headers); Tech info and Bcc from Basic |
| Extract links and codes | The links array on the message, found in both text and HTML. Match codes in your test, or with extractCode from @mailsac/cypress |
Match them in the fetched body |
| Spam and HTML reports | The experimental spam field on the message. No HTML report |
getSpamScore (spam_report) and getHtmlAnalysis (analyze) |
| Mark as read | PUT /api/addresses/{email}/messages/{messageId}/read/true |
PATCH …/messages/{message_id} with is_read, or the sandbox-wide Mark as read |
| Clean up | DELETE /api/addresses/{email}/messages/{messageId}, DELETE /api/addresses/{email}/messages for the inbox, or POST /api/domains/{domain}/delete-all-domain-mail |
DELETE …/messages/{message_id}, or PATCH /api/sandboxes/{sandbox_id}/clean to empty the sandbox |
| Search across everything | GET /api/inbox-filter (to, from and subject, AND), GET /api/inbox-search (OR), GET /api/domains/{domain}/messages |
The search parameter on the sandbox’s message list |
The wait step in TypeScript, with no client library · Node.js 18 or later · works for real delivery and for Email Capture · a standalone version of the loop in tests/inbox.ts in the CI example repository
const headers = { 'Mailsac-Key': process.env.MAILSAC_API_KEY! };
const address = `signup-${Date.now()}@yourteam.msdc.co`; // one address per test; nothing to create
const inbox = encodeURIComponent(address);
// Replaces: GET /api/sandboxes/{sandbox_id}/messages?search=... in a retry loop
async function waitForEmail(subjectIncludes: string, timeoutMs = 60_000) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const res = await fetch(`https://mailsac.com/api/addresses/${inbox}/messages`, { headers });
const messages: Array<{ _id: string; subject: string; links?: string[] }> = await res.json();
const m = messages.find((x) => x.subject.includes(subjectIncludes)); // newest first
if (m) {
const text = await (await fetch(`https://mailsac.com/api/text/${inbox}/${m._id}`, { headers })).text();
return { id: m._id, subject: m.subject, text, links: m.links ?? [] };
}
await new Promise((r) => setTimeout(r, 2_000));
}
throw new Error(`No email matching "${subjectIncludes}" for ${address} within ${timeoutMs / 1000}s`);
}
// after your app has sent to `address`, by real delivery or through Email Capture:
const email = await waitForEmail('Confirm your account');
const code = email.text.match(/\b\d{6}\b/)?.[0]; // one-time code
const link = email.links.find((l) => l.includes('/verify')); // confirmation link
Two habits to keep. Use a new address for every test so parallel runs and retries never read each other’s mail, and match the message you expect rather than taking whatever is newest. The playwright-signup-ci example generates a unique address per test, matches on the subject and deletes the message afterwards; the Playwright tutorial also filters by the time the email was triggered. For Cypress, the tested password-reset example does the same with @mailsac/cypress.
Public and private inboxes
A Mailtrap sandbox belongs to your account and only the people you share it with can see it. Mailsac works the other way round: mail to an @mailsac.com address is public by default. Anyone can view a public inbox on the Mailsac website without an account, and any Mailsac API key can read it. Public inboxes are temporary, and they are fine for trying things out with made-up data.
For password-reset links, codes and anything else that works on a real account, use a private address (the free plan includes one) or a custom domain: a msdc.co subdomain, or your own domain once it is verified. Only your account and team can read that mail, in the Unified Inbox or over the API. A custom domain is the closest match to a shared sandbox, and it lets every test use its own address with nothing to create first.
The same applies to Email Capture: captured mail is public unless you turn on Make Captured Email Private in account settings or the recipient is on your custom domain. If a staging build sends to real-looking customer addresses, enable that setting before you point it at Mailsac.
Public inboxes are for synthetic test data. If a reset link or code would work on a real account, or the email holds real personal data, use a private address or a verified private custom domain.
Frequently asked questions
Is Mailsac a drop-in replacement for Mailtrap Sandbox?
For the SMTP side, close to it: swap the sandbox host and credentials for capture.mailsac.com:5587 with your username and API key, and the same messages are captured. The test code changes, because Mailsac reads one inbox per address instead of one shared sandbox, and the endpoints and JSON differ. The mapping above covers the calls most tests use. If you also relied on HTML Check or the spam report, there is no equivalent.
Does Mailsac stop test email from reaching real people?
Through Email Capture, yes: nothing sent to it is delivered. In real-delivery mode your app is sending normally, so it only reaches Mailsac if the recipient is a Mailsac address. Use Email Capture for staging builds that might address real customers, and real delivery for tests that pick their own recipients on your test domain.
Which free plan is bigger?
They count different things. Mailtrap Sandbox Free allows 50 test emails a month in one sandbox that keeps 10 at a time. Mailsac’s free plan allows 1,500 Ops a month with no expiry; a polled test typically uses 3 to 6 Ops, so a few hundred tests a month, across as many addresses as you like. Public inboxes on the free plan are readable by anyone, so keep the data synthetic.
Can I keep test email private on Mailsac?
Yes. Use a private address (one is included free) or a custom domain, on Indie and up. A yourteam.msdc.co subdomain is ready immediately; your own domain works once DNS is verified. Mail on either is visible only to your account and team, and captured mail can be made private in account settings.
Does Mailsac check HTML rendering or spam score?
No. Each message carries an experimental spam score and the API can check a domain or IP against a deny-list, but there is no HTML compatibility report, spam rule breakdown or device preview. If those checks matter, Mailtrap Sandbox does them well. Some teams run both: Mailtrap for template review before a release, Mailsac for the end-to-end tests that run on every build.
Can I run email tests in parallel?
Yes. Give each test its own address, for example with a timestamp and random suffix, and each worker reads only its own inbox. There is no sandbox count or per-sandbox storage cap to plan around, but each received message and API call counts as an Op.
Is there a Playwright, Cypress or Selenium integration?
The @mailsac/cypress plugin waits for matching messages, verifies links and extracts one-time codes; the Cypress guide walks through a password-reset test with it. The Playwright guide and the Selenium guide use the REST API directly, and the playwright-signup-ci example runs the same sign-up test in GitHub Actions and GitLab CI.
Other comparisons and guides
- Mailsac vs Mailosaur
- Mailsac vs MailSlurp
- Mailsac vs Mailpit and MailHog
- Mailsac vs Mailinator
- Mailsac vs testmail.app
- Mailsac vs Mailisk
- Mailsac vs Temp Mail
- How the email testing API works
- Playwright email testing guide
- Cypress email testing guide
- Selenium sign-up test guide
- playwright-signup-ci example on GitHub
Try Mailsac with your next email test
Create a free account, generate an API key and run the wait step above against any address, or point a staging build at Email Capture. Plans with a private test domain start at $18 a month.