Here is a history of user visible changes to Python milter. 0.8.8 move AddrCache, parse_addr, iniplist, parse_header to Milter package fix plock for missing source and can't change owner/group add sample spfmilter.py milter private_relay config option 0.8.7 Move spf module to pyspf Prevent PTR cache poisoning More lame bounce heuristics Do plain CBV when template is missing 0.8.6 Support CBV timeout Support fail template, headers in templates Create GOSSiP record only when connection will procede to DATA. More SPF lax heuristics Don't require SPF pass for white/black listing mail from trusted relay. Support localpart wildcard for white and black lists. Delay reject of unsigned RCPT for postmaster and abuse only Fix dsn reporting of hard permerror Resolve FIXME for wrap_close in miltermodule.c Add Message-ID to DSNs Use signed Message-ID in delayed reject to blacklist senders Auto-train via blacklist and auto-whitelist Don't check userlist for signed MFROM Accept but skip DSPAM training for whitelisted senders without SPF PASS Report GC stats Support CIDR matching for IP lists Support pysrs sign feature Support localpart specific SPF policy in access file 0.8.5 Simple trusted_forwarder implementation. Fix access_file neutral policy Move Received-SPF header to beginning of headers Supply keyword info for all results in Received-SPF header. Move guessed SPF result to separate header Activate smfi_insheader only when SMFIR_INSHEADER defined Handle NULL MX in spf.py in-process GOSSiP server support (to be extended later) Expire CBV cache and renew auto-whitelist entries 0.8.4 Auto-whitelist recipients of outgoing email. Fix SPF policy via sendmail access map (case insensitive keys). Train screener on whitelisted messages Optional idx parameter to addheader to invoke smfi_insheader Activate progress API when SMFIR_PROGRESS defined 0.8.3 Keep screened honeypot mail, but optionally discard honeypot only mail. spf_accept_fail option for braindead SPF senders (treats fail like softfail) Option to set SPF policy via sendmail access map. Option to supply Sender header from MAIL FROM when missing. Consider SMTP AUTH connections internal. Send DSN for SPF errors corrected by extended processing. Send DSN before SCREENED mail is quarantined Use logging package to keep log lines atomic. 0.8.2 Strict processing limits per SPF RFC Fixed several parsing bugs under RFC Support official IANA SPF record (type99) Honeypot support (requires pydspam-1.1.9) Extended SPF processing results beyond strict RFC limits Support original SES for bounce protection (requires pysrs-0.30.10) Callback exception processing option in milter module Handle corrupt ZIP attachments 0.8.1 Fix zip in zip loop in mime.py Fix HeaderParseError in bms.py header callback Check internal_domains for outgoing mail Fix inconsistent results from send_dsn 0.8.0 Move Milter module to subpackage. DSN support for Three strikes rule and SPF SOFTFAIL Move /*mime*/ and dynip to Milter subpackage Fix SPF unknown mechanism list not cleared Make banned extensions configurable. Option to scan zipfiles for bad extensions. Properly log pydspam exceptions 0.7.3 Experimental release with python2.4 support 0.7.2 Return unknown for invalid ip address in mechanism Recognize dynamic PTR names, and don't count them as authentication. Three strikes and yer out rule. Block softfail by default when no PTR or HELO Return unknown for null mechanism Try best guess on HELO also Expand setreply for common errors make rhsbl.m4 hack available for sendmail.mc 0.7.1 Handle modifying mislabeled multipart messages without an exception Support setbacklog, setmlreply Allow multi-recipient CBV Return TEMPFAIL for SPF softfail 0.7.0 SPF check hello name Move pythonsock to /var/run/milter Move milter.cfg to /etc/mail/pymilter.cfg Check M$ style XML CID records by converting to SPF Recognize, but never match ip6 - until we properly support it. Option to reject when no PTR and no SPF 0.6.9 Reject invalid SRS immediately for benefit of callback verifiers Fix include bug in spf.py Fix check_header bug Fix setup.py to work with python < 2.2.3, thanks to Eric S. Johansson Test driver for SPF test suite. Fix bugs and add features to pass most of test suite. Use best_guess() and get_header() in bms.py for SPF support 0.6.8 Defang message/rfc822 content_type with boundary Support SPF delegation Reject neutral SPF result for selected domains Support SPF default (best_guess) Don't report "spoofed" unless rcpt looks like SRS Check for bounce with multiple rcpts Make dspam see Received-SPF headers Fix sysv init for Redhat 9 and other single ps line per process systems 0.6.7 Fix failure to remove explicit unix socket thanks to Alexander again. Support SRS forgery detection. Detect thread resource starvation in Milter.py. Decode obfuscated subject headers. 0.6.6 Another memory leak plugged by Alexander Kourakos. Support SPF checking: http://spf.pobox.com Hello blacklist RPM compiled for python2.3 and sendmail-8.12 0.6.5 Plug memory leak in wrap_connect thanks to Alexander Kourakos. Support progress notification. Log Received header for trusted relay. Support wildcard user for smart alias. 0.6.4 Exempt entire domains. Tweak SMTP error codes reported. Suppress traceback for Dspam lock timeouts. Dspam internal mail for dspam users. Match hostname for internal connection test, even if no ipaddr. Fix for not saving defang of false positive triggered rejecting it as a virus from self. Size limit for dspam to work around dspam-2.6.5.2 bug. (dspam-2.8 still showstopper buggy for libdspam API.) Whitelist for dspam. Reject list for dspam (REJECT rather than quarantine SCREENed spam for listed domains). Report dspam header changes to sendmail, fix headerChange to handle deleting absent header. dspam feature requires pydspam-1.1.5 0.6.3 dspam screening (with pydspam-1.1.4) Don't write "defang" file for false positive feedback 0.6.2 Work around email package bug in get_filename(). add dspam_exempt list to milter.cfg REJECT messages with missing MIME boundaries (almost always spam) DISCARD messages which any dspam user flags as spam start.sh was calling python instead of python2 on Linux 0.6.1 Work with python-2.2.3 Integrate full dspam application 0.6.0 Use email package in python-2.2.2 0.5.6 Include dspam interface for Bayesian filtering 0.5.5 Allow passing None to setreply and chgheader thanks to George Graf. Experimental IPv6 support thanks to Deron Meranda. Allow removing callbacks by passing None to set_XXX_callback. Recognize internal connections in bms.py. Give users a clue when rejecting banned subjects. 0.5.4 Wiretap redirection feature, smart alias feature, QUARANTINE support 0.5.3 Tweak to run under 2.2 in production 0.5.2 Fix and add to unit test another parsing failure. 0.5.1 Properly handle modifications to rfc822 attachments. Handle encoded rfc822 attachments. 0.5.0 Use config file so users don't have to keep syncing the bms.py script. Keep bms.py marked as %config for a while to avoid wiping out their customizations just yet. 0.4.5 Work with sgmlop package to speed up HTML parsing. Reduce various local hacks to config variables. 0.4.4 Bug fixes for HTML encoding. 0.4.3 Handle quoted-printable HTML attachments. Remove entire attachment when HTML can't be parsed. 0.4.2 Parse HTML attachments to remove <script ...>...</script>. Klez virus uses malformed MIME part separators to prevent the multifile module and other virus scanners from seeing its HTML attachment (which contains Javascript and VBScript). Outhouse happily accepts and executes the malformed attachments, but we still kill the Klez virus because we: Defang attachment when any Content-Type attribute ends with a banned extension - one of the Outhouse bugs exploited by the Klez virus. Outhouse really, really stinks . . . 0.4.1 Bug fix from Jason Erikson for NULL hostaddr in connect callback. 0.4.0 New check_attachments(msg,check) function in mime module allows filtering based on attachment contents. Distribution now includes bms.py, an example milter used in production - including use of the new check_attachments(msg,check) API. Report hostname in WARNING.TXT. More parameter list bug fixes. 0.3.10 Parse quotes in parameter lists to handle embedded ';'. Move test data to subdirectory, write non-junit output to log file in test subdirectory. 0.3.9 Handle non-multipart messages with executable content in sample.py, add more extensions to banned list. 0.3.8 Handle malformed Content-Type in mime.py. Test viruses have been deactivated by deleting most of the viral code. 0.3.7 Put back hint on running sample.py. Add .bat as banned extension. More sample spam filtering logic. 0.3.6 Ran through pychecker-0.8.5. Most systems will name the sendmail user library (used by the milter extension module) 'libsm', but AIX still needs to call it 'libsmutil' because there is a system library called 'libsm'. 0.3.5 Enhanced logging. Fix bug in sample milter where headers were included in body when removing a virus. 0.3.4 Tested distribution on RH6.2 and updated sample.py and docs. Tested with gcc-2.95.2, python-2.1.1, sendmail-8.11.6-2.6.x The RH6.2 spec file to enable libmilter for sendmail-8.11.6 can be obtained from http://www.bmsi.com/linux/sendmail-rhmilter.spec The SRPM can be obtained from http://www.redhat.com 0.3.3 Remove reference to sa_len - not supported by linux. 0.3.2 Rename and add more hints to the sample milter. 0.3.1 Pass a more useful hostaddr to the connect callback. 0.3 Interface now uses a milterContext extension object instead of an index. A PyThreadContext is now created for each milterContext so that "simultaneously" processing multiple messages at once (as often happens on a busy server) actually works. Many milter methods are now object methods of the milterContext extension object. No compatibility API is provided for this change due to the limited user base at this stage. The setname method has been removed, and the name is now passed to register. A simple class to provide an OO wrapper to the milter API is provided. A simple class to parse multipart mime messages into parts and replace selected parts is provided. The sample filter will eventually use the mimelib package instead, but mimelib currently requires reading the entire message into memory. A sample filter that replaces attachments with naughty extensions with a warning message is provided.