SnertSoft: We Serve Your Server

milter-sender/1.16
«Sender Address Verification.»


Description & Usage ° Installation & Notes ° License & Support

WARNING

THIS IS MAIL FILTERING SOFTWARE AND WILL BLOCK MAIL THAT FAILS TO PASS A GIVEN SET OF TESTS. SNERTSOFT AND THE AUTHOR DO NOT ACCEPT ANY RESPONSIBLITY FOR MAIL REJECTED OR POSSIBLE LOSS OF BUSINESSS THROUGH THE USE OF THIS SOFTWARE. BY INSTALLING THIS SOFTWARE THE CLIENT UNDERSTANDS AND ACCEPTS THE RISKS INVOLVED.

Description

Unsolicited bulk email, junk mail, or simply ``spam'' is the black plague of the Internet and this Sendmail mail filter attempts to address a small subset of the problem by verifying that the sender's email address is in good standing by performing an SMTP callback to the MX server responsible for the sender's domain. This milter is not intended to be a complete solution to spam and so it should be used in conjunction with other tools such as DNS blacklists and content filters.

To be in good standing, the MX server of the sender must be reachable and willing to accept email for the sender from the Delivery Status Notification (DSN) address, which is the null address <> used for error reporting. This particular requirement is similar to using the RFC-Ignornat DSN Blacklist.

During the callback, any failure in establishing an SMTP connection such as no DNS entry or the primary MX server is unreachable, or during the SMTP dialogue such as not accepting the DSN, user unknown, or mail box is full, etc. will result in the incoming mail in question being rejected. In the case of a temporary error during the SMTP dialogue with the sender's MX server, milter-sender will reject the current message with a temporary error code, which the sender is then free to retry again later. DNS lookup and connection problems are treated as temporary errors.

The milter will check secondary MX mail servers, though this does weaken the test somewhat. In order to compensate and without having to resort to sending a challenge message, a grey listing technique is applied to servers that appear to blindly accept everything.

Usage

milter-sender [options ...][arguments ...]

Options can be expressed in four different ways. Boolean options are expressed as +option or -option to turn the option on or off respectively. Options that required a value are expressed as option=value or option+=value for appending to a value list. Note that the +option and -option syntax are equivalent to option=1 and option=0 respectively. Option names are case insensitive.

Some options, like +help or -help, are treated as immediate actions or commands. Unknown options are ignored. The first command-line argument is that which does not adhere to the above option syntax. The special command-line argument -- can be used to explicitly signal an end to the list of options.

The default options, as shown below, can be altered by specifying them on the command-line or within an option file, which simply contains command-line options one or more per line and/or on multiple lines. Comments are allowed and are denoted by a line starting with a hash (#) character. If the file option is defined and not empty, then it is parsed first followed by the command-line options.

Note that there may be additional options that are listed in the option summary given by +help or -help that are not described here.

access-db=/etc/mail/access.db
The type and location of the read-only access key-value map. It provides a centralised means to black and white list hosts, domains, mail addresses, etc. The following methods are supported:
text!/path/map.txtR/O text file, memory hash
/path/map.dbBerkeley DB hash format
db!/path/map.dbBerkeley DB hash format
db!btree!/path/map.dbBerkeley DB btree format
sql!/path/databaseAn SQLite3 database
socketmap!host:portSendmail style socket-map
socketmap!/path/local/socketSendmail style socket-map
socketmap!123.45.67.89:portSendmail style socket-map
socketmap![2001:0DB8::1234]:portSendmail style socket-map

If :port is omitted, the default is 7953.

The access-db contains key-value pairs. Lookups are performed from most to least specific, stopping on the first entry found. Keys are case-insensitive.

An IPv4 lookup is repeated several times reducing the IP address by one octet from right to left until a match is found.

tag:192.0.2.9
tag:192.0.2
tag:192.0
tag:192

An IPv6 lookup is repeated several times reducing the IP address by one 16-bit word from right to left until a match is found.

tag:2001:0DB8:0:0:0:0:1234:5678
tag:2001:0DB8:0:0:0:0:1234
tag:2001:0DB8:0:0:0:0
tag:2001:0DB8:0:0:0
tag:2001:0DB8:0:0
tag:2001:0DB8:0:0
tag:2001:0DB8:0
tag:2001:0DB8
tag:2001

A domain lookup is repeated several times reducing the domain by one label from left to right until a match is found.

tag:[ipv6:2001:0DB8::1234:5678]
tag:[192.0.2.9]
tag:sub.domain.tld
tag:domain.tld
tag:tld
tag:

An email lookup is similar to a domain lookup, the exact address is first tried, then the address's domain, and finally the local part of the address.

tag:account@sub.domain.tld
tag:sub.domain.tld
tag:domain.tld
tag:tld
tag:account@
tag:

If a key is found and is a milter specific tag (ie. milter-sender-Connect, milter-sender-From, milter-sender-Auth, milter-sender-To), then the value is processed as a pattern list and the result returned. The Sendmail variants cannot have a pattern list. A pattern list is a whitespace separated list of pattern-action pairs followed by an optional default action. The supported patterns are:

[network/cidr]actionClassless Inter-Domain Routing
!pattern!actionSimple fast text matching.
/regex/actionPOSIX Extended Regular Expressions

The CIDR will only ever match for IP address related lookups.

A !pattern! uses an astrisk (*) for a wildcard, scanning over zero or more characters; a question-mark (?) matches any single character; a backslash followed by any character treats it as a literal (it loses any special meaning).

!abc!exact match for 'abc'
!abc*!match 'abc' at start of string
!*abc!match 'abc' at the end of string
!abc*def!match 'abc' at the start and match 'def' at the end, maybe with stuff in between.
!*abc*def*!find 'abc', then find 'def'

For black-white lookups, the following actions are recognised: OK or RELAY (white list), REJECT or ERROR (black list), DISCARD (accept & discard), SKIP or DUNNO (stop lookup, no result), and NEXT (opposite of SKIP, resume lookup). Its possible to specify an empty action after a pattern, which is treated like SKIP returning an undefined result. Other options may specify other actions.

Below is a list of supported tags. Other options may specify additional tags.

  
milter-sender-Connect:client-ip  value   § Can be a pattern list.
Connect:client-ip  value
client-ip  value
 
milter-sender-Connect:[client-ip]  value   § Can be a pattern list.
milter-sender-Connect:client-domain  value   § Can be a pattern list.
milter-sender-Connect:  value   § Can be a pattern list.
Connect:[client-ip] value
Connect:client-domain value
[client-ip] value
client-domain value
 
All mail sent by a connecting client-ip, unresolved client-ip address or IP addresses that resolve to a client-domain are black or white-listed. These allows you to white-list your network for mail sent internally and off-site, or connections from outside networks. Note that Sendmail also has special semantics for Connect: and untagged forms.
 
milter-sender-From:sender-address  value   § Can be a pattern list.
milter-sender-From:sender-domain  value   § Can be a pattern list.
milter-sender-From:sender@  value   § Can be a pattern list.
milter-sender-From:  value   § Can be a pattern list.
From:sender-address value
From:sender-domain value
From:sender@ value
sender-address value
sender-domain value
sender@ value
 
All mail from the sender-address, sender-domain, or that begins with sender is black or white-listed. In the case of a +detailed email address, the left hand side of the +detail is used for the sender@ lookup. Note that Sendmail also has special semantics for From: and untagged forms.
 
milter-sender-Auth:auth_authenvalue   § Can be a pattern list.
milter-sender-Auth:value   § Can be a pattern list.
 
All mail from the authenticated sender, as given by sendmail's {auth_authen} macro, is black or white-listed. The string searched by the pattern list will be the sender-address. The empty form of milter-sender-Auth: allows for a milter specific default only when {auth_authen} is defined.
 
milter-sender-To:recipient-address  value   § Can be a pattern list.
milter-sender-To:recipient-domain  value   § Can be a pattern list.
milter-sender-To:recipient@  value   § Can be a pattern list.
milter-sender-To:  value   § Can be a pattern list.
Spam:recipient-address value   * (FRIEND or HATER are recognised)
Spam:recipient-domain value   * (FRIEND or HATER are recognised)
Spam:recipient@ value   * (FRIEND or HATER are recognised)
To:recipient-address value
To:recipient-domain value
To:recipient@ value
recipient-address value
recipient-domain value
recipient@ value
 
All mail to the recipient-address, recipient-domain, or that begins with recipient is black or white-listed. In the case of a +detailed email address, the left hand side of the +detail is used for the recipient@ lookup. Note that Sendmail also has special semantics for Spam:, To:, and untagged forms.
 

The milter-sender-Connect:, milter-sender-From:, and milter-sender-To: tags provide a milter specific means to override the Sendmail variants. For example, you normally white list your local network through any and all milters, but on the odd occasion you might want to actually scan mail from inside going out, without removing the Connect: tag that allows Sendmail to relay for your network or white listing for other milters. So for example if you have Sendmail tags like:

To:mx.example.comRELAY

You might have to add milter specific overrides in order to make sure the mail still gets filtered:

To:mx.example.comRELAY
milter-sender-To:mx.example.comSKIP

Some additional examples:

milter-sender-Connect:80.94 [80.94.96.0/20]OK  REJECT
 
Accept connections from the netblock 80.94.96.0/20 (80.94.96.0 through to 80.94.111.255) and rejecting anything else in 80.94.0.0/16.
 
milter-sender-Connect:192.0.2 /^192\.0\.2\.8[0-9]/OK  REJECT
 
Accept connections from 192.0.2.80 through to 192.0.2.89, reject everything else in 192.0.2.0/24.
 
milter-sender-From:example.com /^john@.+/OK  /^fred\+.*@.*/OK  REJECT
 
Accept mail from <john@example.com> and <fred@example.com> when fred's address contains a plus-detail in the address. Reject everything else from example.com.
 
milter-sender-To:example.net !*+*@*!REJECT  !*.smith@*!REJECT  /^[0-9].*/REJECT
 
Reject mail to example.net using a plus-detail address or to any user who's last name is "smith" or addresses starting with a digit. No default given, so B/W processing would continue.
 

Normally when the access.db lookup matches a milter tag, then the value pattern list is processed and there are no further access.db lookups. The NEXT action allows the access.db lookups to resume and is effectively the opposite of SKIP. Consider the following examples:

milter-sender-From:com
From:com
/@com/REJECT  NEXT
OK
 
Reject mail from places like compaq.com or com.com if the pattern matches, but resume the access.db lookups otherwise.
 
milter-sender-From:aol.com  
From:fred@aol.com  
/^[a-zA-Z0-9!#$&'*+=?^_`{|}~.-]{3,16}@aol.com$/NEXT  REJECT
OK
 
AOL local parts are between 3 and 16 characters long and can contain dots and RFC 2822 atext characters except % and /. The NEXT used above allows one simple regex to validate the format of the address and proceed to lookup white listed and/or black listed addresses.
 
CacheAcceptTTL=604800
Senders that successfully pass the MX callback and upgraded grey-listing entries will be cached for the given number of seconds. Specify zero (0) to disable caching of successful senders. The default is 604 800 seconds (1 week). Note the cache is preserved across restarts if milter-sender is built with Berkeley DB support.
CacheFile=/var/db/milter-sender
The cache file path may be specified for the bdb or flatfile types. The default is found in either /var/db/milter-sender (BSD variant) or /var/cache/milter-sender (Linux). If you switch CacheType, you might at least want to switch the cache file extension or delete the old cache file, so that when the milter is restarted the correct file is read or created.
CacheGcFrequency=250
This option specifies the cache garbage collection frequency, which is based on the number of SMTP connections (not messages) handled by the milter. Every N connections, the cache is traversed to remove expired entries. The default is every 250 connections.
CacheGreyListTTL=86400
This is the number of seconds that a grey-list temporary entry will be cached. Specify zero (0) to disable grey-listing.

Grey listing support in milter-sender is used as secondary technique when the MX server appears to blindly accept any and all email addresses, probably because its a secondary MX or gateway.

The current message is temporarily rejected and the tuple given by MxAcceptsAll is grey-listed in the cache for the number of seconds specified by CacheGreyListTTL. A legitimate server is expected to retry to send the message when it next processes its message queue. The temporary reject policy remains in force until GreyListBlockTime seconds has elapsed, at which point the message is allowed to be delivered.

This is a variation of the grey-listing concept as originally outlined in "The Next Step in the Spam Control War: Greylisting".

CacheHashBucketDensity=75
The Berkeley DB hash bucket density value used for the cache. If this value is changed and there already exists a cache database, then it must be deleted in order for the new value to take effect.
CacheRejectTTL=0
Senders that are rejected by the MX callback will be cached for the given number of seconds. Specify zero (0) to disable caching rejections (default). Note the cache is preserved across restarts if milter-sender is built with Berkeley DB support.

This option is intended to temporarily block a sender that failed an MX callback, the idea being that if they are a junk mailer, they will probably make repeated attempts to connect in a short time frame and we can reduce network traffic and testing time by avoiding lots of MX callbacks for a known result. However, if the sender is legitimate, but an MX callback failed because of a full mailbox for example, then their mail will be rejected until the cache entry expires. Therefore, its recommended when using this option to choose a conservative value that is on the order of a few minutes to an hour.

CacheType=bdb
The cache type can be one of: bdb, flatfile, hash.
-ClientIsForged
This option rejects a connecting client IP where the PTR and A DNS lookups do not map to one another. Using this option may result in more legitimate email being turned away, because of badly configured DNS entries The equivalent of this option can be achieved with a ruleset in the sendmail.cf file (see The Bat Book 3ed § 21.9.22).
-ClientNeedsPTR
This option requires that a connecting client IP have a PTR record in the DNS, without evaluating it further. This is a weaker requirement than ClientIsForged. The equivalent of this option can be achieved with a ruleset in the sendmail.cf file (see The Bat Book 3ed § 21.9.22).
ClientReject=benchmark,loopback,multicast,reserved,test-net,this-net
A comma separated word list. Reject a connection from RFC 3330, 3513, or 3849 reserved IP addresses.
all all reserved IP address  
0 accept all.  
benchmark 198.18.0.0/15 RFC 2544
link-local 169.254.0.0/16, FE80::/10 RFC 3330, 3513
localhost 127.0.0.1, ::1 RFC 3330, 3513
loopback 127.0.0.0/8 excluding 127.0.0.1
multicast 224.0.0.0/4, FF00::/8 RFC 3330, 3513
private-a 10.0.0.0/8 RFC 3330
private-b 172.16.0.0/12 RFC 3330
private-c 192.168.0.0/16 RFC 3330
reserved IPv6 unassigned prefixes RFC 3513
site-local FEC0::/10 RFC 3513
test-net 192.0.2.0/24, 2001:DB8::/32 RFC 3513, 3849
this-net 0.0.0.0/8, ::0 RFC 3330, 3513
+daemon
Start as a background daemon or foreground application.
-DebugLogOnly
Debug option that allows milter-sender to operate, but never reject a message. Intended for debugging and verification of what would be rejected and for what reasons, before actually doing so. Note that this does not change the Sendmail LogLevel or /etc/syslog.conf level.
-DeferHeloReject
If the client connection or HELO/EHLO argument is rejected, then defer the rejection until after the sender argument has been received. This allows for white-listing of a sender to override a connection/HELO rejection. This is similar to DeferMailReject option and Sendmail's FEATURE(`delay_checks'), however combining DeferHeloReject and DeferMailReject does NOT defer the rejection until recipients are checked, which is different from FEATURE(`delay_checks').
-DeferMailReject
If the MX callback for the sender address failed, then do not immediately reject the sender. Instead collect recipients and reject all recipients not explicitly white listed by the Sendmail access database. This allows those desperate sort of people who fear to loose any sort of email to receive everything addressed to them or their domain, while filtering everyone else who understand its not the end of the world. Sendmail applies its own rules in between calls to milter-sender for a recipient, therefore its possible for Sendmail to reject or accept the message ahead of milter-sender.
-DnsRejectOnError
Some intermediate MX servers blindly accept mail from non- existant domains and then proceed to relay the message. Subsequent DNS lookups by a milter-sender server report a DNS error of some kind and temporary fail the message (see RFC 974). The blind MX host then requeues the message and keeps making attempts to send it, constantly being temp. failed. This can create something resembling a Denial of Service if the blind MX has queued a sufficent number of bogus domain messages and has short retry times.
-FailWelcome554=
Reject MX servers that return a "554 No SMTP service here" greeting.
file=/etc/mail/milter-sender.cf
Read the option file before command line options. This option is set by default. To disable the use of an option file, simply say file=''
-help or +help
Write the option summary to standard output and exit. The output is suitable for use as an option file.
GreyListBlockTime=600
The amount of time in seconds that a message corresponding to the the connecting IP, sender, and recipient tuple will be temporarily blocked. This value must be less than CacheGreyListTTL. A value between 10 to 30 minutes is suggested as reasonable.
+HeloClaimsUs
This option enables/disables the HELO "claims to be us" test that is posing some trouble for multi-homed servers and fetchmail setups. This option is a temporary workaround until a better solution can be implemented. The equivalent of this test, that maybe more efficient, can be done using Sendmail rulesets. See the contrib/cookbook.mc for details.
+HeloLookupHostIp
Lookup the IP address of the HELO argument. This option does not reject/accept based on the success of the lookup. It influences the HeloReject* family of tests such that the IP address of a full qualified domain name is lookup and then compared against RFC 3330 special addresses. When disabled, only IP address arguments are tested.
HeloReject=benchmark,loopback,multicast,reserved,test-net,this-net
A comma separated word list. Reject a HELO argument from RFC 3330, 3513, or 3849 reserved IP addresses.
all all reserved IP address  
0 accept all.  
benchmark 198.18.0.0/15 RFC 2544
link-local 169.254.0.0/16, FE80::/10 RFC 3330, 3513
localhost 127.0.0.1, ::1 RFC 3330, 3513
loopback 127.0.0.0/8 excluding 127.0.0.1
multicast 224.0.0.0/4, FF00::/8 RFC 3330, 3513
private-a 10.0.0.0/8 RFC 3330
private-b 172.16.0.0/12 RFC 3330
private-c 192.168.0.0/16 RFC 3330
reserved IPv6 unassigned prefixes RFC 3513
site-local FEC0::/10 RFC 3513
test-net 192.0.2.0/24, 2001:DB8::/32 RFC 3513, 3849
this-net 0.0.0.0/8, ::0 RFC 3330, 3513
+HeloRejectRfc2606
Reject a HELO using RFC 2606 reserved domain names.
-IsBackupMx
The machine running milter-sender is a secondary backup-MX. If MxCallAhead is enabled and fails to connect to the primary machine, then continue processing the message instead of a temporary rejection.
milter-socket=unix:/var/run/milter/milter-sender.socket
A socket specifier used to communicate between Sendmail and milter-sender. Typically a unix named socket or a host:port. This value must match the value specified for the INPUT_MAIL_FILTER() macro in the sendmail.mc file. The accepted syntax is:
{unix|local}:/path/to/file
A named pipe. (default)
inet:port@{hostname|ip-address}
An IPV4 socket.
inet6:port@{hostname|ip-address}
An IPV6 socket.
milter-timeout=7210
The sendmail/milter I/O timeout in seconds.
MxAcceptsAll=ip,mail,rcpt
milter-sender assumes that the MX server being queried will return an error for the RCPT command for such things as a mailbox full or bad recipient. However, Yahoo, and possible other mail providers will not report an error until some message content has been transmitted. RFC 2821 section 3.3 Mail Transactions allows for this sequence of events, ie. that MAIL and RCPT verification need not take place until after the message content has been sent.

milter-sender detects this situation by testing for an error result from a RCPT command with an intentionally false address, prior to checking the sender's address. This option specifies either to reject messages from such machines or the elements to be used for a grey-listing key. See CacheGreyListTTL.

reject if the MX appears to accept false addresses, reject the message
ip client IP address is part of the grey-list key
helo HELO argument is part of the grey-list key
mail MAIL argument is part of the grey-list key
rcpt RCPT argument is part of the grey-list key
MxCallAhead=0
Number (0, 1, 2) If non-zero, then check the RCPT address with the next hop. Intended as a poor man's LDAP for gateways that want to validate recipients with an internal mail store. This option relies on FEATURE(`mailertable') table and entries specified with MX lookups disabled:
snert.com esmtp:[pop.snert.net]

With the square-brackets around a host name or IP, the route is defined. If this option is set to one (1), then it will not perform MX lookups when the square brackets are missing. It was intended for mail gateways that know exactly the host of the next hop.

If this option is set to two (2), then MX lookups of the {rcpt_host} value or MxCallAheadDb entries will be attempted first, then followed by {rcpt_host}.

MxCallAheadDb=
When specified, the parameter is the type and location of a read-only key-value map. The following variants are supported:
text!/path/map.txtR/O text file, memory hash
/path/map.dbBerkeley DB hash format
db!/path/map.dbBerkeley DB hash format
db!btree!/path/map.dbBerkeley DB btree format
sql!/path/databaseAn SQLite3 database
socketmap!host:portSendmail style socket-map
socketmap!/path/local/socketSendmail style socket-map
socketmap!123.45.67.89:portSendmail style socket-map
socketmap![2001:0DB8::1234]:portSendmail style socket-map

The recipient's domain is first used as the lookup key followed by each parent domain component that makes up the domain name. If no key is found, then the value of {rcpt_host} will be used.

When a key is found, then the value returned must be the name or IP of the mail server to consult surrounded by square brackets. Below is an example of a database file, similar to mailertable without the mailer designation:

snert.com [pop.snert.net]  
snert.info [pop.snert.net]  
snert.net snert.org Without [ and ], MxCallAhead=2 required.
mx.snert.net [mx.snert.net]  
MxCallAheadHost=host
Force the call-ahead always to this host, overriding the ${rcpt_host} determined by Sendmail. This option is undefined by default.
-MxCallAheadImplicitMx
Try the implicit MX for {rcpt_host} when no other MX answers. Used in special cases where for example departmental subdomain MXes point to a gateway MX and rely on the implicit MX rule with an A record to route the mail internally to the departmental mail store.
-MxCallAheadNotRcptHost
When using the MxCallAheadDb option, in particular to call-ahead past an anti-virus server for example, falling back on the {rcpt_host} for the call-ahead would result often in a redundant connection to a machine that accepts any recipient. This option disables the call-ahead when {rcpt_host} is the target.
-MxCallBackAsPostmaster
Experimental. Use an alternative address <postmaster@our.host.name> in place of the DSN address. This is to address the increasing number of RFC clueless sites that choose to block the DSN address.
+MxCallBackConnect
This option can disable the SMTP callback, effectively making it a noop. All the tests leading upto the SMTP connection, such as MX lookup and MxReject tests are still performed to validate DNS entries. To disable the MX lookup, MxReject tests, and the SMTP callback, specify MxCallBackMaxAttempts=0 instead.
-MxCallBackDsnBlocked
This option will fall back on grey-listing if the MX being tested rejects the null address used for DSN messages. By default this option is disabled, which requires that mail servers be RFC compliant with respect to the null address <>.
-MxCallBackIpBlocked
Some milter-sender servers might be blocked by IP (too many call-backs mistaken for address harvesting or a dynmaic IP address). If the call-back is rejected with a 500 class error and the milter-sender server's IP appears in the error response, then this option short-circuits the call-back and proceeds as though the MX server accepted any address and thus falls back on the MxAcceptsAll setting. This allows the milter-sender server to accept, reject, or use grey-listing. See also PublicIp.
MxCallBackMaxAttempts=3
Enable the MX callback for the sender address with the maximum number of MX hosts that will be checked per message before reporting a failure. Zero (0) disables the MX callback. The default is 3.
MxReject=all
A comma separated word list. Reject an MX that resolves to RFC 3330, 3513, or 3849 reserved IP addresses.
all all reserved IP address  
0 accept all.  
benchmark 198.18.0.0/15 RFC 2544
link-local 169.254.0.0/16, FE80::/10 RFC 3330, 3513
localhost 127.0.0.1, ::1 RFC 3330, 3513
loopback 127.0.0.0/8 excluding 127.0.0.1
multicast 224.0.0.0/4, FF00::/8 RFC 3330, 3513
private-a 10.0.0.0/8 RFC 3330
private-b 172.16.0.0/12 RFC 3330
private-c 192.168.0.0/16 RFC 3330
reserved IPv6 unassigned prefixes RFC 3513
site-local FEC0::/10 RFC 3513
test-net 192.0.2.0/24, 2001:DB8::/32 RFC 3513, 3849
this-net 0.0.0.0/8, ::0 RFC 3330, 3513
-OneRcptPerBounce
Allow only one RCPT when MAIL FROM:<> is given. RFC 2505 § 2.6.1 discourages this.
pid-file=/var/run/milter/milter-sender.pid
The file path of where to save the process-id.
-PrimaryMxAliveReject
For a backup-MX, reject mail when the primary MX is available during the MxCallAhead. This does not conform with RFC 974 section "Interpreting the List of MX RRs", paragraph 7, sentence 2 and 3, which only requires mail clients to attempt delivery to the primary first, before trying another.

Spammers often attempt to by-pass spam filters by sending email directly to secondary MX machines, which often have weaker requirements. This option essentially demands that a client only deliver to the primary MX when it is available. Use with care.

PublicIp=
This option is empty by default. It is currently used in conjunction with MxCallBackIpBlocked to specify the IP address string to search for in error responses during the call-back. Intended for mail servers behind a NAT/firewall or similar situation where the Sendmail ${if_addr} macro is not the same as your publicly visible IP address.
PublicName=
This option is empty by default. Its intended for people who fail to configure /etc/hosts or sendmail properly so as to specify a FQDN for either the ${if_name} that sendmail listens on or $j macro for the machine name. This value is used for the HELO argument during the callback and the "claims to be us" test.

If PublicName= is defined, is not empty, and is a FQDN, then this value is used; else the value of ${if_name} is used if it is not empty and a FQDN; else the value of $j is used if it is not empty and a FQDN; otherwise the value of "127.0.0.1" is used as a last resort.

-quit or +quit
Quit an already running instance of the milter and exit. This is equivalent to: kill -QUIT `cat /var/run/milter/milter-sender.pid`
-restart or +restart
Terminate an already running instance of the milter before starting.
run-group=milter
The process runtime group name to be used when started by root.
run-user=milter
The process runtime user name to be used when started by root.
+smtp-auth-ok
Allow SMTP authenticated senders to send unscanned mail. See also the milter-sender-auth: tag (access-db=) for finer granularity of control.
SocketTimeout=120
Specify the socket timeout in seconds to wait for SMTP responses during the MX callback. A zero (0) value will set the timeout to indefinite. The default is 120 seconds. Note that RFC 2821 § 4.5.3.2 recommends some rather historically large timeout values, which can be rather impractical for the proper functioning of any milter (see Sendmail concerning the settings for F= and T=).
-TlsRejectIfMissing
Reject connection if no TLS/SSL in use or no certificate presented. This option should be used with caution since there are many SMTP servers that still do not support TLS/SSL level encryption yet. The equivalent of this option can be added to a ruleset in the sendmail.cf file (see The Bat Book 3ed)
-TlsRejectInvalid
Reject connection if certificate is invalid. When true then self-signed certificates will be rejected, unless you have installed the sender's root certificate. The equivalent of this option can be added to a ruleset in the sendmail.cf file (see The Bat Book 3ed)
+TlsRejectTemporary
Reject connection on temporary encryption error. The equivalent of this option can be added to a ruleset in the sendmail.cf file (see The Bat Book 3ed)
+TlsRejectProtocol
Reject connection on an encryption protocol error. The equivalent of this option can be added to a ruleset in the sendmail.cf file (see The Bat Book 3ed)
UpstreamMxList=
A comma separated list of host names and/or IP addresses for our upstream MX servers.

Normally for a call-back we return to the client connection the SMTP return code given by the call-back, so a temporary reject from the call-back is temporary reject to the client and likewise for permanent reject.

When the connecting client is one of our upstream MX servers and the first call-back to a sender's MX results in a temporary reject, then return a permanent reject to the client, otherwise the upstream MX will continue to retry the message until either a repeated call-back succeeds, results in a permanent reject, or the upstream MX expires the message from the retry queue. This alteration of the result assumes that repeated call-backs will continue to result in a temporary reject and so result in many useless delivery attempts by upstream MX servers and call-backs by us.

verbose=info
A comma separated list of how much detail to write to the mail log. Those mark with § have meaning for this milter.
§ all All messages
§ 0 Log nothing.
§ info General info messages. (default)
§ trace Trace progress through the milter.
§ parse Details from parsing addresses or special strings.
§ debug Lots of debug messages.
§ dialog I/O from Communications dialog
  state State transitions of message body scanner.
§ dns Trace & debug of DNS operations
§ cache Cache get/put/gc operations.
§ database Sendmail database lookups.
§ socket-fd Socket open & close calls
§ socket-all All socket operations & I/O
§ libmilter libmilter engine diagnostics
work-dir=/var/tmp
The working directory of the process. Normally serves no purpose unless the kernel option that permits daemon process core dumps is set.
-XAuthenticatedSender
Add an X-Authenticated-Sender header showing authentication information and IP address.
-XScannedBy
Add an X-Scanned-By trace header.

SMTP Responses

This is the the list of possible SMTP reponses generated by milter-sender. Note that Sendmail will insert the email address in question between the extended status code and the response for MAIL and RCPT errors.

550 5.7.1 HELO .+ claims to be us '[^']+' \[[^]]+\], but the connection \[[^]]+\] is not from us
The client connection cannot claim to be milter-host and originate from a different IP. All subsequent commands will be rejected for the remainder of the connection. See HeloClaimsUs option
550 5.7.1 connection \[[^]]+\] from RFC 3330, 3513 reserved IP address blocked
The client connection cannot originate from reserved IP addresses. See ClientReject option.
550 5.7.1HELO .+ from RFC 3330, 3513 reserved IP address blocked
The HELO argument (or resolved IP, see HeloLookupHostIp option) cannot specify as reserved IP address. See HeloReject option.
550 5.7.1 HELO .+ from RFC 2606 reserved domains blocked
The HELO argument cannot specify RFC 2606 reserved domain names. See HeloRejectRfc2606 option.
550 5.7.1 encryption required
550 5.7.1 server certificate required
550 5.7.1 server certificate invalid
450 4.7.1 temporary encryption error
550 5.7.1 encryption protocol error
Assert that client connection uses TLS/SSL to encrypt the connection. See TlsReject* options.
550 5.7.1 connection [^ ]+ \[[^]]+\] rejected
The domain or IP address of the connecting client is marked as REJECT in the access database. All subsequent commands will be rejected for the remainder of the connection.
550 5.7.1 connection [%s] is forged (PTR and A records mismatch)
See ClientIsForged.
450 4.7.1 connection "[^"]+" failed to resolve
550 5.7.1 connection "[^"]+" failed to resolve
The IP of the client connection must resolve to a domain name, ie. pass Sendmail's reverse DNS lookup. See ClientNeedsPTR option. All subsequent commands will be rejected for the remainder of the connection.
553 5.1.0 imbalanced angle brackets in path
The path given for a MAIL or RCPT command is missing a closing angle bracket
553 5.1.0 address does not conform to RFC 2821 syntax
The address is missing the angle brackets, < and >, as required by the RFC grammar.
553 5.1.0 local-part too long
The stuff before the @ is too long.
553 5.1.[37] invalid local part
The stuff before the @ sign contains unacceptable characters.
553 5.1.0 domain name too long
The stuff after the @ is too long.
553 5.1.7 address incomplete
Expecting a domain.tld after the @ sign and found none.
553 5.1.[37] invalid domain name
The domain after the @ sign contains unacceptable characters.
550 5.7.1 sender blocked
550 5.7.1 recipient blocked
Mail address or domain marked as REJECT in the access database or conflicts RFC 2606.
450 4.7.1 sender denied for [0-9]+ seconds
Sender's address failed a previous call back attempt. Now rejected temporarily. See CacheRejectTTL option.
451 4.4.3 DNS connection error
Failed to open connections to the DNS servers. See MxCallBackMaxAttempts option.
451 4.4.3 '[^']+' lookup failed: .+
553 5.4.4 '[^']+' lookup failed: .+
The DNS lookup for a domain failed for a particular reason. See MxCallBackMaxAttempts option.
451 4.4.3 internal DNS error looking up '[-.a-zA-z0-9]+'
A system function returned an error preventing DNS lookup. See MxCallBackMaxAttempts option.
554 5.4.4 '%s' has no acceptable MX server
See MxReject.
451 4.4.4 cannot determine MX for <[^>]+>
DNS lookup returned an empty list. No MX or IP address found for sender's domain. See MxCallBackMaxAttempts option.
550 5.0.0 internal error converting {if_addr}='[^']*'
SocketAddressToIP() failed to convert the address string to a binary representation. See MxCallBackMaxAttempts option.
xyz x.7.1 MX [0-9]+ [^ ]+ \[[^]]+\] for <[^>]+> communication error
xyz x.7.1 MX [0-9]+ [^ ]+ \[[^]]+\] for <[^>]+> broke connection
xyz x.7.1 MX [0-9]+ [^ ]+ \[[^]]+\] for <[^>]+> not answering
xyz x.7.1 MX [0-9]+ [^ ]+ \[[^]]+\] for <[^>]+> responded with a busy signal
xyz x.7.1 MX [0-9]+ [^ ]+ \[[^]]+\] for <[^>]+> provides no SMTP service
xyz x.7.1 MX [0-9]+ [^ ]+ \[[^]]+\] for <[^>]+> responded with: .*
xyz x.7.1 MX [0-9]+ [^ ]+ \[[^]]+\] for <[^>]+> did not accept HELO
xyz x.7.1 MX [0-9]+ [^ ]+ \[[^]]+\] for <[^>]+> rejected address saying: .*
xyz x.7.1 MX [0-9]+ [^ ]+ \[[^]]+\] for <[^>]+> rejected
xyz x.7.1 MX [0-9]+ [^ ]+ \[[^]]+\] for <[^>]+> did not accept DATA
xyz x.7.1 MX [0-9]+ [^ ]+ \[[^]]+\] for <[^>]+> did not accept NOOP
xyz x.7.1 MX [0-9]+ [^ ]+ \[[^]]+\] for <[^>]+> did not accept RSET
xyz x.7.1 MX [0-9]+ [^ ]+ \[[^]]+\] for <[^>]+> rejected message saying: .*
The value returned for xyz by the MX being checked is passed along to the connecting client. See MxCallBackConnect and MxCallBackMaxAttempts options.
xyz x.7.1 MX [0-9]+ '[^']+' \[[^]]+\] for <[^>]+> did not accept the empty address, <>, as required by RFC 821, 1123, 2505, and 2821
The MX rejected MAIL FROM:<> contrary to the RFC. The value returned for xyz by the MX being checked is passed along to the connecting client. See MxCallBackConnect and MxCallBackDsnBlocked options.
xyz x.7.1 MX [0-9]+ '[^']+' \[[^]]+\] for <[^>]+> appears to be blocking our IP
The value returned for xyz by the MX being checked is passed along to the connecting client. See MxCallBackConnect, MxCallBackIpBlocked, and PublicIp options.
452 4.5.3 too many recipients
Only one RCPT command allowed in combination with MAIL FROM:<>, since there should normally only be one original sender to which an error message can be returned. See OneRcptPerBounce option.
550 5.7.1 routed address relaying denied
The recipient address tried to use the %-hack for routed address relaying.
xyz x.7.1 server [^ ]+ for <[^>]+> communication error
xyz x.7.1 server [^ ]+ for <[^>]+> broke connection
xyz x.7.1 server [^ ]+ for <[^>]+> not answering
xyz x.7.1 server [^ ]+ for <[^>]+> responded with: .*
xyz x.7.1 server [^ ]+ for <[^>]+> did not accept HELO
xyz x.7.1 server [^ ]+ for <[^>]+> did not accept the empty address, <>, as required by RFC 821, 1123, 2505, and 2821
xyz x.7.1 server [^ ]+ for <[^>]+> rejected address saying: .*
xyz x.7.1 server [^ ]+ for <[^>]+> rejected
xyz x.7.1 server [^ ]+ for <[^>]+> did not accept DATA
xyz x.7.1 server [^ ]+ for <[^>]+> did not accept NOOP
xyz x.7.1 server [^ ]+ for <[^>]+> did not accept RSET
xyz x.7.1 server [^ ]+ for <[^>]+> rejected message saying: .*
xyz x.7.1 server [^ ]+ for <[^>]+> appears to be blocking our IP
The value returned for xyz by the server being checked is passed along to the connecting client. See MxCallAhead option.
xyz x.7.1 server [^ ]+ for <[^>]+> responded with a busy signal
The value returned for xyz by the server being checked is passed along to the connecting client. See MxCallAhead and IsBackupMx options.
xyz x.7.1 server [^ ]+ for <[^>]+> provides no SMTP service
The value returned for xyz by the server being checked is passed along to the connecting client. See MxCallAhead, IsBackupMx, and FailWelcome554 options.
450 4.7.1 server [^ ]+ for <[^>]+> online and accepting mail
See MxCallAhead and PrimaryMxAliveReject options.
450 4.7.1 from <[^>]+> via \[[^]]+\] to <[^>]+> denied for [0-9]+ seconds
A connecting IP, sender, and recipient tuple is grey-listed and temporarily rejected. See MxAcceptsAll, GreyListBlockTime, and CacheGreyListTTL options.
450 4.7.1 from <[^>]+> via \[[^]]+\] denied for [0-9]+ seconds
A connecting IP and sender pair is grey-listed and temporarily rejected. See MxAcceptsAll, GreyListBlockTime, and CacheGreyListTTL options.
[45]50 [45].7.1 recipient denied, because .+
The call back failed earlier and the recipient is not white listed in the access database. The original call back error is reported.

Installation

  1. Download:

    milter-sender/1.16 md5sum Change Log
    LibSnert md5sum Change Log
    Sendmail 8.14   http://www.sendmail.org/
    Berkeley DB   http://www.sleepycat.com/
  2. In order to support B/W lists milter-sender requires Berkeley DB 3 or better. If you do not require support for Sendmail's access database, skip this step.

    1. You should build and install Berkeley DB library first, if you do not already have it. Please read the Berkeley DB documentation on how to build the library. Briefly, it should be something like this:

      cd (path to)/db-4.3.27/build_unix
      ../dist/configure
      make
      make install
      

      If your system is Linux and you install Berkeley DB in the default, non- standard, location then you must remember to update /etc/ld.so.conf and run ldconfig. You can change the default install location by specifying the ../dist/configure option --prefix=/usr/local for example.

    2. Note that Sendmail will probably have to be rebuilt to use Berkeley DB, especially if the library was never installed and/or Sendmail was built against an older version of Berkeley DB. Please see the Sendmail documentation as to how this is done. The following is a brief outline, however be sure to read devtools/README, devtools/Site/README, and "Using Berkeley DB with Sendmail" for details on how to configure the Sendmail build process. Outline of steps

      cd (path to)/sendmail-8.14.0
      vi devtools/Site/site.config.m4
      sh Build -c install
      
  3. If you have never built a milter for Sendmail, then please make sure that you build and install libmilter, which is not built by default when you build Sendmail. Please read the libmilter documentation. Briefly, it should be something like this:

    cd (path to)/sendmail-8.14.0/libmilter
    sh Build -c
    sh Build install
    
  4. The build process for libsnert and milter-sender is pretty straight forward once you have libmilter installed:

    cd (path to)/com/snert/src/lib
    ./configure
    make build
    cd ../milter-sender
    ./configure
    make build
    make install
    

    Both configuration scripts have some options that allow you to override defaults. Those options are listed with:

    ./configure --help
    
  5. An example ${prefix}/share/examples/milter-sender/milter-sender.mc is supplied. This file should be reviewed and the necessary elements inserted into your Sendmail .mc file and sendmail.cf rebuilt. Please note the comments on the general milter flags.

    dnl -------------------------------------------------------------------
    dnl milter-sender.mc				$custom$
    dnl -------------------------------------------------------------------
    dnl Example configuration to be added to sendmail.mc.
    dnl
    
    dnl -------------------------------------------------------------------
    dnl Enable this for debug output from Sendmail.
    
    dnl define(`confLOG_LEVEL', `14')dnl
    
    dnl -------------------------------------------------------------------
    dnl Enable this to see even more debug output.
    dnl Defaults to confLOG_LEVEL.
    dnl
    dnl If Milter.LogLevel is greater-than:
    dnl
    dnl	0	Communication errors
    dnl	8	Header & RCPT modification messages
    dnl	9	Connect to info
    dnl	10	Milter error return codes, abort messages
    dnl	12	More return code info, connection/open errors
    dnl	14	grey & rcpts info
    dnl	17	Show headers & body sent to a milter.
    dnl	18	Quit
    dnl	21	Time a milter
    
    dnl define(`confMILTER_LOG_LEVEL', 14)dnl
    
    dnl -------------------------------------------------------------------
    dnl Note that the F= says what to do with the message if the milter
    dnl is not running.
    dnl
    dnl	F=T	Temporary fail connection if filter unavailable
    dnl	F=R	Reject connection if filter unavailable
    dnl
    dnl If no F= specified and there is a problem with the milter, then
    dnl the default is to continue normal handling, skipping the milter.
    dnl
    dnl Note that the T= specifies timeouts for communication. The
    dnl following fields are defined:
    dnl
    dnl	C	Timeout for connecting to a filter. If set to zero (0),
    dnl		the system's connect() timeout will be used. Default: 5m
    dnl	S	Timeout for sending information from the MTA to a
    dnl		filter. Default: 10s
    dnl	R	Timeout for reading reply from the filter. Default: 10s
    dnl	E	Overall timeout between sending end-of-message to filter
    dnl		and waiting for the final acknowledgment. Default: 5m
    dnl
    dnl So the default values are equivalent to:
    dnl
    dnl	T=C:5m;S=10s;R=10s;E:5m
    dnl
    
    INPUT_MAIL_FILTER(
    	`milter-sender',
    	`S=unix:/var/run/milter/milter-sender.socket, T=C:1m;S:30s;R:6m'
    )dnl
    
    dnl The default for confMILTER_MACROS_CONNECT is typically
    dnl `j, _, {daemon_name}, {if_name}, {if_addr}'
    define(`confMILTER_MACROS_CONNECT', confMILTER_MACROS_CONNECT`, {client_resolve}')dnl
    
    dnl The default for confMILTER_MACROS_HELO is typically
    dnl `{tls_version}, {cipher}, {cipher_bits}, {cert_subject}, {cert_issuer}'
    define(`confMILTER_MACROS_HELO', confMILTER_MACROS_HELO`, {verify}')dnl
    
    dnl
    dnl Disables VRFY, EXPN, requires HELO, no return receipts,
    dnl bounce messages without message body. The important one
    dnl required by milter-sender is `needmailhelo'. The others
    dnl are recommended.
    dnl
    dnl goaway = 	authwarnings, noexpn, novrfy, noverb, needmailhelo,
    dnl 		needexpnhelo, needvrfyhelo, nobodyreturn
    dnl
    dnl
    define(`confPRIVACY_FLAGS',`goaway,noreceipts')
    
    dnl -------------------------------------------------------------------
    dnl End milter-sender.mc
    dnl -------------------------------------------------------------------
    
    
  6. Once installed and configured, start milter-sender and then restart Sendmail. An example startup script is provided in ${prefix}/share/examples/milter-sender/milter-sender.sh The default options can be altered by specifying them on the command-line or within a /etc/mail/milter-sender.cf. The milter-sender.cf is parsed first followed by the command-line options.

Notes

  • Currently tested platforms:

    FreeBSD 4.4+ (x386); Debian Linux 3.0 (64 bit UltraSparc); Red Hat Linux 5.1+ (mips, x386); Mandrake Linux 9 (x386); NetBSD 1.5.2; OpenBSD 3.6 (Intel x386) SunOS 5.8 (sparc)
  • The minimum desired file ownership and permissions are as follows for a typical Linux system. For FreeBSD, NetBSD, and OpenBSD the binary and cache locations may differ, but have the same permissions.

    Process user ``milter'' is primary member of group ``milter'' and secondary member of group ``smmsp''. Note that the milter should be started as root, so that it can create a .pid file and .socket file in /var/run; after which it will switch process ownership to milter:milter before starting the accept socket thread.

    /etc/mail/root:smmsp0750 drwxr-x---
    /etc/mail/access.dbroot:smmsp0640 -rw-r-----
    /etc/mail/sendmail.cfroot:smmsp0640 -rw-r-----
    /etc/mail/milter-sender.cfroot:root0644 -rw-r--r--
    /var/run/milter/milter-sender.pidmilter:milter0644 -rw-r--r--
    /var/run/milter/milter-sender.socketmilter:milter0644 srw-r--r--
    /var/db/milter-sendermilter:milter0644 -rw-r--r-- (*BSD)
    /var/cache/milter-sendermilter:milter0644 -rw-r--r-- (linux)
    /usr/local/libexec/milter-senderroot:milter0550 -r-xr-x---
  • What is "the MX mail server"? MX refers to the Domain Name Service (DNS) record that directs mail servers sending mail to the mail servers that are responsible for handling incoming mail for specific domains.

    RFC 1035 Domain Names - Implementation and Specification
    section 3.3.9. MX RDATA Format
    RFC 974 Mail Routing and The Domain System
  • Its an error to specify private or special purpose addresses like locahost (127.0.0.1) for public DNS records.

    RFC 3513 Internet Protocol Version 6 (IPv6) Addressing Architecture
    section 4. IANA Considerations summary
    RFC 3330 Special-Use IPv4 Addresses
    section 3. Summary Table
    RFC 1918 Address Allocation for Private Internets
    section 3. Private Address Space
  • Relevant RFC references concerning the requirement for the Null Address (<>) used for Delivery Status Notification:

    RFC 2821 Simple Mail Transfer Protocol
    section 4.1.1.2 MAIL, BNF grammar
    section 6.1 Reliable Delivery and Replies by Email, paragraph 2
    RFC 2505 Anti-Spam Recommendations for SMTP MTAs
    section 2. Recommendations 6a.
    section 2.6.1. "MAIL From: <>"
    RFC 1123 Requirements for Internet Hosts -- Application and Support
    section 5.2.9 Command Syntax: RFC-821 Section 4.1.2
    RFC 821 Simple Mail Transfer Protocol
    (obsoleted by RFC 2821)
    section 3.6
    section 4.1.1
  • Volker Stolz comments on using fetchmail with milter-sender:

    If you use fetchmail to talk with a sendmail/milter-sender server then either:
    1. whitelist the fetchmail client machine in the access database,
    2. use the fetchmail --mda option to invoke a local mailer
  • There has been some questions raised as to whether or not milter-sender is conformant with respect to RFC 2821 section 5, paragraph 2, which states:

    When the lookup succeeds, the mapping can result in a list of alternative delivery addresses rather than a single address, because of multiple MX records, multihoming, or both. To provide reliable mail transmission, the SMTP client MUST be able to try (and retry) each of the relevant addresses in this list in order, until a delivery attempt succeeds. However, there MAY also be a configurable limit on the number of alternate addresses that can be tried. In any case, the SMTP client SHOULD try at least two addresses.

    The first MUST clause is addressed correctly. milter-sender will try the MX list starting with the lowest preference (the primary MX).

    The MAY clause allows the choice of limiting how many servers will be tried, which milter-sender limits to only the primary MX hosts. In the case of only one primary MX, milter-sender does make at least two (2) attempts to connect. If there are multiple primary MX hosts (such as with aol.com or hotmail.com) milter-sender will attempt to contact the first three primary MX hosts (see MxCallBackMaxAttempts option).

    The final SHOULD clause is a strong recommendation, but is still optional. It says milter-sender should try at least two different servers when provided, which it does.

    There are legitimate sites that choose to publish in their DNS records to a primary MX with a public IP address that is never reachable from the public Internet. While this might solve a local configuration issue, I claim that this practice is not RFC conformant since a service announced through the DNS should be available the majority of the time from the public Internet. This practice forces all SMTP servers to make at least two attempts to connect, once for the primary that never answers, then to a secondary. milter-sender will check the secondary MX.

  • When using this milter, you should place the local host and your local network in the access database. For example:

    Connect:127.0.0.1		OK
    Connect:192.168.1		OK
    

    You might want to review the following third-party recommended IP white list for servers known to have problems with grey-listing servers. It is updated from time to time.

    Also some mail servers like gmail.com use outbound pools of SMTP servers that share a common mail queue, such that the IP address changes with each delivery attempt. Consider using either white listing:

    Connection:gmail.com		OK
    

    Or specify a different grey-listing key:

    MxAcceptsAll=mail,rcpt
    
  • I would like to express my thanks to Daniel Krones, Jeff Powell, and Benji Spencer for all their invaluable help, feedback, and patience during development and testing. Ken Dean for a SunOS account to build/port on. Also Volker Stolz for further insights into FreeBSD. And Derek Balling for his support at http://www.milter.org/.

User Feeback

Jeff Powell
I just wanted to say thank you for the milter-sender program. It appears to be working fine. It brought tears to my eyes to see it in action (well, almost!). This is just what I needed.
Ralf Fischer
Do you have an amazon whishlist or something like that? It's really a pleasure to watch a tail -f /var/log/mail | grep "milter-sender" :-)
Daniel Krones
I have been running milter-sender on RH Linux 7.1 for the past 7-8 months. It has been running virtually trouble free for the entire time. It has been catching an average of 350 spams per day and I am really happy about this. A terrific program. Thank you!
Philipp Baer of Germany
I've installed milter-sender about a week ago and by now, the traffic consumed by the mailserver was decreased by at least 50%. It's amazing! Almost every feature I missed in sendmail is now supported by milter-sender. About 70 to 90% of bulk and other unwanted trash emails are rejected. Great done!
Jose Carlos da Silva
First of all, I would like to congratulate you for your great software. milter-sender has became one of the strongest tools in fighting SPAM in our network. It's really great!
Chris from Xymox1
Fun tools. You have some of the most interesting SPAM tools on the internet! RFC Compliance or die I say! Its great !...

License Agreement 1.4

SNERTSOFT IS WILLING TO LICENSE THE SOFTWARE IDENTIFIED ABOVE TO YOU ONLY UPON THE CONDITION THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS LICENSE AGREEMENT. PLEASE READ THE AGREEMENT CAREFULLY. BY DOWNLOADING OR INSTALLING THIS SOFTWARE, YOU ACCEPT THE TERMS OF THE AGREEMENT.

  1. Definitions

    1. ``Package'' means the identified above in source and/or binary form, any other machine readable materials provided (including, but not limited to documentation, sample files, data files), any updates or error corrections, and its derivative works.

    2. ``Private Individual'' means an individual using the Package for personal, private, and non-commercial use only.

    3. ``Organisation'' means a legal entity or an individual that does not qualify as a Private Individual defined above.

    4. ``You'' (or ``Your'') means a Private Individual or Organisation exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 5.1. For legal entities, ``You'' includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition,``control'' means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity.

    5. The Package is an original work written by Anthony C. Howe, hereto referred to as the ``Author''.

  2. License To Use

    1. If You are a Private Individual and so benefited from a reduced purchase price, then You may only compile, install, and use this Package, with or without private modifications, exclusively on a single machine You legally own or rent from a third party, provided You retain this notice, the Author's copyright notice, any and all license control methods (see below), and any links within the Package back to the most current online versions of this License and Disclaimer.

    2. Otherwise if You have paid the full purchase price, then You may compile, install, and use this Package, with or without private modifications, exclusively on machines You legally own or rent from a third party, provided You retain this notice, the Author's copyright notice, any and all license control methods (see below), and any links within the Package back to the most current online versions of this License and Disclaimer.

    3. You may copy, share, distribute, modify, and create derivative works from the user manuals and any related documentation solely for Your internal business purposes, such as in-house documentation, training manuals, or reference material.

  3. Restrictions

    1. Redistribution, including but not limited to books, CDROMS, download mirrors, floppy diskettes, hard disks, hardcopy print outs, online archives, solid state disks, streaming tapes, or other current or future forms of storage or communication media of the Package, with or without modifications, including any and all derivative works such as source patches, binaries, binary patches, or similar is expressly forbidden without prior written permission in hardcopy (letter or fax) signed and dated by the Author.

    2. It is expressly forbidden for You to use the Package, in whole or in part, in any other software, except those designated by the Author.

    3. It is expressly forbidden for You to use the Package to develop any software or other technology having the same primary function as the Package, including but not limited to using the Package in any development or test procedure that seeks to develop like software or other technology, or determine if such software or other technology performs in a similar manner as the Package.

    4. You may not sell, rent, lease, or transfer the Package to third parties without prior written permission in hardcopy (letter or fax) signed and dated by the Author.

  4. Termination

    1. This Agreement is effective until terminated. You may terminate this Agreement at any time by destroying all copies of the Package. This Agreement will terminate immediately without notice from the Author if You fail to comply with any provision of this Agreement. Either party may terminate this Agreement immediately should any portion of the Package become, or in either party's opinion be likely to become, the subject of a claim of infringement of any intellectual property right. Upon Termination, You must destroy all copies of the Package.

  5. Versions Of The License

    1. New Versions. The Author may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number.

    2. Effect of New Versions. Once a version of the Package has been published under a particular version of the License, You may always continue to use it under the terms of that License version. You may also choose to use such Package under the terms of any subsequent version of the License published by the Author. No one other than the Author has the right to modify the terms applicable to the Package created under this License.

Disclaimer

THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO WAY SHALL THE AUTHOR OR LICENSEE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

License Control

The Package may use one or more license control methods including, but not limited to, license key activation, periodic reporting of Package details and IP address of installation to SnertSoft, remote license verification by SnertSoft, or other future technical means. Any information reported to or gathered by SnertSoft shall remain strictly confidential and the private property of SnertSoft. Under no circumstances will SnertSoft resell or release this information to third parties, unless demanded by court order.

Support

Support is only provided for the Author's original Package. Priority support can be purchased. Free support is limited, based on the Author's availability, though enhancements requests and problem reports are welcome. A community mailing list is available; please refer to SnertSoft web site Support area for details.

Gifts

Gifts from the author's Amazon US or Amazon UK wishlist (search by mail address <achowe at snert dot com>) are welcomed for the continued encouragement, moral support, and ego pumping needed to work in foreign non-english speaking lands.

111689 black holes since 24 February 2003