Spam emails with no "to:" address. Filter with Postfix..?

My forum is recently getting peppered with a series of similar spam emails. They use a different sender, domain, & IP each time. (But they’re always about some construction industry conference somewhere.)

They end up in Rejected with Email::Receiver::BadDestinationAddress, and the system tries to send a rejection message to the invalid sender address. sends a rejection message, emitting backscatter. re. EDIT: there’s no evidence the sender addresses are invalid.

In fact, they have no to: or cc: address at all. I’ve learned that recipients are actually defined in the SMTP envelope, not the header, and that mailing list systems may omit to:/cc: from headers on purpose.

(I’ll note that this started in November, around when fast-rejection was removed :thinking:)

I don’t relish diving into Postfix configuration, but apparently it can do header checks

Wondering if anyone has already tried this and has any tips?

example spam email header, FWIW
Received: from 103-191-76-30.cprapid.com (unknown [103.191.76.30])	by forum-mail-receiver.localdomain (Postfix) with ESMTPS id 0845A2FB2B6; Thu, 08 Jan 2026 02:30:19 +0000
Received: from [::1] (port=57140 helo=103-191-76-30.cprapid.com)	by 103-191-76-30.cprapid.com with esmtpa (Exim 4.99.1)	(envelope-from <alexg@connectconsortiumplaceru.com>)	id 1vdfl5-00000000rLO-0bcP; Wed, 07 Jan 2026 21:28:18 -0500
Date: Wed, 07 Jan 2026 21:26:55 -0500
From: alexg@connectconsortiumplaceru.com
Message-ID: <093f4b04eb0e41f70390cf63dcce77d4@connectconsortiumplaceru.com>
Subject: 5th Annual Modular Construction & Prefabrication Symposium - Toronto,
 Canada | March 2026 (Limited Seats Left)
MIME-Version: 1.0
Content-Type: multipart/mixed;
 boundary="=_605ba79265fcf8605b02d6716c2455fc";
 charset=UTF-8
Content-Transfer-Encoding: 7bit
Authentication-Results: forum-mail-receiver.localdomain; dmarc=none (p=none
 dis=none) header.from=connectconsortiumplaceru.com
Authentication-Results: forum-mail-receiver.localdomain; dkim=pass (2048-bit
 key; unprotected) header.d=connectconsortiumplaceru.com
 header.i=@connectconsortiumplaceru.com header.a=rsa-sha256 header.s=default
 header.b=hljdS4ya; dkim-atps=neutral
Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=103.191.76.30;
 helo=103-191-76-30.cprapid.com;
 envelope-from=alexg@connectconsortiumplaceru.com; receiver=forum.tasat.org
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
 d=connectconsortiumplaceru.com; s=default; h=Content-Type:Message-ID:Subject:
 To:From:Date:MIME-Version:Sender:Reply-To:Cc:Content-Transfer-Encoding:
 Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender:
 Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:
 List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive;
 bh=QsuKb3maShWc9C0uTAfGJZlp0GLvUFzREukTJkY4TbE=; b=hljdS4yaocpaFXSAbqnR+pvdM5
 W02vREZeWNQEtDMCqxEmI17jqjL5k+VGWi6vcruI2QBIi+C3omMWl1MrzAZ18EotG4/SfmY0jqcyV
 G5lu46MfkyxsUUdqQoKIHChQ5T0aa7jfc7LzZzM8bIBUk6VnV4lNn5SItSDEMAzRqrq66rL7ugL3u
 16OkrMph0Kjw7YP2swVhZY9y0TqJBy0L05XHy5BfLjh5K7UGbNxnnN6daXlpCJ/zsQPFjjkiTNicc
 WLIuKHpH+sCQt2VqnbvGVcdYJmapKCzXn0sS08BspidViHbf/2hOAHkDlbVyWduINyn44Es5oj2Jh
 B9+D9w8g==;
User-Agent: Roundcube Webmail/1.6.12
X-Sender: alexg@connectconsortiumplaceru.com
X-AntiAbuse: This header was added to track abuse, please include it with any
 abuse report
X-AntiAbuse: Primary Hostname - 103-191-76-30.cprapid.com
X-AntiAbuse: Original Domain - forum.tasat.org
X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12]
X-AntiAbuse: Sender Address Domain - connectconsortiumplaceru.com
X-Get-Message-Sender-Via: 103-191-76-30.cprapid.com: authenticated_id:
 alexg@connectconsortiumplaceru.com
X-Authenticated-Sender: 103-191-76-30.cprapid.com:
 alexg@connectconsortiumplaceru.com
X-Source: 
X-Source-Args: 
X-Source-Dir:

They usually send to as bcc to a long list of scraped emails, I have seen that behaviour on a few sites, but don’t have any practical solution yet.

Yeah, this is how BCC: is done, the address just doesn’t make it into a header.

Discourse is a bit different in that it does not use the envelope recipient at all, only the headers. Arguably, this is wrong, but so many people depend on the current behaviour it’s hard to change.

Fast Rejection was removed as it was broken. On top of that, the logic checked the envelope recipient, which doesn’t match what Discourse looks for. This mismatch means that fast-rejection might reject otherwise deliverable mail, and allow non-deliverable.

Reconciling this would unfortunately be a gnarly effort for comparatively little gain.

I see… thanks for the details.

I currently only use reply-by-email, so figured it would make sense to block anything without a TO:/CC: header. But I can imagine how this could be problematic for sites using post-by-email.

Reconciling this would unfortunately be a gnarly effort for comparatively little gain.

I’m certainly biased–I wrote the fast-rejection code that was removed–but I would disagree about the value of the concept, especially if the backscatter starts landing people’s Discourse servers on spam blocklists, or services like Mailgun start complaining about it (or worse, they don’t complain about it and happily charge you to send tons of bogus emails when a big wave of spammers pound through).

If someone else were to contribute code to resolve the concerns (parse the headers instead of the envelope, etc), would this be something Discourse would be willing to reincorporate, or is this just something no one has time to mess around with in any capacity at the moment?

(Either way is fine, I totally get that everyone is doing the best they can with limited time and resources!)

Hey, just a few tips I’ve been trying out for this kind of spam:

- For messages with no To:/Cc: headers, dropping them at the Postfix level works well if you only use reply-by-email.

- You can also add a simple SPF/DKIM check to filter out spoofed domains before they hit Discourse.

- Another trick I’ve seen is rate-limiting incoming mail per IP or per sender domain — it helps slow down spam waves without touching normal users.

- If you’re feeling adventurous, combining header checks with a small whitelist (for trusted senders or mailing lists) can cut down false positives.

Nothing fancy, just some ideas that have helped me reduce the noise a bit :slightly_smiling_face: