On Wed, 2009-07-01 at 00:23 +0100, Mike Cardwell wrote:
> I've started seeing spam email containing an X-Mailer header which is
> the domain name of the From header. Eg:
>
> From: "Compare and Cover Life" <
info@...>
> X-Mailer: webguide103.com
The *first* question should be, how are these scoring generally, and if
it's worth the effort. If they sneak by, there's usually a more
fundamental problem than a missing rule like this.
That said -- nice catch. :)
> How would I construct a spamassassin rule to check for this?
Using the all-magic, all-dancing pseudo ALL header [1], and a brave mix
of RE modifiers like /m and /s [2], to handle multi-line strings. :)
Something like this should do. DO NOTE that I just hacked it up in the
email, and did NOT test it. Mind the manual line wrap.
header FROM_EQ_XM ALL =~
/^From: [^\@]+\@(?:[^.]+\.)?([^.]+\.[^.]+)>?\$.{0,400}^X-Mailer: \1\$/msi
Now what the fuck does that do? The /m enables multi-line matching, so ^
and $ match the beginning and end of a line respectively, rather than of
the string (which would be the entire headers).
First, we identify a From header, consume all the crap before the @,
optionally also consume a host without capturing (the (?:...)? part).
The trailing example.com we do capture, followed by an optional closing
bracket and the end of the line \$. Note that this appears slightly over
complicated, but it is important -- the dot also matches \n, due to
the /s modifier.
Then match whatever header junk there is, up to an arbitrary bound of
400 chars. With an X-Mailer header following, that matches the domain we
just captured, up to the end of the header. Et voila. :)
Note that this only matches this particular order of headers, so you
might need a second (sub-)rule (meta'd together) to match the reverse.
End proof of concept. ;)
guenther
[1]
http://spamassassin.apache.org/full/3.2.x/doc/Mail_SpamAssassin_Conf.html[2]
http://perldoc.perl.org/perlre.html--
char *t="\10pse\0r\0dtu\0.@ghno\x4e\xc8\x79\xf4\xab\x51\x8a\x10\xf4\xf4\xc4";
main(){ char h,m=h=*t++,*x=t+2*h,c,i,l=*x,s=0; for (i=0;i<l;i++){ i%8? c<<=1:
(c=*++x); c&128 && (s+=h); if (!(h>>=1)||!t[s+h]){ putchar(t[s]);h=m;s=0; }}}