ARTICLE

Should You Block Disposable Emails at Signup? A Policy Guide for SaaS Trials

You added disposable-email detection to your signup flow. Now the harder question shows up: when the check says an address is a burner, what should your product actually do with it?

The instinct is to hard-block. Sometimes that is right. Often it is not. Block too little and your free trial becomes a renewable resource for people who never plan to pay. Block too much and you turn away privacy-minded users, confuse honest people who made a typo, and push determined abusers toward Gmail accounts you cannot block at all.

This guide is for founders and backend engineers who already accept that a deliverable email is not the same as a trustworthy signup (we covered that in Free Trial Abuse: Why Email Validation Isn't Enough). Here we go one step further: how to turn a disposable-email result into a policy you can defend, tune, and explain to support.

The short answer

Block disposable emails outright only when two things are true: the free thing you hand out has a real marginal cost, and the evidence is strong. For everything else, route the signup to a lighter-weight path such as email confirmation, reduced trial credits, or a manual look, instead of a dead end.

A workable setup has three lanes:

  • Allow: no meaningful risk factors. Full trial.
  • Review: disposable or otherwise uncertain evidence. The account exists, but costly benefits wait.
  • Block: strong, stacked evidence. No trial.

The rest of this article is about deciding which signups land in which lane.

Why "just block them all" backfires

A blanket block feels clean, but it has three predictable failure modes.

1. Not every disposable-looking address is a throwaway.

Forwarding and alias services exist for privacy, and mainstream products like Apple's Hide My Email generate random addresses that forward to a real inbox (Castle's research on disposable emails covers the difference between short-lived inboxes and persistent aliases). Some of those users are exactly the careful, technical buyers a developer tool wants.

2. Abusers adapt faster than your rule does.

Once a signup form blocks known disposable domains, low-effort abusers move to free provider accounts or domains they control. Castle makes the same point in the article linked above. A hard block on disposable domains removes the easiest path; it does not end the behavior.

3. You lose the evidence.

A rejected signup leaves nothing to learn from. A reviewed signup leaves a record you can check a week later: did it confirm the email, did it activate, did it burn credits and vanish?

None of this means you should allow burners into a costly trial. It means the block should be earned by evidence, not triggered by a single category label.

What a disposable-email result actually tells you

"Disposable" is not one fact. A useful check tells you how sure it is.

Signup Risk API's disposable_email check returns one of five results: confirmed, likely, suspicious, none, or unknown. Those are very different inputs to a policy:

  • confirmed: the strongest evidence that the domain is a known disposable provider.
  • likely / suspicious: weaker evidence than a confirmed match. Worth friction, rarely worth a hard block on its own.
  • none: no disposable evidence found.
  • unknown: the check could not be evaluated. That is not a pass and not a failure.

That last point matters more than it looks. When a DNS lookup times out, Signup Risk API reports the evidence as unavailable, and the affected check contributes nothing to the score instead of inventing risk. Your policy should do the same: treat "we could not tell" as its own case, not as "clean" and not as "burner."

The disposable result also never stands alone. The same response includes other independent checks: domain infrastructure (DNS, MX, SPF, DMARC), provider type, role addresses like support@, domain typos like gmal.com, synthetic patterns like keyboard walks or numeric-only local parts, and name-to-email alignment when you send a name. IP infrastructure context (datacenter, VPN, proxy, Tor) is available on the Growth plan and above.

Let the score do the stacking

Rather than writing a rule for every combination, let the score combine the evidence and read the recommendation. Signup Risk API maps the 0–100 score to a band and an action:

Risk scoreRisk banddecision.action
0–24lowallow
25–49moderatereview
50–74highreview
75–100very_highblock

Don't assume a confirmed disposable result always maps to block, or that it never does. Where it lands depends on the rest of the evidence in the request. For example, a very newly registered domain adds risk on top of disposable evidence, and IP infrastructure context adds more on Growth and above. So read decision.action together with checks.disposable_email.result. If your product wants every confirmed burner rejected, make that rule explicit in your own code, as the policy below does, rather than assuming the recommendation will do it for you.

Here is what a request and a response look like. The values below are illustrative, not a live result; real scores depend on current data and on everything else in the request.

bash
curl https://api.signuprisk.com/v1/analyze-email \
  -H "Authorization: Bearer $SIGNUPRISK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "maria.lopez@mailinator.com",
    "name": "Maria Lopez",
    "options": { "include_checks": true, "include_explanation": true }
  }'

Illustrative response, not a real API result:

json
{
  "decision": {
    "action": "review",
    "risk_score": 70,
    "risk_band": "high",
    "summary": "High-risk signup. Primary concern: disposable email provider detected.",
    "assessment": {
      "confidence": "high",
      "evidence_strength": "strong",
      "evidence_coverage": "partial",
      "uncertainty": "low",
      "limitations": ["ip_not_supplied"]
    }
  },
  "checks": {
    "disposable_email": {
      "result": "confirmed",
      "is_disposable": true,
      "confidence": "high",
      "risk_contribution": 70
    },
    "domain_typo": { "result": "no_typo", "risk_contribution": 0 },
    "role_address": { "result": "personal_like", "risk_contribution": 0 }
  },
  "explanation": {
    "top_reasons": [
      {
        "reason": "Disposable email provider detected",
        "check": "disposable_email",
        "contribution": 70
      }
    ],
    "recommendation_reason": "Review this signup before granting normal account access."
  }
}

