divert(-1) dnl ################################################################### dnl # This crudel checks for the validity of the "From:" header and dnl # the "Message-Id:" header, and rejects mail where the headers dnl # are obviously invalid. dnl # dnl # For the "From:" header, anything of the form *@* is accepted, dnl # where the "*" wildcards match non-empty strings. dnl # dnl # An unqualified address, or a missing "From:" header is also dnl # allowed, if the envelope sender address contains an "@". The dnl # principle is that sendmail can generate a valid "From:" in dnl # this case, perhaps depending on the "C" mailer flag for smtp dnl # mailers. However, when the envelope sender is null (<>), as dnl # with some spam, stricter standards for "From:" are required. dnl # dnl # The "Message-Id:" header, if it exists, is required to be of dnl # the form: comment comment. There is no check dnl # of an absent header in this case, since the standards do not dnl # require the header. dnl # dnl # There is a check for access map entries for host or ip dnl # address, tagged with "CheckMsgid". This allows a particular dnl # sending host to be whitelisted, bypassing message-id dnl # rejections for that host. The entry for a host can be OK or dnl # RELAY, which whitelist the host. It can also be DISCARD to dnl # silently discard bad message-id mail from this host. dnl # dnl # I probably should add a similar "CheckFrom:" tagging, but dnl # I have not yet found any need for that. dnl # dnl ################################################################### dnl # dnl # The macro ${HeadersSeen} is used to keep track, for checking dnl # in an end of header check. It is expected to contain a dnl # string of key letters, one for each header whose presence is dnl # recorded. At present it is used only for "F" for the "From:" dnl # header, and "M" for the "Message-Id:" header. divert(0)dnl VERSIONID(`$Id: reject_bad_from.m4,v 1.2 2001/10/18 00:58:20 rickert Exp $') divert(-1) define(`_NEED_MACRO_MAP_')dnl LOCAL_CONFIG HFrom: $>CheckFrom HMessage-Id: $>CheckMsgid LOCAL_RULESETS SCheckFrom ## First record that we have seen this header. R$* $:$(macro {HeadersSeen} $@ $&{HeadersSeen} F $) $1 R$+ @ $+ $@ ok Passes crude check R$* $: $&f Recover envelope sender. R$+ @ $+ $@ ok With C mailer flag, will use sender @domain R$* $#error $: "553 Bogus 'From:' header" SCheckMsgid ## First record that we have seen this header. R$* $:$(macro {HeadersSeen} $@ $&{HeadersSeen} M $) $1 R$*<$+@$+>$* $@ ok Passes crude check R$* $:<$&{client_addr}><$&{client_name}> Client addr/name R<$+><$+> $: $>A <$1> <$2> R<$+> $: $>D <$1> <> R$* $: <$(access CheckMsgid: $: ? $)> Default R<$={Accept}>$* $@ ok R$* $#discard $: discard R$* $#error $: "553 Bogus \"Message-Id:\" header" Scheck_eoh R$* $:<$&f>$&{HeadersSeen} recover list of seen headers R$* $:$(macro {HeadersSeen} $@ $) $1 and reset list R<$*>$* F $* $@ ok "From:" seen. R<> $* $#error $: "553 Missing 'From:' header" #R<$+>$* $@ ok sendmail will generate from envelope