Open source · Rspamd + Redis

Recipient tracking.
Without the noise.

Count unique email recipients per authenticated sender using Rspamd and Redis, with alerting and Prometheus metrics.

Hundreds of messages to one familiar recipient should not look the same as a burst to hundreds of different addresses.

RCPTWatch envelope, radar and alert icon
Illustrative example127 / 50

unique recipients

! Threshold exceeded
◎

Count unique recipients

Repeated messages to known recipients increase the message count, not the distinct-recipient total.

!

Configurable alerts

Raise an Rspamd symbol when a sender exceeds the limit, with optional email alerts via metadata_exporter.

▥

Prometheus metrics

Expose aggregate message, recipient, new-relationship and alarm counters — without sender labels.

⌁

Redis-backed state

Short-lived recipient relationships, atomic updates and automatic cleanup after inactivity.

The workflow

How it works

Simple components. No extra alerting daemon required.

01
✉

Postfix MSA

Authenticated mail submission supplies the sender and SMTP envelope recipients.

→
02
◇

Rspamd Lua

Compute recipient relationship hashes and run the check, including for whitelisted senders.

→
03
▤

Redis

Count active relationships and messages atomically. Expire inactive entries.

→
04
!

Alerts & metrics

Trigger zero-score symbols, notify admins and make aggregate counters available.

Quick start

Designed to fit your Rspamd setup.

Install the Lua callback in lua.local.d, keep the Redis Lua script separately under local.d, and configure your thresholds. The GitHub README documents all installation steps and the metadata_exporter rule.

Read installation instructions ↗
Rspamd log · example
# First recipient
OUTGUARD_OBSERVE (0) [1/50, new=1]

# Repeated recipient
OUTGUARD_OBSERVE (0) [1/50, new=0]

# Threshold exceeded
OUTGUARD_ALERT   (0) [51/50]

# No SMTP rejection by default
Action: no action
Built for administrators

Signal over volume.

RCPTWatch observes recipient counts; it does not classify message content. Its default behavior is monitoring and alerting, not blocking. Review the documentation before enabling automated enforcement.

Explore the project ↗