May 2026 Major Release

This release focuses on improving team account management, inbox performance, and frontend reliability across the Mailsac web app.

Summary

  • New “elevate to root” permission for safer admin delegation
  • Inbox UI rewritten with improved pagination and clarity
  • Faster debugging tools and message analytics
  • MFA enforcement tightened for account security

Features

Elevate to Root User

Team users can now be granted an “elevate to root” permission. This allows a user to temporarily assume root-level privileges within their session without exposing root account credentials.

Use cases:

  • Safer offboarding (no shared root access to rotate)
  • Delegating admin tasks without sharing credentials

Elevation is session-scoped and requires re-authentication.

Individual Inbox Refresh

The inbox UI has been rewritten on the new frontend framework.

Improvements:

  • Faster, more complete pagination and message navigation
  • Clearer indication of public vs private inboxes
  • Reduced UI latency when loading large inboxes

General Improvements

Continued migration to the new frontend framework across multiple app pages.

Faster loading for inbound message debugging and message count charts.

Direct access to forwarded inboxes from the Enhanced Addresses list.

POP3 settings consolidated into the Enhanced Address Management screen.

Security & Fixes

MFA is now required, as an additional security step, to remove MFA from both team and root accounts.

Fixed an issue where some inbound mail was not tracked correctly. As a result, Ops usage may increase for affected accounts.

Removed the spam feature due to low usage.

Upgraded frontend dependencies to address known security vulnerabilities.

Behavior Changes

Spam feature removed – account.disableSpam property no longer present.

Inbound message tracking corrected (may increase Ops usage as noted above).

March 2026 Release

We continue to enhance the Mailsac platform and have improved the performance of the throttling engine that is at the heart of our inbound email service. It helps us separate non-customer email from spam.

Streamline Email Testing in Healthcare with Mailsac

In healthcare, email communication intersects with patient care and data security. The margin for error is virtually nonexistent. Mailsac’s SaaS platform offers a robust email delivery suite, tailored to meet the rigorous demands of healthcare IT security, compliance, and operational efficiency. Mailsac has been integrated into systems at many enterprises in the healthcare industry, and has been relied on 24/7 for email testing for over a decade.

Enhanced Security and Compliance

Security Audits: Mailsac is built to pass IT department security audits, aligning with healthcare standards like HIPAA. Its infrastructure ensures patient data is safeguarded during email testing.

Data Privacy: With disposable email addresses, Mailsac supports testing that avoids exposing real patient information, maintaining privacy and compliance.

Collaborative Testing Environment

Unified Inbox: Devs and QAs can collaborate effectively using Mailsac’s unified inbox feature, which consolidates test emails from both persistent and temporary email accounts into a single view.

SSO Integration: Simplify access while enhancing security with Single Sign-On (SSO), allowing seamless integration into existing healthcare IT ecosystems.

Automated and Efficient Testing

CI/CD Integration: Mailsac’s API automates email tests within CI/CD pipelines, reducing manual effort and accelerating development cycles in fast-paced healthcare settings.

Scalable Solutions: Whether scaling up operations or integrating new services, Mailsac’s scalable platform adapts to the evolving needs of healthcare enterprises, ensuring email testing is never a bottleneck. There’s no need to manage server resources, deployments or upgrades.

Comprehensive Compatibility Testing

Device and Platform Coverage: Guarantee that critical communications are accessible across all devices and platforms used by healthcare professionals and patients alike.

Deliverability Assurance

Inbox Placement: Rigorous testing with Mailsac ensures healthcare emails achieve high deliverability, crucial for appointment reminders, test results, and other sensitive communications.

Optimizing Patient Communication

Email Optimization: Test and refine email content for clarity and engagement, ensuring messages to patients are both accessible and actionable.

Conclusion

For healthcare organizations, Mailsac offers a precision toolset for email testing — ensuring security, efficiency, and compliance while enhancing collaborative efforts between QA and development teams. Since 2012, Mailsac has practiced technical excellence and has helped hundreds of customers in healthcare manage their unique challenges.

10 Common Email Testing Pitfalls and How to Avoid Them

Email testing is an essential step in the QA process, ensuring that communications reach their intended recipients accurately and efficiently. However, even experienced QA teams can fall into common traps that undermine their efforts. Here are ten frequent email testing pitfalls and strategic ways to avoid them, streamlining your workflow and enhancing email reliability.

1. Ignoring Mobile Responsiveness

Pitfall:

Not testing how emails render on mobile devices, leading to formatting issues or poor user experiences.

Solution:

Use email testing tools that simulate various mobile devices and screen sizes to ensure your emails look great everywhere.

2. Overlooking Email Client Diversity

Pitfall:

Focusing on a single email client, ignoring the fact that your audience uses a wide range of email services with different rendering engines.

Solution:

Test emails across multiple clients (like Gmail, Outlook, Yahoo) to identify and fix client-specific issues.