The response is trimmed for readability; with include_checks on, all eight checks are returned. Three fields do most of the policy work: decision.action (the recommendation), checks.disposable_email.result (what the check found), and checks.disposable_email.confidence (how sure the check is about that finding). The stricter rule in the policy below keys on the last two. Don't confuse that with decision.assessment.confidence, which describes how stable the overall recommendation is given the evidence that was available.

A policy you can ship this week

This is a starting point for a SaaS product with a free trial or free credits. Adjust the lanes to what your trial actually costs you.

javascript
async function scoreSignup({ email, name }) {
  const res = await fetch("https://api.signuprisk.com/v1/analyze-email", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SIGNUPRISK_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ email, name, options: { include_checks: true } }),
  });
  if (!res.ok) return null; // timeout, quota, or outage: handled below
  return res.json();
}

function trialAccess(result) {
  // Scoring unavailable: don't hand out the expensive part blind.
  if (!result) return { lane: "review", credits: "starter" };

  const { action } = result.decision;
  const disposable = result.checks?.disposable_email?.result;

  if (action === "block") return { lane: "block" };

  // Optional stricter rule: reject confirmed burners when the disposable check itself reports high confidence.
  if (disposable === "confirmed" && result.checks?.disposable_email?.confidence === "high") {
    return { lane: "block", message: "Please sign up with a permanent email address." };
  }

  if (action === "review") return { lane: "review", credits: "starter" };

  return { lane: "allow", credits: "full" };
}

A few choices in there are deliberate.

Decide your failure mode on purpose. Some disposable-check guides tell you to fail open: if the API errors, let the signup through. That is right for a newsletter form. For a trial that hands out GPU time or API credits, failing open means an outage is a free-credit window. The middle path above creates the account but holds back the expensive part until you can score it again.

Make "review" mean something concrete. Signup Risk API recommends; it never blocks or challenges anyone itself. Your app decides what review means. Good options, roughly in order of friction:

  1. Require email confirmation before trial credits are issued.
  2. Start with a smaller credit allowance and unlock the rest after real activity.
  3. Delay the costly feature (API keys, compute, exports) until the account has been active for a day or two.
  4. Queue it for a human look if your volume allows.

Stripe's guidance on multi-account abuse lands in the same place: rather than blocking at signup for higher-risk signups, gate the high-value action (trial activation, promo redemption, referral payouts) until the account shows baseline legitimate behavior (Stripe: How to detect fake users and multiaccount sign-up abuse).

Write a block message a human can act on. "Invalid email" makes an honest user think your form is broken. "Please sign up with a permanent email address" tells them exactly what to do.

Request explanations only when you need them. include_checks gives your code the structured evidence. Explanations draw on a separate monthly allowance (50 per month on Free), so ask for include_explanation in your review tooling or logs, not necessarily on every signup.

Close the loophole blocking creates

Once burners stop working, the cheapest next move for a repeat abuser is the same Gmail inbox with a +tag or extra dots. The email object in a Signup Risk API response includes a canonical field that folds those variants together (for example, stripping plus-addressing and Gmail dots, and folding googlemail.com into gmail.com). Store it and use it as your one-trial-per-identity key. It is not a delivery address; keep sending mail to what the user typed.

What this approach does not do

Honest limits, so you can plan around them:

  • It is not mailbox verification. Signup Risk API does not send mail or confirm that an inbox exists. If you need proof of ownership, keep your email confirmation step.
  • It does not replace your auth. It runs alongside Clerk, Auth0, Supabase, Firebase, Cognito, or your own system. Call it from your backend before granting trial access.
  • It does not enforce anything. The action is a recommendation. Your code owns the allow, review, and block behavior.
  • Name matching is not identity verification. It compares the name you send with the email local part. It proves nothing about who the person is.
  • Email evidence has a ceiling. A patient abuser with fresh free-provider accounts can look clean on email alone. IP infrastructure context helps on Growth and above; device fingerprinting and payment checks are outside what this API does.
  • No score is a verdict. A disposable address is evidence of risk, not proof of fraud. Plenty of people use burners to avoid marketing email.

What good looks like

Before you tighten anything, run a week in log-only mode: score every signup, store the action, disposable result, disposable confidence, and canonical email, and change nothing. Then check:

  • How many signups land in each lane?
  • Of the reviewed accounts, how many confirm their email and go on to use the product normally?
  • Are repeat trials clustering on the same canonical identity?
  • Is support hearing from people who could not sign up?

Once those answers look sane, turn the lanes on. Revisit when your trial gets more valuable, because a more expensive trial justifies a stricter policy.

For the full breakdown of what each check evaluates, see Email Validation vs Signup Risk Scoring. For trial-specific patterns, see SaaS trial abuse. To wire it up step by step, start with the quickstart.

Try it on your own signups

The fastest way to settle your policy is to score real addresses from your own signup log and see where they land. Signup Risk API's Free plan includes the complete core signup-risk analysis: 200 requests per month, no credit card required.

Start free with 200 requests/month

and score your first signup in a few minutes.