CheckMessageId: Empty Message-Id

Last Update 1998-09-03
Newsgroups: comp.mail.sendmail
From: (Robert Harker, 408-295-9432)
Subject: Using header rulesets to reject spam without a Message-Id: header
Message-ID: <>
Summary: sendmail 8.9 reject spam local message-id header
Organization: Harker Systems, 1180 Hester Ave, San Jose, CA 95126
Date: Thu, 3 Sep 1998 04:47:17 GMT

I was looking at some of the spam I received today and found a message
that had a Message-Id: header that was generated by my mail host.
This is an indication of a message that was passed via SMTP to my host
with no Message-Id: header passed during the DATA phase.  Since the
Message-Id: header was missing, my host generated one and inserted into
the message.  I got to thinking about this and realized that the sendmail
8.9 feature of sending headers to check_* type rulesets could be used to
reject non-local messages with a locally generated Message-Id: header.

In my opinion there are three cases in which a local Message-Id: header
is generated:
1) Local messages generated on the local system with a local MUA
2) A POP or IMAP type SMTP client that is part of the local domain
3) Everything else (which implies the sender is remote and the message is spam)

What you want to do with this header ruleset is to test if the client
is local, in which case accept any Message-Id: header.  Otherwise if
the Message-Id: header ends with the local host's FQDN, <anything@$j>,
then the client is remote and passed us a SMTP message without a
Message-Id: header.  If this is the case, then the message is probably
is spam and should be rejected.

Here is the ruleset.  I home my comments explain what I am trying to do.

	HMessage-Id: $>CheckMessageId

	# check for local Message-Id: header for non-local headers
	# Put client hostname in an initial lookup focus
	# anything	->	   < lookup focus >    anything
	R$*			$: < $&{client_name} > $1

	# test if client hostname in lookup focus ends with one of our
	#	domains, $=m, if so the message is locally generated and all
	#	Message-Id: header are OK
	R< $+.$=m > < $+ >		$@ OK

	# reject all other locally generated Message-Id: headers because
	#	client hostname is not local
	R< $+ > < $+ @ $j >	$#error $:"553 Header error, use your own header"

	# strip trash lookup focus leaving the original header
	R< $+ > < $+ >		< $2 >

	# now do the normal header check from the sendmail 8.9.1 cf/README file
	R< $+ @ $+ >		$@ OK
	R$*			$#error $: "553 Header error"

This is something I whipped together and have not tested extensively.
Issues that come to mind are:
	What about local mail where $&{client_name} is <NULL>?
	Should I include some rules to check for deferred delivery mode?
	My header ruleset does not take into account of issues with
		complex sites like class $=R or the access database.

Ideas and feedback are welcome.

Ahh... To be back home for more than a week.

Just another "Harker's Helpful Hint"


  > Generate files using the web. Check out our web based  <
  > file generator:  <

  > For info about our "Managing Internet Mail, Setting Up and Trouble <
  > Shooting sendmail and DNS" and a schedule of dates and locations,  <
  > please send email to, or visit      <

Robert Harker						Harker Systems
Sendmail and TCP/IP Network Training			1180 Hester Ave
Sendmail, Network, and Sysadmin Consulting		San Jose, CA 95126					408-295-6239

[(links)] [Hints] [Avoiding UBE] [New]
Copyright © Claus Aßmann Please send comments to: <>