3. Neglecting Deliverability Tests

Pitfall:

Assuming emails reach the inbox without verifying, risking them being flagged as spam.

Solution:

Conduct deliverability tests with tools that provide insights into spam scores and help optimize for better inbox placement.

4. Underestimating the Importance of Content Clarity

Pitfall:

Creating content that’s confusing or misleading, leading to poor user engagement.

Solution:

Ensure your messages are clear, concise, and actionable. Test variations to see which performs best in terms of user engagement.

5. Skipping Accessibility Checks

Pitfall:

Forgetting to make emails accessible to all users, including those with disabilities.

Solution:

Include text alternatives for images, use sufficient contrast ratios, and test with screen readers to ensure accessibility.

6. Failing to Test Links and Attachments

Pitfall:

Assuming all links and attachments work without thoroughly testing them, which could lead to a frustrating user experience.

Solution:

Manually check each link and attachment in different environments to ensure functionality and security.

7. Ignoring Email Load Times

Pitfall:

Overloading emails with high-resolution images or complex HTML, leading to slow loading times.

Solution:

Optimize images and streamline code to improve load times, ensuring a smooth user experience.

8. Forgetting to Validate Email Lists

Pitfall:

Sending tests to outdated or incorrect email addresses, skewing testing results.

Solution:

Regularly cleanse and validate your email lists to ensure accuracy and relevance.

9. Overlooking Privacy and Compliance

Pitfall:

Neglecting privacy laws and email regulations, risking legal issues and damaged reputation.

Solution:

Stay informed about regulations like GDPR and CAN-SPAM, ensuring your email practices are compliant.

10. Not Leveraging Automation

Pitfall:

Performing repetitive tests manually, which is time-consuming and prone to human error.

Solution:

Incorporate automated testing workflows to save time, reduce errors, and increase efficiency.

In Conclusion

By being mindful of these common pitfalls and implementing the suggested solutions, QA teams can significantly improve their email testing processes. Tools like Mailsac offer zero-configuration custom private domains, comprehensive Swagger REST APIs, and a generous free tier, making it easier for teams to test emails effectively and efficiently. Remember, the goal is not just to send emails but to ensure they are delivered, readable, and engaging across all devices and clients.

Email testing in CI/CD pipelines: a step-by-step guide with GitHub Actions and GitLab CI

Every signup, password reset and invite flow ends in an email, and that email is the step most end-to-end suites skip. This guide adds it to your pipeline. You will test four things about the email your app sends, run those tests in two layers (a local SMTP catcher on every pull request, and hosted Mailsac inboxes for capture and real-delivery checks), and wire both into GitHub Actions and GitLab CI.

The complete project is the playwright-signup-ci example in Mailsac’s integration-test examples repository: a small Express app that sends a verification link and code, one Playwright test, and both CI configurations. Every code block below is copied from it. Clone it, or copy the pieces into your own repository.

What to test in an email

Four things break, roughly in this order:

  1. The link. The URL in the email must open the right page with a valid token. The classic bug is an email that says http://localhost:3000/verify?... because the deployed environment inherited a development APP_URL.
  2. The code. The 6-digit code in the email must be the one the app accepts, and it must still be accepted after the email has been rendered, wrapped and copied.
  3. The content. The subject, sender and recipient are right, there is a plain-text part, and no {{firstName}} placeholders leak through.
  4. Delivery. The email actually leaves the app through your email provider, with the credentials, sending domain and DNS records (SPF and DKIM) you ship with, and lands in a real mailbox.

The first three can be tested without any mail leaving CI. The fourth cannot. That is why this guide uses two layers.

Two layers, three CI jobs

Layer CI job Runs Mail goes to Proves
Local SMTP catcher mailpit every pull request a Mailpit service container beside the app, port 1025 the app sends the right email with a working link and code
Hosted test inbox mailsac-capture every run where MAILSAC_API_KEY is set Mailsac Email Capture: the app’s SMTP points at capture.mailsac.com:5587; the test reads the message over the Mailsac API the same, with inboxes that any runner or person can read from anywhere
Hosted test inbox real-delivery pushes to main, a daily schedule, manual runs your deployed staging app sends through its real provider to a Mailsac inbox delivery works: provider credentials, sending domain, SPF and DKIM

The local layer is fast and never leaves CI. The hosted layer catches what a local catcher cannot: expired provider credentials, DNS mistakes, a throttled or blocked sending domain, and templates that only break in production. The test code is identical in all three jobs; only environment variables change.

The example app and the test

The app under test is app/server.js: an Express form at / that takes an email address, then sends a message containing a confirmation link (/verify?token=...) and a 6-digit code with Nodemailer. It reads SMTP_HOST, SMTP_PORT, SMTP_SECURE, SMTP_USER and SMTP_PASS from the environment, plus APP_URL for the link and MAIL_FROM for the sender, so the same code sends to Mailpit, to Mailsac Email Capture, or to your real provider without changes.

