DEV Community

MAYNO
MAYNO

Posted on

Half Your Free Trial Signups Are Fake: Here's How to Fix It

The Problem Every SaaS Faces

Fake signups from disposable emails are killing your metrics. Someone signs up with throwaway@mailinator.com, uses your free trial, and vanishes.

Why It Matters

  • Wastes customer success time
  • Inflates your user count (fake growth)
  • Costs you money (server resources, email sends)
  • Makes your analytics useless

The Solution: Email Risk Scoring

Instead of just validating syntax, check:

  1. Is it from a disposable provider? (mailinator, guerrillamail, etc.)
  2. Does the domain have MX records?
  3. Free provider vs business email?

What Good Email Validation Detects

A proper email risk scorer checks multiple signals:

  • Disposable domains: Is it from Mailinator, Guerrilla Mail, or 500+ other temporary providers?
  • MX records: Can the domain actually receive emails?
  • Provider type: Free (Gmail/Yahoo) vs Business (company.com)?
  • Role-based emails: Generic addresses like info@, admin@, noreply@
  • Risk level: Low, Medium, or High

How to Implement It

Option 1: DIY Solution (Free, But Manual)

# Use the GitHub disposable-email-domains list
import requests

DISPOSABLE_DOMAINS = requests.get(
    "https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/main/disposable_email_blocklist.conf"
).text.split()

def is_disposable(email):
    domain = email.split("@")[1]
    return domain in DISPOSABLE_DOMAINS
Enter fullscreen mode Exit fullscreen mode

Option 2: Use a Ready-Made API (Faster Setup)

Or skip all that complexity and use a ready-made solution.

I built this to solve the problem: https://apify.com/mayno/email-risk-scorer

What you get out of the box:

  • 500+ disposable domains detected (Mailinator, Guerrilla Mail, YOPmail, etc.)
  • MX record validation - checks if the domain can actually receive emails
  • Email provider identification - detects Google Workspace, Microsoft 365, Zoho, etc.
  • Free vs business email classification - Gmail/Yahoo vs company domains
  • Role-based email detection - flags generic addresses (info@, admin@, noreply@)
  • Automatic syntax validation - RFC-compliant email format checking
  • Risk level scoring - returns low/medium/high based on multiple signals
  • Batch processing - validate up to 10,000 emails per run
  • No maintenance - disposable domain list updated automatically
  • Fast processing - handles 1,000 emails in ~3-5 seconds

Setup time: 5 minutes. Here's the complete implementation for an Express.js signup route:

import { ApifyClient } from 'apify-client';

const apifyClient = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

app.post('/signup', async (req, res) => {
  const { email, password } = req.body;

  // Check email risk (one API call)
  const run = await apifyClient.actor('mayno/email-risk-scorer').call({
    emails: [email]
  });

  const results = await apifyClient.dataset(run.defaultDatasetId).listItems();
  const emailRisk = results.items[0];

  // Block disposable emails
  if (emailRisk.isDisposable) {
    return res.status(400).json({
      error: 'Disposable email addresses are not allowed'
    });
  }

  // Block high-risk emails
  if (emailRisk.riskLevel === 'high') {
    return res.status(400).json({
      error: 'This email address cannot be used for registration'
    });
  }

  // Optional: Flag free email providers for review
  if (emailRisk.isFreeProvider && !emailRisk.hasMXRecord) {
    // Log for manual review
    console.log('Suspicious signup:', email);
  }

  // Proceed with signup
  await createUser(email, password);
  res.json({ success: true });
});
Enter fullscreen mode Exit fullscreen mode

Example API response:

{
  "email": "test@mailinator.com",
  "isValid": true,
  "isDisposable": true,
  "isFreeProvider": false,
  "isBusinessEmail": false,
  "isRoleBasedEmail": false,
  "domain": "mailinator.com",
  "hasMXRecord": true,
  "mxProvider": "mail.mailinator.com",
  "riskLevel": "high",
  "reasons": ["Disposable/temporary email provider"]
}
Enter fullscreen mode Exit fullscreen mode

Why this beats the DIY approach:

  • No code to maintain (I handle updates)
  • No DNS infrastructure to manage
  • No edge cases to debug
  • No weekly domain list updates
  • Works day one, scales to millions

Time saved: ~6 hours initial setup + 1-2 hours/month maintenance = ship faster, focus on your product

Conclusion

Pick what works for your stage:

  • Early/MVP: DIY approach
  • Scaling: Use an API

Try It Yourself

Want to test it out? The actor is live on Apify with a free tier: https://apify.com/mayno/email-risk-scorer

Questions? Feedback? Drop a comment below. I'm actively working on this and would love to hear what features would be most useful!

Top comments (0)