local function check_forged_headers(task)
local auser = task:get_user()
local delivered_to = task:get_header('Delivered-To')
- local smtp_rcpts = task:get_recipients(1)
- local smtp_from = task:get_from(1)
+ -- Compare the envelope and the headers as they were transmitted: alias
+ -- rewrites (e.g. a cross-domain virtual alias applied to the envelope
+ -- recipients) must not make the wire To/Cc headers look forged
+ local smtp_rcpts = task:get_recipients({ 'smtp', 'orig' })
+ local smtp_from = task:get_from({ 'smtp', 'orig' })
if not smtp_rcpts then
return
-- Check sender
if smtp_from and smtp_from[1] and smtp_from[1]['addr'] ~= '' then
- local mime_from = task:get_from(2)
+ local mime_from = task:get_from({ 'mime', 'orig' })
if not mime_from or not mime_from[1] or
not rspamd_util.strequal_caseless_utf8(mime_from[1]['addr'], smtp_from[1]['addr']) then
task:insert_result(symbol_sender, 1, ((mime_from or E)[1] or E).addr or '', smtp_from[1].addr)
... Rcpt=user@example.com
Expect Symbol ALIAS_RESOLVED
Expect Symbol With Exact Options GET_FROM Abuse Desk,admin@example.com,admin,example.com
+
+RCPT CROSS-DOMAIN ALIAS - NOT FORGED
+ [Documentation] A recipient rewritten to another domain (allowed for
+ ... recipients) must not make the matching wire To header look forged:
+ ... forged_recipients compares the addresses as transmitted
+ Scan File ${RSPAMD_TESTDIR}/messages/aliases_rcpt_virtual.eml
+ ... From=sender@external.com
+ ... Rcpt=virtual@example.com
+ Expect Symbol ALIAS_RESOLVED
+ Do Not Expect Symbol FORGED_RECIPIENTS
+ Do Not Expect Symbol FORGED_SENDER
--- /dev/null
+From: Sender <sender@external.com>
+To: virtual@example.com
+Subject: Test cross-domain recipient alias vs forged recipients
+Message-ID: <test-rcpt-virtual@example.com>
+Date: Mon, 01 Jan 2025 10:00:00 +0000
+
+A recipient rewritten to another domain must not make the wire To header
+look forged.