The test reaches inboxes through one small interface in tests/inbox.ts. Excerpt from tests/inbox.ts (the interface, the address generator and the backend switch):

export interface TestInbox {
  /** A new, unique address for one test. */
  newAddress(prefix?: string): string;
  /** Poll until an email for `address` arrives (optionally matching the subject). */
  waitForEmail(address: string, opts?: { subject?: string | RegExp; timeoutMs?: number }): Promise<ReceivedEmail>;
  /** Remove the message after the test, so private inboxes stay tidy. */
  cleanup(address: string, id: string): Promise<void>;
}

const unique = (prefix: string) =>
  `${prefix}-${Date.now().toString(36)}-${randomBytes(4).toString('hex')}`.toLowerCase();

// ...

export const testInbox = (): TestInbox => (process.env.INBOX === 'mailpit' ? new MailpitInbox() : new MailsacInbox());

MailsacInbox builds addresses on MAILSAC_DOMAIN (default mailsac.com) and uses three REST calls, each with your key in the Mailsac-Key header:

  • GET https://mailsac.com/api/addresses/{email}/messages lists the inbox, newest first, with a links array per message that Mailsac extracted from the text and HTML. Nothing has to be created before your app sends to the address.
  • GET https://mailsac.com/api/text/{email}/{messageId} returns the plain text, which is where the code is matched.
  • DELETE https://mailsac.com/api/addresses/{email}/messages/{messageId} removes the message when the test is done.

The wait is a plain polling loop. Excerpt from tests/inbox.ts (MailsacInbox.waitForEmail):

  async waitForEmail(address: string, { subject, timeoutMs = 60_000 }: { subject?: string | RegExp; timeoutMs?: number } = {}) {
    const inbox = encodeURIComponent(address);
    const deadline = Date.now() + timeoutMs;
    while (Date.now() < deadline) {
      const messages: Array<{ _id: string; subject: string; links?: string[] }> =
        await (await this.api(`/addresses/${inbox}/messages`)).json();
      const message = messages.find((m) => matches(m.subject || '', subject));
      if (message) {
        const text = await (await this.api(`/text/${inbox}/${encodeURIComponent(message._id)}`)).text();
        return { id: message._id, subject: message.subject, text, links: message.links?.length ? message.links : extractLinks(text) };
      }
      await sleep(2_000);
    }
    throw new Error(`No email for ${address} within ${timeoutMs / 1000}s`);
  }

