Drop-in SMTP relay to combat bots and prevent spamming users

Taming Runaway Email: Why We Built a Smarter SMTP Relay

Anyone who runs forms on the public Internet eventually meets the same problem: abusive scripts hammering signup forms, contact boxes, or forgotten-password links. Each hit triggered an email. One bot could generate a hundred emails to the same recipient within minutes. Multiply that by several forms or several sites, and the flood becomes impossible to ignore. We saw recipients get hammered with repetitive notifications.

It wasn’t enough to block bots at the form level. We needed defense in depth. Even if something slipped through, we didn’t want a single automation-happy script to melt a mailbox. The SMTP layer needed a safety valve.

So we built one.


A Relay That Stands Between Your App and the World

Instead of sending emails directly from applications, we inserted a lightweight SMTP relay—just a single script—between our apps and the real SMTP server. Every outgoing email passes through it. The relay performs a few simple but powerful functions:

  1. Immediate delivery of the first email to any given recipient
  2. Digesting subsequent emails into periodic summaries
  3. Exponential backoff to handle ongoing bursts
  4. Automatic cooldown to reset the schedule when things quiet down
  5. Attachment size limits and omission summaries
  6. Drop-in compatibility with anything that normally talks to an SMTP server

The result is a general-purpose layer that “tames” outgoing mail without touching existing applications.


Designing the Features: Practical Decisions

1. Immediate Delivery

If someone fills out a form once, they should receive the email right away.
The relay doesn’t delay the first message. It passes through instantly.
This preserves usability and keeps notifications feeling normal.

2. Digesting (Summaries)

If multiple emails arrive for the same recipient during a short window, the relay batches them into a single digest.

Instead of:

Your form was submitted.
Your form was submitted.
Your form was submitted.
…

The recipient gets:

Your form was submitted.
(+ 27 more messages)

This cuts the volume down dramatically while still communicating the event.

3. Exponential Backoff

If the spam continues, the relay increases the delay between digests:

  • First digest: after 1 minute
  • Next: after 2 minutes
  • Next: after 4 minutes
  • etc.

This turns an infinite stream into a controlled trickle.
Backoff limits and intervals are configurable—set them to whatever pace fits your system.

4. Cooldown Reset

Once the bots quiet down, the relay resets the timing back to normal.
No long delays carry over to the next legitimate message.
The cooldown logic wipes the slate clean automatically.

5. Omitted Attachments and Safe Limits

Bots love sending garbage as attachments. Most web apps don’t.
The relay enforces:

  • total attachment size limits
  • per-file caps
  • a maximum number of attachments
  • inline-image omission
  • safe HTML truncation

Oversized or excess content is summarized at the end of the digest instead of being delivered.

6. Works With Everything

This was important: no plugins, no SDKs, no framework dependencies.

If your app already sends mail like this:

SMTP_HOST=smtp.example.com

You just change it to:

SMTP_HOST=localhost:2525

The relay accepts the connection, processes the message, and forwards it to your actual mail server on the backend. It works with:

  • PHP’s mail() (via sendmail wrappers)
  • PHPMailer
  • Node.js libraries
  • Rails ActionMailer
  • Django email backends
  • Anything that talks SMTP

No code changes required. This works with all your transactional emails, your notifications, etc.


Why Not Just Rate-Limit at the Application Layer?

We do that too—but we want guarantees.

Applications have bugs. Developers forget edge cases. A spammer finds an odd URL. A monitoring service misbehaves. An internal script enters a loop at 3 AM.

When everything above the SMTP layer fails, the relay still holds the line.
It’s the last barrier before email actually leaves your system.

And, frankly speaking, we wanted to make something that other app developers could use, regardless of whether they built their apps in PHP, Python, Javascript, Go, or anything else.


Try It Out

The script is open source:

https://github.com/Qbix/Platform/blob/main/platform/scripts/smtp.js

Drop it into your stack, point your apps to it instead of your usual SMTP server, and enjoy some peace and quiet. It works with any stack—PHP, Node.js, Python, Ruby, Go—anything that sends mail over SMTP.

If you’ve ever been frustrated watching your servers spray hundreds of redundant emails, this relay will feel like a breath of fresh air.