MailpitInbox does the same against a local Mailpit at MAILPIT_URL (default http://localhost:8025): GET /api/v1/search?query=to:"{address}", GET /api/v1/message/{ID} and DELETE /api/v1/messages, polling every 500 ms for up to 30 seconds. The whole file is about 110 lines and needs nothing beyond Node’s built-in fetch.

The test itself is tests/signup.spec.ts, complete:

// End-to-end signup verification: sign up with a fresh address, wait for the
// verification email, then confirm the account with the link and with the code.
import { test, expect } from '@playwright/test';
import { testInbox } from './inbox';

const inbox = testInbox();

test.describe('signup verification email', () => {
  test('arrives and its link verifies the account', async ({ page }) => {
    const address = inbox.newAddress('signup-link');

    await page.goto('/');
    await page.getByLabel('Email').fill(address);
    await page.getByRole('button', { name: 'Sign up' }).click();
    await expect(page.getByRole('heading', { name: 'Check your email' })).toBeVisible();

    const email = await inbox.waitForEmail(address, { subject: 'Confirm your email address' });
    // assert on content, not only on arrival
    expect(email.text).toContain('Confirm your email address');
    const link = email.links.find((l) => l.includes('/verify?token='));
    expect(link, 'verification link in the email').toBeTruthy();

    await page.goto(link!);
    await expect(page.getByRole('heading', { name: 'Email verified' })).toBeVisible();
    await expect(page.getByText(address)).toBeVisible();

    await inbox.cleanup(address, email.id);
  });

  test('arrives with a 6-digit code that verifies the account', async ({ page }) => {
    const address = inbox.newAddress('signup-code');

    await page.goto('/');
    await page.getByLabel('Email').fill(address);
    await page.getByRole('button', { name: 'Sign up' }).click();

    const email = await inbox.waitForEmail(address, { subject: 'Confirm your email address' });
    const code = email.text.match(/\b(\d{6})\b/)?.[1];
    expect(code, '6-digit code in the email').toMatch(/^\d{6}$/);

    await page.getByLabel('6-digit code').fill(code!);
    await page.getByRole('button', { name: 'Verify' }).click();
    await expect(page.getByRole('heading', { name: 'Email verified' })).toBeVisible();

    await inbox.cleanup(address, email.id);
  });
});

playwright.config.ts starts the example app unless APP_URL points at a deployed one, allows one retry on CI, writes an HTML report on CI, and sets the test timeout above the 60-second email wait so a missing email fails with the helper’s clear message rather than a generic timeout:

import { defineConfig } from '@playwright/test';

const PORT = Number(process.env.PORT || 3000);

export default defineConfig({
  testDir: './tests',
  timeout: 90_000,
  retries: process.env.CI ? 1 : 0,
  reporter: process.env.CI ? [['list'], ['html', { open: 'never' }]] : 'list',
  use: { baseURL: process.env.APP_URL || `http://localhost:${PORT}` },
  // Starts the example app. In your project, point baseURL at your own app or staging URL
  // and remove webServer if the app is already running.
  webServer: process.env.APP_URL
    ? undefined
    : { command: 'node app/server.js', url: `http://localhost:${PORT}`, reuseExistingServer: !process.env.CI },
});

Run it locally

After cd playwright-signup-ci, npm ci and npx playwright install chromium, the three ways to run it are, from the example’s README:

With Mailpit, no account needed:

docker run -d -p 1025:1025 -p 8025:8025 axllent/mailpit
INBOX=mailpit SMTP_HOST=localhost SMTP_PORT=1025 npx playwright test

With Mailsac, sending through Email Capture, which keeps every message in Mailsac instead of delivering it:

export MAILSAC_API_KEY=...            # your API key
export SMTP_HOST=capture.mailsac.com SMTP_PORT=5587 SMTP_USER=your-mailsac-username SMTP_PASS=$MAILSAC_API_KEY
npx playwright test

Against your deployed app, which sends through your real provider to a Mailsac inbox:

APP_URL=https://staging.example.com MAILSAC_API_KEY=... npx playwright test

The example’s .env.example lists the same variables for a local .env; the only secret among them is the API key, which Email Capture also uses as the SMTP password.

GitHub Actions

Add the repository secret MAILSAC_API_KEY and the repository variables MAILSAC_USERNAME (for Email Capture), MAILSAC_DOMAIN (your private domain, optional) and STAGING_URL (for the real-delivery job) under Settings, Secrets and variables, Actions. Save this as .github/workflows/email-tests.yml. It is the example’s workflow file without the paths filters, the defaults.run.working-directory block, the cache-dependency-path lines, the two working-directory: . lines and the folder prefix on the report path, which exist there only because the example sits in the playwright-signup-ci/ subfolder of a larger repository:

name: Playwright signup email tests (playwright-signup-ci)

on:
  pull_request:
  push:
    branches: [main]
  schedule:
    - cron: "17 6 * * *" # daily real-delivery check
  workflow_dispatch:

jobs:
  # 1. Every pull request: a local SMTP catcher. Fast, free, nothing leaves CI.
  #    Proves the app sends the right email with a working link and code.
  mailpit:
    runs-on: ubuntu-latest
    services:
      mailpit:
        image: axllent/mailpit:latest
        ports:
          - 1025:1025
          - 8025:8025
    env:
      INBOX: mailpit
      SMTP_HOST: localhost
      SMTP_PORT: "1025"
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npx playwright install --with-deps chromium
      - run: npx playwright test
      - uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: playwright-report-mailpit
          path: playwright-report

  # 2. Hosted inboxes with Mailsac Email Capture: the app sends to capture.mailsac.com
  #    and the test reads the message over the Mailsac API from any runner.
  #    Needs the repository secret MAILSAC_API_KEY and variable MAILSAC_USERNAME.
  mailsac-capture:
    runs-on: ubuntu-latest
    env:
      MAILSAC_API_KEY: ${{ secrets.MAILSAC_API_KEY }}
      MAILSAC_DOMAIN: ${{ vars.MAILSAC_DOMAIN }}
      SMTP_HOST: capture.mailsac.com
      SMTP_PORT: "5587"
      SMTP_USER: ${{ vars.MAILSAC_USERNAME }}
      SMTP_PASS: ${{ secrets.MAILSAC_API_KEY }}
    steps:
      - name: Skip when Mailsac is not configured
        id: configured
        run: echo "ok=${{ env.MAILSAC_API_KEY != '' }}" >> "$GITHUB_OUTPUT"
      - uses: actions/checkout@v4
        if: steps.configured.outputs.ok == 'true'
      - uses: actions/setup-node@v4
        if: steps.configured.outputs.ok == 'true'
        with:
          node-version: 22
          cache: npm
      - run: npm ci
        if: steps.configured.outputs.ok == 'true'
      - run: npx playwright install --with-deps chromium
        if: steps.configured.outputs.ok == 'true'
      - run: npx playwright test
        if: steps.configured.outputs.ok == 'true'

  # 3. Real delivery, daily and on main: sign up on your deployed staging app, which sends
  #    through your real email provider (SES, SendGrid, Postmark...) to a Mailsac inbox.
  #    Catches expired provider credentials, DNS/SPF/DKIM problems and blocked sending domains.
  #    Needs MAILSAC_API_KEY and the variable STAGING_URL. A private Mailsac domain
  #    (MAILSAC_DOMAIN) keeps the mail from real signups out of public inboxes.
  real-delivery:
    if: github.event_name != 'pull_request'
    runs-on: ubuntu-latest
    env:
      MAILSAC_API_KEY: ${{ secrets.MAILSAC_API_KEY }}
      MAILSAC_DOMAIN: ${{ vars.MAILSAC_DOMAIN }}
      APP_URL: ${{ vars.STAGING_URL }}
    steps:
      - name: Skip when staging is not configured
        id: configured
        run: echo "ok=${{ env.MAILSAC_API_KEY != '' && env.APP_URL != '' }}" >> "$GITHUB_OUTPUT"
      - uses: actions/checkout@v4
        if: steps.configured.outputs.ok == 'true'
      - uses: actions/setup-node@v4
        if: steps.configured.outputs.ok == 'true'
        with:
          node-version: 22
          cache: npm
      - run: npm ci
        if: steps.configured.outputs.ok == 'true'
      - run: npx playwright install --with-deps chromium
        if: steps.configured.outputs.ok == 'true'
      - run: npx playwright test
        if: steps.configured.outputs.ok == 'true'

Three things to notice:

  • mailpit starts Mailpit as a service container. On a Linux runner its ports are published on localhost, so the app sends to localhost:1025 and the test reads from localhost:8025. It needs no secrets, so it runs on every pull request, including ones from forks.
  • mailsac-capture runs the app inside the job with its SMTP pointed at Email Capture. SMTP_USER is your Mailsac username and SMTP_PASS is the API key. Mail to any recipient is captured into that recipient’s Mailsac inbox rather than delivered, and the test reads it with the same API it would use for real delivery. The first step checks whether the secret is present and every later step is skipped if not, so a fork without secrets gets a green skip instead of a failure.
  • real-delivery does not start the app at all. APP_URL is set from the STAGING_URL variable, so Playwright signs up on your deployed staging environment, which sends through whatever provider and domain it is configured with. That is the point of the job. It is limited to pushes, the daily schedule and manual runs, because pull requests from forks never see the secret anyway.

GitLab CI

Set MAILSAC_API_KEY (masked) and MAILSAC_USERNAME as CI/CD variables under Settings, CI/CD, Variables, add STAGING_URL and schedule a pipeline for the real-delivery job. GitLab reads .gitlab-ci.yml from the repository root, so the example keeps its copy in its folder as a template to copy to the root of your project. Complete:

# GitLab CI template for this example. GitLab reads .gitlab-ci.yml from the repository root:
# copy this file there in your own project (paths below assume the example is the project root).
# The same two layers on GitLab CI. Set MAILSAC_API_KEY (masked) and MAILSAC_USERNAME
# as CI/CD variables; STAGING_URL enables the scheduled real-delivery job.
default:
  image: mcr.microsoft.com/playwright:v1.63.0-noble
  before_script:
    - npm ci

email-tests:mailpit:
  services:
    - name: axllent/mailpit:latest
      alias: mailpit
  variables:
    INBOX: mailpit
    MAILPIT_URL: http://mailpit:8025
    SMTP_HOST: mailpit
    SMTP_PORT: "1025"
  script:
    - npx playwright test
  artifacts:
    when: on_failure
    paths: [playwright-report/]

email-tests:mailsac-capture:
  rules:
    - if: $MAILSAC_API_KEY
  variables:
    SMTP_HOST: capture.mailsac.com
    SMTP_PORT: "5587"
  script:
    - SMTP_USER="$MAILSAC_USERNAME" SMTP_PASS="$MAILSAC_API_KEY" npx playwright test

email-tests:real-delivery:
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule" && $MAILSAC_API_KEY && $STAGING_URL
  script:
    - APP_URL="$STAGING_URL" npx playwright test

In GitLab a service is reachable by its alias rather than localhost, so the app sends to mailpit:1025 and the test reads from mailpit:8025. Playwright’s Docker image already contains the browsers, which is why there is no playwright install step; its tag matches the @playwright/test version pinned in package.json (1.63.0), and the two must move together. The rules: blocks make the hosted jobs appear only when their variables exist, and the real-delivery job only on scheduled pipelines.

Handling secrets

  • The Mailsac API key is used only by the test runner, which runs in Node, and by the app’s SMTP transport. It never reaches the browser or the page under test.
  • The key is the SMTP password for Email Capture. MAILSAC_USERNAME is not a secret, but keep the key masked everywhere it appears.
  • Use one key per pipeline. Business plans and up have multiple named API keys, so a leaked key can be rotated without touching other pipelines.
  • Pull requests from forks do not get repository secrets. The mailsac-capture job skips itself when the key is empty, and real-delivery does not run on pull requests at all. In GitLab, mark the variables protected so only protected branches and schedules see them.
  • Treat test output as sensitive. The HTML report is uploaded only on failure and this config records no traces, screenshots or videos. If you enable traces, remember they capture the codes typed and the links opened, including password-reset links. Do not log email bodies.
  • Prefer a private domain (below) so the messages themselves are not readable by anyone who guesses an address.

Keeping email tests from flaking

Email tests fail for timing reasons far more often than for product reasons. These habits remove most of it:

  • A new address for every test. newAddress() builds one from a prefix, a base-36 timestamp and 4 random bytes, for example [email protected]. Parallel workers and retries then never read each other’s mail, and you never have to ask which of five messages is yours. Never share one fixed inbox across tests.
  • Poll with a deadline, not a sleep. waitForEmail checks every 2 seconds and gives up after 60 seconds (every 500 ms for 30 seconds with Mailpit). A fixed sleep(10000) is both too slow on good days and too short on bad ones.
  • Match on more than “a message exists”. The test filters by subject. If your inbox can hold older mail, also record a timestamp before the trigger and ignore anything received earlier, as the Playwright tutorial does.
  • Set the test timeout above the email wait. The config uses 90 seconds against a 60-second wait. Otherwise Playwright’s generic timeout fires first and hides the useful error, which names the address and the deadline.
  • Assert on content, not only arrival. The test checks the subject text, the link path and the code format before using them.
  • Clean up. Each test deletes its message at the end. On Mailsac this keeps private inboxes inside the plan’s stored-message limit (1,000 on Indie, 5,000 on Business). Move cleanup into test.afterEach if you want it to run even when an assertion fails.
  • Retries are safe only because addresses are fresh. The config allows one retry on CI. A retry re-runs the whole test with a new address, so it cannot read the previous attempt’s email. For a slow provider, a longer deadline is the better fix.
  • Check the provider when nothing arrives. Sandbox and test modes on some providers accept the message and deliver nothing. The error tells you which address it waited for; compare it with the provider’s log.
  • Public inboxes are throttled. A busy suite pointed at @mailsac.com can see mail delayed by up to about a minute. Run busy suites on a custom domain, which also has higher inbound limits.

Private domain or public inbox

Where the test email goes decides who else can read it.

  • Public @mailsac.com addresses work on every plan, including the free one, with no setup, and are the default when MAILSAC_DOMAIN is unset. Anyone can open a public inbox on the Mailsac website, and messages are temporary. Use them for a first run and for made-up accounts only.
  • A private address (POST /api/addresses/{email}, one included free) is readable only by your account. It suits one fixed test account, not a fresh address per test.
  • A custom domain, on Indie ($18 a month) and up, gives every test its own private address. A zero-setup yourteam.msdc.co subdomain receives mail immediately; your own domain works once its DNS is verified. Set MAILSAC_DOMAIN and nothing else changes. It also gets past signup forms that reject well-known disposable-email domains.

Each received message, API call and webhook or WebSocket push counts as one Op. A test that polls every 2 seconds typically uses 3 to 6 Ops for a message that arrives within a few seconds, plus one per extra poll if delivery is slow. The free plan’s 1,500 covers a few hundred runs a month, and Indie’s 25,000 covers a delivery check on every merge for most teams. Turning on webhook or WebSocket forwarding for a private address or domain delivers each message for one Op and removes the polling.

Next steps

Create a free Mailsac account to get an API key, add it to your pipeline as a secret, and run the delivery check on your next merge.


The Complete Checklist for Email Testing in QA Projects

Email remains a critical communication tool in business, making its reliability and functionality crucial for a wide range of applications. For QA teams, ensuring that emails are sent, received, and displayed as intended across various environments and platforms is a non-negotiable part of the software development process. This checklist provides a comprehensive guide for QA professionals to thoroughly test email functionality, ensuring a seamless user experience.

1. Preparation and Planning

  • Define Objectives: Clearly outline what you need to test, such as deliverability, content, links, and attachments.
  • Identify Email Scenarios: List all the scenarios in which an email would be sent. This includes transactional emails, marketing emails, notifications, and any others specific to your application.
  • Understand the Audience: Know the email clients (e.g., Gmail, Outlook) and devices (e.g., smartphones, tablets) your audience uses.

2. Functional Testing

  • Deliverability: Ensure emails reach the recipient’s inbox, not the spam folder.
  • Send and Receive Verification: Confirm that emails are sent and received without errors in all scenarios.
  • Link and Attachment Testing: Check all links and attachments for correct functionality and security.
  • Formatting and Layout: Verify that emails display correctly across different email clients and devices.
  • Accessibility Testing: Ensure emails are accessible, including alternative text for images and readable fonts for those with visual impairments.

3. Content and Design Testing

  • Spelling and Grammar: Verify the accuracy of content, including spelling and grammar.
  • Branding Consistency: Ensure the email design aligns with your brand’s guidelines and messaging.
  • Responsive Design: Test emails on various screen sizes to ensure the design is responsive and elements are clickable.

4. Security and Compliance Testing

  • Data Protection: Confirm that personal data is handled securely, in compliance with laws like GDPR.
  • Email Authentication: Check for SPF, DKIM, and DMARC records to prevent phishing and ensure sender authenticity.

5. Performance Testing

  • Load Testing: Assess the system’s ability to handle high volumes of emails without performance degradation.
  • Speed Testing: Evaluate the time taken to send, receive, and load emails, ensuring it meets user expectations.

6. Integration and Automation Testing

  • Integration Checks: Verify that email functionality integrates seamlessly with other systems and workflows.
  • Automation Suitability: Identify processes that can be automated, such as regression tests for email functionalities.

7. User Acceptance Testing

  • Real User Simulation: Conduct tests that mimic real-user scenarios to ensure the email meets user needs and expectations.
  • Feedback Collection: Gather and incorporate feedback from actual users to refine email functionality.

Review

Email testing is a critical component of QA that ensures your application communicates effectively and reliably with users. By following this comprehensive checklist, QA teams can systematically address and rectify potential issues, enhancing the overall user experience.

Interested in simplifying and accelerating your email testing process? Mailsac offers a robust platform designed to streamline email testing for QA teams. With features like disposable email addresses, zero-setup custom domain support, and extensive API access, Mailsac enables you to focus on what matters most—delivering a flawless product. Try Mailsac for free today, getting test email in seconds, and discover how we can elevate your QA email testing to the next level.

Why Professional QAs and Software Devs May Choose Mailsac Over Disposable Email

Email deliverability testing, and QA testing web apps with multiple account permissions, are critical aspects of software development and Quality Assurance (QA). Although disposable email websites and gmail addresses are a common choice for this task, they present several significant drawbacks for enterprises. This article will detail the advantages of using dedicated email deliverability platforms like Mailsac instead.

Limitations of Disposable Email

1. Security and Privacy

Disposable email platforms typically make all emails public. These websites are frequently crawled by scammers to acquire sensitive information.

Disposable email services often lack robust security measures, exposing sensitive test data. This lack of security can compromise the integrity of testing and risk breaches of confidential information. They rely on security through obscurity – random email addresses that are hopefully unguessable.

Disposable email providers typically do not have Information Security and Assurance programs, and cannot pass a Vendor Risk Assessment.

2. Business Agreements

The terms of service for disposable email services are often unsuitable for professional development and testing contexts. They can include problematic clauses and offer limited protections for users, which isn’t ideal for businesses. The terms and privacy policies tend to be non-negotiable.

3. B2B Interfaces

Disposable email services often lack capabilities for Business-to-Business (B2B) interfacing. This limitation can hinder the integration of these services into larger, automated testing suites, significantly limiting their usefulness in professional testing scenarios.

4. Uptime and Performance

Disposable email services are often slow and lack reliable uptime. These performance issues can introduce unnecessary delays into the testing process and create uncertainties around the reliability of test results. If an email was delayed, it can be hard to know if it was on your end, or theirs.

Advantages of Using Mailsac

Mailsac, as a dedicated email deliverability platform, provides a solution to these limitations and offers considerable advantages for professional QAs and software devs.

1. Enhanced Security

Mailsac prioritizes security, providing secure paid private inboxes and whole subdomains for testing.

You can test your application’s email functionality without risking sensitive data being leaked or public, or sold to a data broker.

2. Professional Business Agreements

Mailsac offers business-friendly terms of service, custom terms, P.O.s, multiple users, SSO and other features designed with the needs of professional QAs and software developers in larger companies with legal and security requirements. This provides a more suitable environment for business operations and testing.

3. Integration and functional testing

Mailsac provides powerful REST APIs, webhooks, and web sockets for integrating into CI/CD and workflows. Companies frequently integrate mailsac seamlessly into their automated testing suite. Using a consumer disposable provider often results in unexpectedly failed builds. Using a professional provider gives you comprehensive and efficient testing and enables continuous deployment.

4. Reliable Performance

Mailsac has high uptime and quick API and UI performance, ensuring a smooth and reliable email testing process. We believe performance is a feature.

5. Share test environment account email addresses

When you are testing a web application, you can use email addresses that are private to your Mailsac account to sign up for your app. Then share those inboxes with your teammates. For example, you may be testing a web app with two RBAC roles – administrator and readonly user. Each can have a unique mailsac email address. Your web app sends a sign-in link via email. All team members can access it (using mailsac’s multi-user or SSO feature). And since it’s not disposable email, the sign-in link to your app’s dev environment won’t be public.

While disposable email services may appear convenient, they come with considerable drawbacks for professional QAs and software devs. They can be against company policies because they may leak proprietary business information. Mailsac, with its robust features and focus on business needs, provides a far more effective solution for email deliverability testing.

QA Testing Email Deliverability using Mailsac: An Overview for QA Managers

The importance of Quality Assurance (QA) testing in software development and operations cannot be overstated. It ensures the product or system performs as expected, minimizing the risk of unexpected failures in production environments. A crucial aspect of QA testing involves testing email deliverability. This article will focus on how to use Mailsac, a leading tool in email testing, to execute this task effectively.

What is Mailsac?

Mailsac is a service providing temporary, “for-test-only” email addresses that can be used for testing and development purposes. Mailsac’s uniqueness lies in its capability to accept emails sent to any unique, auto-generated email addresses under its domain, thus eliminating the need for pre-generating email addresses or setting up a dedicated testing email server.

Why Use Mailsac for Email Deliverability Testing?

Email deliverability testing is vital to ensure emails are correctly dispatched from your application and are appropriately received by your users. Mailsac offers the flexibility to test various email formats and content, inspect the received emails, and verify they are correctly formatted and contain the correct data. This helps mitigate common issues such as emails being marked as spam, lost emails, or broken email formats.

How to Perform QA Testing with Mailsac

Let’s delve into the steps to conduct QA testing for email deliverability using Mailsac.

Step 1: Set Up a Mailsac Account

First and foremost, you need to create a Mailsac account. Visit the Mailsac website and follow the sign-up instructions.

Step 2: Send Emails to Mailsac

Next, send emails from your application to any addresses on the mailsac.com domain. Mailsac is designed in such a way that you don’t need to pre-generate the email addresses. Just decide on the address you want to use and send the email. The inbox will be created automatically when an email is received.

You can send the emails from anywhere, too – personal or work addresses, fake senders, CLI tools, software applications – without a separate sending gateway.

Step 3: Check Email Deliverability

After sending the emails, you can verify their delivery in the Mailsac interface. Here, you can view the received emails, check their contents, and confirm they are correctly formatted. Mailsac also enables you to check if attachments are included correctly using the Unified Inbox or API, and whether the links and images in the email are functioning properly.

Advanced Testing with Mailsac API

For more sophisticated or comprehensive testing, Mailsac offers a robust JSON REST API and Web Socket API. This empowers you to automate the process of sending emails, checking their delivery, and verifying their contents. These API calls can be integrated into your automated testing suite, enabling you to conduct in-depth email deliverability tests as a part of your regular testing process.

Wrapping Up

Mailsac presents a powerful and versatile method to test email deliverability as a part of your QA process. It allows you to send emails to any address on its domain, and the inboxes are created automatically when an email is received. By integrating Mailsac into your QA testing, you can significantly enhance the quality and reliability of your email notifications, thus offering a better user experience. Sign up and start receiving email in seconds.

Unveiling Mailsac’s New API Endpoint Feature: Inbox Filter

A look at filtering email messages with the Mailsac API

Mailsac has rolled out a new API endpoint feature, dubbed “inbox filter.”

It limits email messages using the to, from, and subject fields. Say goodbye to the conventional OR logic of /api/inbox-search and embrace the power of logical AND.

The Inbox Filter Endpoint: Technical Breakdown

The /api/inbox-filter API endpoint accepts the following optional query parameters:

  1. andSubjectIncludes: Filter messages by text included in the subject line
  2. andFrom: Filter messages by text included in the FROM envelope
  3. andTo: Filter messages by text included in the TO envelope

This endpoint delivers results only when at least one query condition is specified, otherwise, expect a 400 error. The response is capped at 100 results, so adjust your query or prune your account accordingly.

JavaScript Unit Test with Mocha and Axios

To illustrate the usage of the /inbox-filter API endpoint, here’s a JavaScript unit test using Mocha and Axios:

const axios = require('axios');
const assert = require('assert');

describe('Inbox Filter API Endpoint Test', () => {
  it('should return filtered messages', async () => {
    const mailsacApiKey = 'your-api-key-here';
    const endpoint = 'https://mailsac.com/api/inbox-filter';
    const andSubjectIncludes = 'Important';
    const andFrom = '[email protected]';
    const andTo = '[email protected]';

    const response = await axios.get(endpoint, {
      headers: { 'Mailsac-Key': mailsacApiKey },
      params: { andSubjectIncludes, andFrom, andTo },
    });

    assert.strictEqual(response.status, 200);
    assert.strictEqual(Array.isArray(response.data.messages), true);
    response.data.messages.forEach((message) => {
      assert.strictEqual(message.subject.includes(andSubjectIncludes), true);
      assert.strictEqual(message.from[0].address.includes(andFrom), true);
      assert.strictEqual(message.to[0].address.includes(andTo), true);
    });
  });
});

Looking for a robust email testing solution that can simplify your workflow and improve efficiency? Look no further, friends. Mailsac offers powerful features like this new inbox filter API endpoint and many more, tailored to meet the needs of developers, testers, and businesses alike. Discover the benefits of Mailsac today and elevate your email management game. Try Mailsac for free or learn more about our plans and join our growing community of satisfied users at forum.mailsac.com.