New webpage design based on ht2html.
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
+157
@@ -0,0 +1,157 @@
|
||||
<h2> Recent Changes </h2>
|
||||
|
||||
Python milter has been moved to
|
||||
<a href="http://sourceforge.net/projects/pymilter/">pymilter Sourceforge
|
||||
project</a> for development and release downloads.
|
||||
|
||||
<h3> New website design </h3>
|
||||
|
||||
Hey, I'm no artist, so I just used the
|
||||
<a href="http://ht2html.sourceforge.net/"ht2html</a> package
|
||||
by <a href="http://barry.wooz.org/">Barry Warsaw</a>. The mascot
|
||||
is by <a href="http://alphard.ethz.ch/hafner/lebl.htm">Christian Hafner</a>,
|
||||
or maybe his wife. I chose Maxwell's daemon because it tirelessly
|
||||
and invisibly sorts molecules, just as milters sort mail.
|
||||
Cristian has also provided a fun
|
||||
<a href="http://alphard.ethz.ch/hafner/PPS/PPS2002/Maxwell/simulation.htm">
|
||||
simulation</a> that lets you try your hand at sorting molecules.
|
||||
|
||||
<h3> 0.8.4 </h3>
|
||||
|
||||
Release 0.8.4 makes configuring SPF policy via access.db actually work.
|
||||
The honeypot idea is enhanced by auto-whitelisting recipients of
|
||||
email sent from selected domains. Whitelisted messages are then used
|
||||
to train the honeypot. This makes the honeypot screener entirely self
|
||||
training. The smfi_progress() API is now automatically supported when present.
|
||||
An optional idx parameter to milter.addheader() invokes smfi_insheader().
|
||||
|
||||
<h3> 0.8.3 </h3>
|
||||
|
||||
Release 0.8.3 uses the standard logging module, and supports configuring
|
||||
more detailed SPF policy via the sendmail access map. SMTP AUTH connections
|
||||
are considered INTERNAL. Preventing forgery between internal domains is
|
||||
just a matter of specifying the user-domain map - I'll define something
|
||||
for the next version. We now send DSNs when mail is quarantined (rejecting
|
||||
if DSN fails) and for SPF syntax errors (PermError). There is an
|
||||
experimental option to add a Sender header when it is missing and the From
|
||||
domain doesn't match the MAIL FROM domain. Next release, we may start
|
||||
renaming and replacing an existing Sender header when neither it nor the
|
||||
From domain matches MAIL FROM. Since bogus MAIL FROMs are rejected
|
||||
(to varying degrees depending on the configured SPF policy), and
|
||||
both Sender and From and displayed by default in many email clients,
|
||||
this provides some phishing protection without rejecting mail based
|
||||
on headers.
|
||||
|
||||
<h3> 0.8.2 </h3>
|
||||
|
||||
Release 0.8.2 has changes to <a href="http://openspf.net">SPF</a> to bring it
|
||||
in line with the newly official RFC. It adds
|
||||
<a href="http://ses.codeshare.ca/">SES</a>
|
||||
support (the original SES without body hash) for pysrs-0.30.10, and honeypot
|
||||
support for pydspam-1.1.9. There is a new method in the base milter module.
|
||||
milter.set_exception_policy(i) lets you choose a policy of CONTINUE, REJECT, or
|
||||
TEMPFAIL (default) for untrapped exceptions encountered in a milter callback.
|
||||
|
||||
<h3> 0.8.0 </h3>
|
||||
|
||||
Release 0.8.0 is the first <a href="http://sourceforge.net/">Sourceforge</a>
|
||||
release. It supports Python-2.4, and provides an option to accept mail
|
||||
that gets an SPF softfail or fails the 3 strikes rule, provided the
|
||||
alleged sender accepts a DSN explaining the problem. Python-2.3 is
|
||||
no longer supported by the reworked mime.py module, although API changes
|
||||
could be backported. There are too many incompatible changes to the
|
||||
python email package.
|
||||
|
||||
<h3> Older Releases </h3>
|
||||
|
||||
Release 0.7.2 tightens the authentication screws with a "3 strikes and
|
||||
you're out" policy. A sender must have a valid PTR, HELO, or SPF record
|
||||
to send email. Specific senders can be whitelisted using the
|
||||
"delegate" option in the spf configuration section by adding a
|
||||
default SPF record for them. The PTR and HELO are required
|
||||
by RFC anyway, so this is not an unreasonable requirement.
|
||||
There is now a coherent policy for an SPF softfail result. A softfail
|
||||
is accepted if there is a valid PTR or HELO, or if the domain
|
||||
is listed in the "accept_softfail" option of the spf configuration section.
|
||||
A neutral result is accepted by default if there is a valid PTR or
|
||||
HELO, (and the SPF record was not guessed), unless the domain is listed in the
|
||||
"reject_neutral" option. Common forms of PTR records for dynamic IPs are
|
||||
recognized, and do not count as a valid PTR. This does not prevent anyone
|
||||
from sending mail from a dynamic IP - they just need to configure a
|
||||
valid HELO name or publish an SPF record.
|
||||
<p>
|
||||
As SPF adoption continues to rise, forged spam is not getting through. So
|
||||
spammers are publishing their SPF records as predicted. The 0.7.2 RPM
|
||||
now provides the <code>rhsbl</code> sendmail hack so that spammer domains
|
||||
can be blacklisted. With the RPM installed, add a line like the following
|
||||
to your <code>sendmail.mc</code>.
|
||||
<pre>
|
||||
HACK(rhsbl,`blackholes.example.com',"550 Rejected: " $&{RHS} " has been spamming our customers.")dnl
|
||||
</pre>
|
||||
<p>
|
||||
Of course, spammers are now starting to register
|
||||
throwaway domains. The next thing we need is a custom DNS server,
|
||||
in Python, that
|
||||
can recognize patterns. For instance, one spammer registers ded304.com,
|
||||
ded305.com, ded306.com, etc. We also need the custom DNS server to
|
||||
let SPF classic clients check SES (which will be part of pysrs).
|
||||
The <a href="http://twistedmatrix.com/products/twisted">Twisted Python</a>
|
||||
framework provides a custom DNS server - but I
|
||||
would like a smaller implementation for our use.
|
||||
<p>
|
||||
The RPM for release 0.7.0 moves the config file and socket locations to
|
||||
/etc/mail and /var/run/milter respectively. We now parse Microsoft CID records
|
||||
- but only hotmail.com uses them. They seem to have applied for a patent on
|
||||
the brilliant idea of examining the mail headers to see who the message is
|
||||
from. We aren't doing that here, so not to worry - but I am not a lawyer, so
|
||||
if you are worried, change spf.py around line 626 to return None instead of
|
||||
calling CIDParser(). There is a new option to reject mail with no PTR
|
||||
and no SPF.
|
||||
<p>
|
||||
Microsoft is pushing an anti-opensource license for their pending patent
|
||||
along with their sender-ID proposal before the IETF.
|
||||
It is royalty free - but requires anyone distributing a binary they've
|
||||
compiled from source to sign a license agreement. The Apache Software
|
||||
Foundation <a
|
||||
href="http://www.apache.org/foundation/docs/sender-id-position.html"> explains
|
||||
the problem with sender-ID</a>, and Debian <a
|
||||
href="http://www.debian.org/News/2004/20040904">concurs</a>. Since
|
||||
the <a href="http://download.microsoft.com/download/4/3/9/439b024b-09fd-44ee-8ff0-10e834004c36/senderid_FAQ.PDF">Microsoft license</a> is
|
||||
<a href="http://www.circleid.com/article/732_0_1_0_C/">incompatible with free
|
||||
software in general</a> and the <a
|
||||
href="http://www.imc.org/ietf-mxcomp/mail-archive/msg03678.html">GPL in
|
||||
particular</a>, Python milter will not be able to implement sender-ID in its
|
||||
current form. This was, no doubt, Microsoft's intent all along.
|
||||
<p>
|
||||
Sender-ID attempts to do for RFC2822 headers what SPF does for RFC2821 headers.
|
||||
Unlike SPF, it has never been tried, and is encumbered by a stupid patent. I
|
||||
recommend ignoring it and continuing to implement and improve SPF until a
|
||||
working and unencumbered proposal for RFC2822 headers surfaces.
|
||||
|
||||
<p>
|
||||
<a href="http://openspf.com">
|
||||
<img src="SPF.gif" align=left alt="SPF logo"></a>
|
||||
Release 0.6.6 adds support for <a href="http://openspf.com/">SPF</a>,
|
||||
a protocol to prevent forging of the envelope from address.
|
||||
SPF support requires <a href="http://pydns.sourceforge.net/">pydns</a>.
|
||||
The included spf.py module is an updated version of the original 1.6
|
||||
version at <a href="http://www.wayforward.net/spf/">wayforward.net</a>.
|
||||
The updated version tracks the draft RFC and test suite.
|
||||
<p>
|
||||
The FAQ addresses <a href="faq.html#spf">how to get started with SPF</a>.
|
||||
<p>
|
||||
Release 0.6.1 adds a full milter based dspam application.
|
||||
<p>
|
||||
I have selected the <a href="http://www.nuclearelephant.com/projects/dspam/">
|
||||
dspam bayes filter project</a> and <a href="dspam.html">
|
||||
packaged it for python</a>.
|
||||
Release 0.6.0 offers a simple application of dspam I call "header triage",
|
||||
which rejects messages with spammy headers.
|
||||
To use header triage, you must have <a href="dspam.html">DSPAM</a> installed,
|
||||
and select a dictionary that is well moderated by someone who gets
|
||||
lots of spam. That dictionary can be used to block spam that is
|
||||
obvious from the headers (e.g. X-Mailer and Subject) before it ties
|
||||
up any more resources. I have yet to see any false positives from this
|
||||
approach (check the milter log), but if there are, the sender will
|
||||
get a REJECT with the message "Your message looks spammy."
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<h1> CREDITS </h1>
|
||||
|
||||
<a href="mailto:Jim Niemira <urmane@urmane.org>">Jim Niemira</a>
|
||||
wrote the original C module and some quick
|
||||
and dirty python to use it.
|
||||
<a href="mailto:Stuart Gathman <stuart@bmsi.com>">Stuart D. Gathman</a>
|
||||
took that kludge and added threading and context objects to it, wrote a proper
|
||||
OO wrapper (Milter.py) that handles attachments, did lots of testing, packaged
|
||||
it with distutils, and generally transformed it from a quick hack to a
|
||||
real, usable Python extension.
|
||||
|
||||
<h2>Other contributors (in random order):</h2>
|
||||
|
||||
<dl>
|
||||
<dt> <a href="http://alphard.ethz.ch/hafner/lebl.htm">Christian Hafner</a>
|
||||
<dd>for the pymilter mascot image of
|
||||
<a href="http://maxwelld.netfirms.com/">
|
||||
Maxwell's daemon</a>
|
||||
<dt>Dave MacQuigg
|
||||
<dd>for noticing that smfi_insheader wasn't supported, and creating
|
||||
a template to help first time pymilter users create their own milter.
|
||||
<dt>Terence Way
|
||||
<dd>for providing a Python port of SPF
|
||||
<dt>Scott Kitterman
|
||||
<dd>for doing lots of testing and debugging of SPF against draft standard,
|
||||
and for putting up a web page that validates SPF records using spf.py
|
||||
<dt>Alexander Kourakos
|
||||
<dd>for plugging several memory leaks
|
||||
<dt>George Graf at Vienna University of Economics and Business Administration
|
||||
<dd>for handling None passed to setreply and chgheader.
|
||||
<dt>Deron Meranda
|
||||
<dd>for IPv6 patches
|
||||
<dt>Jason Erikson
|
||||
<dd>for handling NULL hostaddr in connect callback.
|
||||
<dt>John Draper
|
||||
<dd>for porting Python milter to OpenBSD, and starting to work on tutorials
|
||||
then pointing out that it would be easier to just write the MTA in Python.
|
||||
<dt>Eric S. Johansson
|
||||
<dd>for helpful design discussions while working on camram
|
||||
<dt>Alex Savguira
|
||||
<dd>for finding bugs with international headers and
|
||||
suggesting the scan_zip option.
|
||||
<dt><a href="http://www.bmsi.com">Business Management Systems</a>
|
||||
<dd>for hosting the website, and providing paying clients who need milter
|
||||
service so I can work on it as part of my day job.
|
||||
</dl>
|
||||
|
||||
If I have left anybody out, send me a reminder:
|
||||
<a href="mailto:Stuart Gathman <stuart@bmsi.com>">stuart@bmsi.com</a>
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Python Milter FAQ</title>
|
||||
</head><body>
|
||||
|
||||
<h1> Python Milter <a name=faq>FAQ</a> </h1>
|
||||
|
||||
<ol>
|
||||
<h3> Compiling Python Milter </h3>
|
||||
<li> Q. I have installed sendmail from source, but Python milter won't
|
||||
compile.
|
||||
<p> A. Even though libmilter is officially supported in sendmail-8.12,
|
||||
you need to build and install it in separate steps. Take a look
|
||||
at the <a href="/aix/sendmail12.spec">RPM spec file</a> for sendmail-8.12.
|
||||
The %prep section shows you how to create
|
||||
a site.config.m4 that enables MILTER. The %build section shows you how
|
||||
to build libmilter in a separate invocation of make. The %install section
|
||||
shows you how to install libmilter with a separate invocation of make.
|
||||
<p>
|
||||
|
||||
<li> Q. Why is mfapi.h not found when I try to compile Python milter on
|
||||
RedHat 7.2?
|
||||
<p> A. RedHat forgot to include the header in the RPM. See the
|
||||
<a href="requirements.html#rh72">RedHat 7.2 requirements</a>.
|
||||
<p>
|
||||
|
||||
<h3> Running Python Milter </h3>
|
||||
|
||||
<li> Q. The sample.py milter prints a message, then just sits there.
|
||||
<pre>
|
||||
To use this with sendmail, add the following to sendmail.cf:
|
||||
|
||||
O InputMailFilters=pythonfilter
|
||||
Xpythonfilter, S=local:inet:1030@localhost
|
||||
|
||||
See the sendmail README for libmilter.
|
||||
sample milter startup
|
||||
</pre>
|
||||
<p> A. You need to tell sendmail to connect to your milter. The
|
||||
sample milter tells you what to add to your sendmail.cf to tell
|
||||
sendmail to use the milter. You can also add an INPUT_MAIL_FILTER
|
||||
macro to your sendmail.mc file and rebuild sendmail.cf - see the sendmail
|
||||
README for milters.
|
||||
<p>
|
||||
|
||||
<li> Q. I've configured sendmail properly, but still nothing happens
|
||||
when I send myself mail!
|
||||
<p> A. Sendmail only milters SMTP mail. Local mail is not miltered.
|
||||
You can pipe a raw message through sendmail to test your milter:
|
||||
<pre>
|
||||
$ cat rawtextmsg | sendmail myname@my.full.domain
|
||||
</pre>
|
||||
Now check your milter log.
|
||||
<p>
|
||||
|
||||
<li> Q. Why do I get this ImportError exception?
|
||||
<pre>
|
||||
File "mime.py", line 370, in ?
|
||||
from sgmllib import declstringlit, declname
|
||||
ImportError: cannot import name declstringlit
|
||||
</pre>
|
||||
<p> A. <code>declstringlit</code> is not provided by sgmllib in all versions
|
||||
of python. For instance, python-2.2 does not have it. Upgrade to
|
||||
milter-0.4.5 or later to remove this dependency.
|
||||
<p>
|
||||
|
||||
<li> Q. Why do I get <code>milter.error: cannot add recipient</code>?
|
||||
<pre>
|
||||
</pre>
|
||||
<p> A. You must tell libmilter how you might mutate the message with
|
||||
<code>set_flags()</code> before calling <code>runmilter()</code>. For
|
||||
instance, <code>Milter.set_flags(Milter.ADDRCPT)</code>. You must add together
|
||||
all of <code>ADDHDRS, CHGBODY, ADDRCPT, DELRCPT, CHGHDRS</code> that apply.
|
||||
<p> NOTE - recent versions default flags to enabling all features. You
|
||||
must now call <code>set_flags()</code> if you wish to disable features for
|
||||
efficiency.
|
||||
<p>
|
||||
|
||||
<li> Q. Why does sendmail sometimes print something like:
|
||||
"...write(D) returned -1, expected 5: Broken pipe"
|
||||
in the sendmail log?
|
||||
<p> A. Libmilter expects "rcpt to" shortly after getting "mail from".
|
||||
"Shortly" is defined by the timeout parameter you passed to
|
||||
<code>Milter.runmilter()
|
||||
</code> or <code>milter.settimeout()</code>. If the timeout is 10 seconds,
|
||||
and looking up the first recipient in DNS takes more than
|
||||
10 seconds, libmilter will give up and break the connection.
|
||||
<code>Milter.runmilter()</code> defaulted to 10 seconds in 0.3.4. In 0.3.5
|
||||
it will keep the libmilter default of 2 hours.
|
||||
<p>
|
||||
|
||||
<li> Q. Why does milter block messages with big5 encoding? What if I
|
||||
want to receive them?
|
||||
<p> A. sample.py is a sample. It is supposed to be easily modified
|
||||
for your specific needs. We will of course continue to move generic
|
||||
code out of the sample as the project evolves. Think of sample.py as
|
||||
an active config file.
|
||||
<p>
|
||||
If you are running bms.py, then the block_chinese option in
|
||||
<code>/etc/mail/pymilter.cfg</code> controls this feature.
|
||||
<p>
|
||||
|
||||
<li> Q. Why does sendmail coredump with milters on OpenBSD?
|
||||
<p> A. Sendmail has a problem with unix sockets on old versions of OpenBSD.
|
||||
Use an internet domain socket instead. For example, in
|
||||
<code>sendmail.cf</code> use
|
||||
<pre>
|
||||
Xpythonfilter, S=inet:1234@localhost
|
||||
</pre>
|
||||
and change sample.py accordingly.
|
||||
<p> OpenBSD users report that this problem has been fixed.
|
||||
<p>
|
||||
|
||||
<li> Q. How can I change the bounce message for an invalid recipient?
|
||||
I can only change the recipient in the eom callback, but the eom callback
|
||||
is never called when the recipient is invalid!
|
||||
<p> A. Configure sendmail to use virtusertable, and send all unknown
|
||||
addresses to /dev/null. For example,
|
||||
<h4>/etc/mail/virtusertable</h4>
|
||||
<pre>
|
||||
@mycorp.com dev-null
|
||||
dan@mycorp.com dan
|
||||
sally@mycorp.com sally
|
||||
</pre>
|
||||
<h4>/etc/aliases</h4>
|
||||
<pre>
|
||||
dev-null: /dev/null
|
||||
</pre>
|
||||
Now your milter will get to the eom callback, and can change the
|
||||
envelope recipient at will. Thanks to Dredd at
|
||||
<a href=http://www.milter.org/>milter.org</a> for this solution.
|
||||
<p>
|
||||
|
||||
<li> Q. I am having trouble with the setreply method. It always outputs
|
||||
"milter.error: cannot set reply".
|
||||
<p> A. Check the sendmail log for errors. If sendmail is getting
|
||||
milter timeouts, then your milter is taking too long and sendmail gave
|
||||
up waiting. You can adjust the timeouts in your sendmail config. Here
|
||||
is a milter declaration for sendmail.cf with all timeouts specified:
|
||||
<pre>
|
||||
Xpythonfilter, S=local:/var/log/milter/pythonsock, F=T, T=C:5m;S:20s;R:60s;E:5m
|
||||
</pre>
|
||||
<li> Q. There is a Python traceback in the log file! What happened to
|
||||
my email?
|
||||
<p> A. When the milter fails with an untrapped exception, a TEMPFAIL
|
||||
result (451) is returned to the sender. The sender will then retry every
|
||||
hour or so for several days. Hopefully, someone will notice the
|
||||
traceback, and workaround or fix the problem.
|
||||
|
||||
<li> Q. I read some notes such as "Check valid domains allowed by internal
|
||||
senders to detect PCs infected with spam trojans." but could not
|
||||
understand the idea. Could you clarify the content ?
|
||||
|
||||
<p> A. The <code>internal_domains</code> configuration specifies which
|
||||
MAIL FROM domains are used by internal connections. If an internal
|
||||
PC tries to use some other domain, it is assumed to be a "Zombie".
|
||||
<p>
|
||||
Here is a sample log line:
|
||||
<pre>
|
||||
2005Jun22 12:01:04 [12430] REJECT: zombie PC at 192.168.100.171 sending MAIL FROM debby@fedex.com
|
||||
</pre>
|
||||
No, fedex.com does not use pymilter, and there is no one named debby at my
|
||||
client. But the idiot using the PC at 192.168.100.171 has downloaded and
|
||||
installed some stupid weatherbar/hotbar/aquariumscreensaver that is actually a
|
||||
spam bot.
|
||||
<p>
|
||||
The <code>internal_domains</code> option is simplistic, it assumes all
|
||||
valid senders of the domains are internal. SPF provides a much more general
|
||||
check of IP and MAIL FROM for external email. Pymilter should soon
|
||||
have a local policy feature for more general checking of internal mail.
|
||||
|
||||
<h3> Using SPF </h3>
|
||||
|
||||
<a name="spf">
|
||||
<li> Q. So how do I use the SPF support? The sample.py milter doesn't seem
|
||||
to use it.
|
||||
<p> A. The bms.py milter supports spf. The RedHat RPMs will set almost
|
||||
everything up for you. For other systems:
|
||||
<ol type=i>
|
||||
<li> Arrange to run bms.py in the background (as a service perhaps) and
|
||||
redirect output and errors to a logfile. For instance, on AIX you'll want
|
||||
to use SRC (System Resource Controller).
|
||||
<li> Copy pymilter.cfg to the /etc/mail or the directory you run bms.py in,
|
||||
and edit it. The comments should explain the options.
|
||||
<li> Start bms.py in the background as arranged.
|
||||
<li> Add Xpythonfilter to sendmail.cf or add an INPUT_MAIL_FILTER to
|
||||
sendmail.mc. Regen sendmail.cf if you use sendmail.mc and restart
|
||||
sendmail.
|
||||
<li> Arrange to rotate log files and remove old defang files in
|
||||
<code>tempdir</code>. The RedHat RPM uses <code>logrotate</code> for
|
||||
logfiles and a simple cron script using <code>find</code> to clean
|
||||
<code>tempdir</code>.
|
||||
</ol>
|
||||
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,76 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.1 Final//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Python Milter Log Documentation</title>
|
||||
<style>
|
||||
DT { font-weight: bolder; padding-top: 1em }
|
||||
</style>
|
||||
</head><body>
|
||||
|
||||
<h1> Milter Log Documentation </h1>
|
||||
|
||||
The milter log has a variety of "tags" in it that indicate what it did.
|
||||
|
||||
<dl>
|
||||
<dt> DSPAM: honeypot SCREENED
|
||||
<dd> message was quarantined to the honeypot quarantine
|
||||
|
||||
<dt> REJECT: hello SPF: fail 550 access denied
|
||||
<dt> REJECT: hello SPF: softfail 550 domain in transition
|
||||
<dt> REJECT: hello SPF: neutral 550 access neither permitted nor denied
|
||||
<dd> message was rejected because there was an SPF policy for the
|
||||
HELO name, and it did not pass.
|
||||
|
||||
<dt> CBV: sender-17-44662668-643@bluepenmagic.com
|
||||
<dd> we performed a call back verification
|
||||
|
||||
<dt> dspam
|
||||
<dd> dspam identifier was added to the message
|
||||
|
||||
<dt> REJECT: spam from self: jsconnor.com
|
||||
<dd> message was reject because HELO was us (jsconnor.com)
|
||||
|
||||
<dt> INNOC: richh
|
||||
<dd> message was used to update richh's dspam dictionary
|
||||
|
||||
<dt> HONEYPOT: michaelb@jsconnor.com
|
||||
<dd> message was sent to a honeypot address (michaelb@jsconnor.com), the
|
||||
message was added to the honeypot dspam dictionary as spam
|
||||
|
||||
<dt> REJECT: numeric hello name: 63.217.19.146
|
||||
<dd> message was rejected because helo name was invalid (numeric)
|
||||
|
||||
<dt> eom
|
||||
<dd> message was successfully received
|
||||
|
||||
<dt> TEMPFAIL: CBV: 450 No MX servers available
|
||||
<dd> we tried to do a call back verification but could not look up
|
||||
MX record, we told the sender to try again later
|
||||
|
||||
<dt> CBV: info@emailpizzahut.com (cached)
|
||||
<dd> call back verification was needed, we had already done it recently
|
||||
|
||||
<dt> abort after 0 body chars
|
||||
<dd> sender hung up on us
|
||||
|
||||
<dt> REJECT: SPF fail 550 SPF fail: see
|
||||
http://openspf.com/why.html?sender=m.hendersonxk@163.net&ip=213.47.161.100
|
||||
<dd> message was reject because its sender's spf policy said to
|
||||
|
||||
<dt> REJECT: Subject: Cialis - No prescription needed!
|
||||
<dd> message was rejected because its subject contained a bad expression
|
||||
|
||||
<dt> DSPAM: tonyc tonyc@jsconnor.com
|
||||
<dd> message was sent to tonyc@jsconnor.com and it was identified as spam
|
||||
and placed in the tonyc dspam quarantine
|
||||
|
||||
<dt> REJECT: CBV: 550 calvinalstonis@ix.netcom.com...User unknown
|
||||
<dt> REJECT: CBV: 553 sorry, that domain isn't in my list
|
||||
<dt> REJECT: CBV: 554 delivery error: dd This user doesn't have an account
|
||||
<dd> message was rejected because call back verification gave us a fatal
|
||||
error
|
||||
</dl>
|
||||
|
||||
Please add more tags to this list if you know of any. Thanks.
|
||||
</body>
|
||||
</html>
|
||||
+302
@@ -0,0 +1,302 @@
|
||||
|
||||
<P ALIGN="CENTER"><A HREF="http://www.anybrowser.org/campaign/">
|
||||
<IMG SRC="http://bmsi.com/art/brain1.gif"
|
||||
ALT="Viewable With Any Browser" BORDER="0"></A>
|
||||
|
||||
<img src="http://bmsi.com/art/banner_4.gif" width="468" height="60" border="0"
|
||||
usemap="#banner_4" alt="Your vote?">
|
||||
<map name="banner_4">
|
||||
<area shape="rect" coords="330,25,426,59"
|
||||
href="http://education-survey.org/" alt="I Disagree">
|
||||
<area shape="rect" coords="234,28,304,57" href="http://www.honestEd.com/" alt="I Agree">
|
||||
</map>
|
||||
</P>
|
||||
|
||||
<img src="Maxwells.gif" alt="Maxwell's Daemon: pymilter mascot" align=left>
|
||||
<h1 align=center>Sendmail Milters in Python</h1>
|
||||
<h4 align=center>by <a href="mailto:%75%72%6D%61%6E%65%40%6E%65%75%72%61l%61%63%63%65%73%73%2E%63%6F%6D">Jim Niemira</a>
|
||||
and <a href="mailto:%73%74%75%61%72%74%40%62%6D%73%69%2E%63%6F%6D">
|
||||
Stuart D. Gathman</a><br>
|
||||
This web page is written by Stuart D. Gathman<br>and<br>sponsored by
|
||||
<a href="http://www.bmsi.com">Business Management Systems, Inc.</a> <br>
|
||||
Last updated Oct 25, 2005</h4>
|
||||
|
||||
See the <a href="faq.html">FAQ</a> | <a href="http://sourceforge.net/project/showfiles.php?group_id=139894">Download now</a> |
|
||||
<a href="http://bmsi.com/mailman/listinfo/pymilter">Subscribe to mailing list</a> |
|
||||
<a href="#overview">Overview</a> |
|
||||
<a href="/python/dspam.html">pydspam</a> |
|
||||
<a href="/libdspam/dspam.html">libdspam</a>
|
||||
<p>
|
||||
<a href="//www.python.org">
|
||||
<img src="python55.gif" align=left alt="A Python"></a>
|
||||
<a href="//www.sendmail.org/">Sendmail</a> introduced a
|
||||
<a href="http://www.milter.org/milter_api/api.html"> new API</a> beginning with version 8.10 -
|
||||
libmilter. The milter module for <a href="//www.python.org">Python</a>
|
||||
provides a python interface to libmilter that exploits all its features.
|
||||
<p>
|
||||
Sendmail 8.12 officially releases libmilter.
|
||||
Version 8.12 seems to be more robust, and includes new privilege
|
||||
separation features to enhance security. Even better, sendmail 8.13
|
||||
supports socket maps, which makes <a href="pysrs.html">pysrs</a> much more
|
||||
efficient and secure. I recommend upgrading.
|
||||
|
||||
<h3><a name=overview>Overview</a></h3>
|
||||
|
||||
This package provides a robust toolkit for Python <a
|
||||
href="#milter">milters</a>, and the beginnings of a general purpose mail
|
||||
filtering system written in Python.
|
||||
<p>
|
||||
At the lowest level, the 'milter' module provides a thin wrapper around the
|
||||
<a href="http://www.milter.org/milter_api/api.html">
|
||||
sendmail libmilter API</a>. This API lets you register callbacks for
|
||||
a number of events in the
|
||||
<a href="http://www.cs.concordia.ca/~group/fig/public/email/relay/milter+ruleset-checks.html">process of sendmail receiving a message via SMTP</a>.
|
||||
These events include the initial connection from a MTA,
|
||||
the envelope sender and recipients, the top level mail headers, and
|
||||
the message body. There are options to mangle all of these components
|
||||
of the message as it passes through the milter.
|
||||
<p>
|
||||
At the next level, the 'Milter' module (note the case difference) provides a
|
||||
Python friendly object oriented wrapper for the low level API. To use the
|
||||
Milter module, an application registers a 'factory' to create an object
|
||||
for each connection from a MTA to sendmail. These connection objects
|
||||
must provide methods corresponding to the libmilter callback events.
|
||||
<p>
|
||||
Each event method returns a code to tell sendmail whether to proceed
|
||||
with processing the message. This is a big advantage of milters over
|
||||
other mail filtering systems. Unwanted mail can be stopped in its
|
||||
tracks at the earliest possible point.
|
||||
<p>
|
||||
The Milter.Milter class provides default implementations for event
|
||||
methods that
|
||||
do nothing, and also provides wrappers for the libmilter methods to mutate
|
||||
the message.
|
||||
<p>
|
||||
The 'spf' module provides an implementation of <a href="http://openspf.com">
|
||||
SPF</a> useful for detecting email forgery.
|
||||
<p>
|
||||
The 'mime' module provides a wrapper for the Python email package that
|
||||
fixes some bugs, and simplifies modifying selected parts of a MIME message.
|
||||
<p>
|
||||
Finally, the bms.py application is both a sample of how to use the
|
||||
Milter and spf modules, and the beginnings of a general purpose SPAM filtering,
|
||||
wiretapping, SPF checking, and Win32 virus protecting milter. It can
|
||||
make use of the <a href="pysrs.html">pysrs</a> package when available for
|
||||
SRS/SES checking and the <a href="dspam.html">pydspam</a> package for Bayesian
|
||||
content filtering. SPF checking
|
||||
requires <a href="http://pydns.sourceforge.net/">
|
||||
pydns</a>. Configuration documentation is currently included as comments
|
||||
in the <a href="milter.cfg">sample config file</a> for the bms.py milter.
|
||||
See also the <a href="HOWTO">HOWTO</a> and <a href="logmsgs.html">
|
||||
Milter Log Message Tags</a>.
|
||||
<p>
|
||||
Python milter is under GPL. The authors can probably be convinced to
|
||||
change this to LGPL if needed.
|
||||
|
||||
<h3>What is a <a name="milter">milter</a>?</h3>
|
||||
|
||||
Milters can run on the same machine as sendmail, or another machine. The
|
||||
milter can even run with a different operating system or processor than
|
||||
sendmail.
|
||||
Sendmail talks to the milter via a local or internet socket.
|
||||
Sendmail keeps the
|
||||
milter informed of events as it processes a mail connection. At any
|
||||
point, the milter can cut the conversation short by telling sendmail
|
||||
to ACCEPT, REJECT, or DISCARD the message. After receiving a complete
|
||||
message from sendmail, the milter can again REJECT or DISCARD it, but it
|
||||
can also ACCEPT it with changes to the headers or body.
|
||||
|
||||
<h3> What can you do with a milter? </h3>
|
||||
|
||||
<menu>
|
||||
<li> A milter can DISCARD or REJECT spam based based on algorithms scripted
|
||||
in python rather than sendmail's cryptic "cf" language.
|
||||
<li> A milter can alter or remove attachments from mail that are poisonous to
|
||||
Windows.
|
||||
<li> A milter can scan for viruses and clean them when detected.
|
||||
<li> A milter scans outgoing as well as incoming mail.
|
||||
<li> A milter can add and delete recipients to forward or secretly
|
||||
copy mail.
|
||||
<li> For more ideas, check the <a href="//www.milter.org">Milter Web Page</a>.
|
||||
</menu>
|
||||
|
||||
<a href="http://www.milter.org/milter_api/api.html">
|
||||
Documentation</a> for the C API is provided with sendmail. Miltermodule
|
||||
provides a thin python wrapper for the C API. Milter.py provides a simple
|
||||
OO wrapper on top of that.
|
||||
<p>
|
||||
The Python milter package includes a sample milter that replaces dangerous
|
||||
attachments with a warning message, discards mail addressed to
|
||||
MAILER-DAEMON, and demonstrates several SPAM abatement strategies.
|
||||
The MimeMessage class to do this used to be based on the
|
||||
<code>mimetools</code> and <code>multifile</code> standard python packages.
|
||||
As of milter version 0.6.0, it is based on the email standard
|
||||
python packages, which were derived from the
|
||||
<a href="http://sourceforge.net/projects/mimelib">mimelib</a> project.
|
||||
The MimeMessage class patches several bugs in the email package,
|
||||
and provides some backward compatibility.
|
||||
|
||||
<p>
|
||||
The "defang" function of the sample milter was inspired by
|
||||
<a href="http://www.roaringpenguin.com/mimedefang/">MIMEDefang</a>,
|
||||
a Perl milter with flexible attachment processing options. The latest
|
||||
version of MIMEDefang uses an apache style process pool to avoid reloading
|
||||
the Perl interpreter for each message. This makes it fast enough for
|
||||
production without using Perl threading.
|
||||
<p>
|
||||
<a href="http://sourceforge.net/projects/mailchecker">mailchecker</a> is
|
||||
a Python project to provide flexible attachment processing for mail. I
|
||||
will be looking at plugging mailchecker into a milter.
|
||||
<p>
|
||||
<a href="http://software.libertine.org/tmda/">TMDA</a> is a Python project
|
||||
to require confirmation the first time someone tries to send to your
|
||||
mailbox. This would be a nice feature to have in a milter.
|
||||
<p>
|
||||
There is also a <a href="http://www.milter.org/">Milter community website</a>
|
||||
where milter software and gory details of the API are discussed.
|
||||
|
||||
<h3> Is a milter written in python efficient? </h3>
|
||||
|
||||
The python milter process is multi-threaded and startup cost is incurred
|
||||
only once. This is much more efficient than some implementations that
|
||||
start a new interpreter for each connection. Testing in a production
|
||||
environment did not use a significant percentage of the CPU. Furthermore,
|
||||
python is easily extended in C for any step requiring expensive CPU
|
||||
processing.
|
||||
<p>
|
||||
For example, the HTML parsing feature to remove scripts from HTML attachments
|
||||
is rather CPU intensive in pure python. Using the C replacement for sgmllib
|
||||
greatly speeds things up.
|
||||
|
||||
<h3> Goals </h3>
|
||||
|
||||
<menu>
|
||||
<li> Implement RRS - a backdoor for non-SRS forwarders. User lists non-SRS
|
||||
forwarder accounts (perhaps in <code>~/.forwarders</code>), and a util
|
||||
provides a special local alias for the user to give to the forwarder.
|
||||
Alias only works for mail from that forwarder. Milter gets forwarder
|
||||
domain from alias and uses it to SPF check forwarder. Requires
|
||||
milter to have read access to <code>~/.forwarders</code> or else
|
||||
a way for user to submit entries to milter database.
|
||||
<li> The bms.py milter has too many features. Create a framework where
|
||||
numerous small feature modules can be plugged together in the
|
||||
configuration.
|
||||
<li> Create a pure python substitute for miltermodule and libmilter that
|
||||
implements the <a
|
||||
href="http://www.duh.org/cvsweb.cgi/~checkout~/pmilter/doc/milter-protocol.txt?rev=1">
|
||||
libmilter protocol</a> in python.
|
||||
<li> Find or write a faster implementation of sgmllib. The
|
||||
<a href="http://www.effbot.org/zone/sgmlop-index.htm">sgmlop package</a>
|
||||
is not very compatible with
|
||||
<a href="http://www.python.org/doc/2.1.3/lib/module-sgmllib.html">
|
||||
Python-2.1 sgmllib</a>, but it is a start, and is supported in
|
||||
milter-0.4.5 or later.
|
||||
<li> Implement all or most of the features of
|
||||
<a href="http://www.roaringpenguin.com/mimedefang/">MIMEDefang</a>.
|
||||
<li> Follow the official <a href="http://www.python.org/peps/pep-0008.html">
|
||||
Python coding standards</a> more closely.
|
||||
<li> Make unit test code more like other python modules.
|
||||
</menu>
|
||||
|
||||
<h3> Confirmed Installations </h3>
|
||||
|
||||
Please <a href="mailto:%73%74%75%61%72%74%40%62%6D%73%69%2E%63%6F%6D">email</a>
|
||||
me if you successfully install milter on a system not mentioned below.
|
||||
<p>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Operating System</th> <th>Compiler</th> <th>Python</th> <th>Sendmail</th>
|
||||
<th>milter</th>
|
||||
<tr>
|
||||
<td>Mandrake 8.0</td><td>gcc-3.0.1</td><td>2.1.1</td><td>8.12.0</td>
|
||||
<td>0.3.3</td><tr>
|
||||
<td>Mandrake 8.0</td><td>gcc-2.96</td><td>2.0</td><td>8.11.2</td>
|
||||
<td>0.3.6</td><tr>
|
||||
<td>RedHat 6.2</td><td>egcs-1.1.2</td><td>2.2.2</td><td>8.11.6</td>
|
||||
<td>0.5.4</td><tr>
|
||||
<td>RedHat 7.1</td><td>gcc-2.96</td><td>?</td><td>8.12.1</td>
|
||||
<td>0.3.5</td><tr>
|
||||
<td>RedHat 7.3</td><td>gcc-2.96</td><td>2.2.2</td><td>8.11.6</td>
|
||||
<td>0.5.5</td><tr>
|
||||
<td>RedHat 7.3</td><td>gcc-2.96</td><td>2.3.3</td><td>8.13.1</td>
|
||||
<td>0.7.2</td><tr>
|
||||
<td>RedHat 7.3</td><td>gcc-2.96</td><td>2.4.1</td><td>8.13.5</td>
|
||||
<td>0.8.4</td><tr>
|
||||
<td>RedHat 8.0</td><td>gcc-3.2</td><td>2.2.1</td><td>8.12.6</td>
|
||||
<td>0.5.2</td><tr>
|
||||
<td>Debian Linux</td><td>gcc-2.95.2</td><td>2.1.1</td><td>8.12.0</td>
|
||||
<td>0.3.7</td><tr>
|
||||
<td>Debian Linux</td><td>gcc-3.2.2</td><td>2.2.2</td><td>8.12.7</td>
|
||||
<td>0.5.4</td><tr>
|
||||
<td>AIX-4.1.5</td><td>gcc-2.95.2</td><td>2.1.1</td><td>8.11.5</td>
|
||||
<td>0.3.3</td><tr>
|
||||
<td>AIX-4.1.5</td><td>gcc-2.95.2</td><td>2.1.1</td><td>8.12.1</td>
|
||||
<td>0.3.4</td><tr>
|
||||
<td>AIX-4.1.5</td><td>gcc-2.95.2</td><td>2.1.3</td><td>8.12.3</td>
|
||||
<td>0.4.2</td><tr>
|
||||
<td>AIX-4.1.5</td><td>gcc-2.95.2</td><td>2.4.1</td><td>8.13.1</td>
|
||||
<td>0.8.4</td><tr>
|
||||
<td>Slackware 7.1</td><td>?</td><td>?</td><td>8.12.1</td>
|
||||
<td>0.3.8</td><tr>
|
||||
<td>Slackware 9.0</td><td>gcc-3.2.2</td><td>2.2.3</td><td>8.12.9</td>
|
||||
<td>0.5.4</td><tr>
|
||||
<td>OpenBSD</td><td>?</td><td>2.3.3?</td><td>8.13.1?</td>
|
||||
<td>0.7.2</td><tr>
|
||||
<td>SuSE 7.3</td><td>gcc-2.95.3</td><td>2.1.1</td><td>8.12.2</td>
|
||||
<td>0.3.9</td><tr>
|
||||
<td>FreeBSD</td><td>gcc-2.95.3</td><td>2.2.1</td><td>8.12.3</td>
|
||||
<td>0.4.0</td><tr>
|
||||
<td>FreeBSD</td><td>gcc-2.95.3</td><td>2.2.2</td><td>?</td>
|
||||
<td>0.5.5</td><tr>
|
||||
<td>FreeBSD 4.4</td><td>gcc-2.95.3</td><td>?</td><td>8.12.10</td>
|
||||
<td>0.6.6</td>
|
||||
</table>
|
||||
|
||||
<h2> Enough Already! </h2>
|
||||
|
||||
Nearly a dozen people have emailed me begging for a feature to copy
|
||||
outgoing and/or incoming mail to a backup directory by user. Ok, it
|
||||
looks like this is a most requested feature for 0.5.6. In the meantime,
|
||||
here are some things to consider:
|
||||
<ul>
|
||||
<li> If you want to equivalent of a Bcc added to each message, this
|
||||
is very easy to do in the python code for bms.py. See below.
|
||||
<li> If you want to copy to a file in a directory (thus avoiding having to
|
||||
set up aliases), this is slightly more involved. The bms.py milter already
|
||||
copies the message to a temporary file for use in replacing the message body
|
||||
when banned attachments are found. You have to open a file, and copy the
|
||||
Mesage object to it in eom().
|
||||
<li> Finally, you are probably aware that most email clients already
|
||||
keep a copy of outgoing mail? Presumably there is a good reason for
|
||||
keeping another copy on the server.
|
||||
</ul>
|
||||
<p>
|
||||
To Bcc a message, call <code>self.add_recipient(rcpt)</code> in envfrom after
|
||||
determining whether you want to copy (e.g. whether the sender is local). For
|
||||
example,
|
||||
<pre>
|
||||
def envfrom(...
|
||||
...
|
||||
if len(t) == 2:
|
||||
self.rejectvirus = t[1] in reject_virus_from
|
||||
if t[0] in wiretap_users.get(t[1],()):
|
||||
self.add_recipient(wiretap_dest)
|
||||
if t[1] == 'mydomain.com':
|
||||
self.add_recipient('<copy-%s>' % t[0])
|
||||
...
|
||||
</pre>
|
||||
<p>
|
||||
To make this a generic feature requires thinking about how the configuration
|
||||
would look. Feel free to make specific suggestions about config file
|
||||
entries. Be sure to handle both Bcc and file copies, and designating what
|
||||
mail should be copied. How should "outgoing" be defined? Implementing it is
|
||||
easy once the configuration is designed.
|
||||
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<a href="http://validator.w3.org/check/referer">
|
||||
<img border=0 src="http://bmsi.com/vh32.png" alt=" [ Valid HTML 3.2! ] " height=31 width=88></a>
|
||||
<a href="http://www.redhat.com">
|
||||
<img src="http://bmsi.com/art/powered_by.gif" width="88" height="31" alt=" [ Powered By Red Hat Linux ] " border="0"></a>
|
||||
</p>
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Python Milter Mail Policy </title>
|
||||
</head><body>
|
||||
|
||||
<h1> Python Milter Mail Policy </h1>
|
||||
|
||||
<h3> Classify connection </h3>
|
||||
|
||||
When the SMTP client connects, the connection IP address is
|
||||
saved for later verification, and the connection
|
||||
is classified as INTERNAL or EXTERNAL by matching the ip
|
||||
address against the <code>internal_connect</code> configuration.
|
||||
IP addresses with no PTR, and PTR names that look like
|
||||
the kind assigned to dynamic IPs (as determined by a heuristic
|
||||
algorithm) are flagged as DYNAMIC. IPs that match the
|
||||
<code>trusted_relay</code> configuration are flagged as TRUSTED.
|
||||
<p>
|
||||
Examples from the log file (<i>not</i> the SMTP error message returned):
|
||||
<pre>
|
||||
2005Jul29 13:56:53 [71207] connect from p50863492.dip0.t-ipconnect.de at ('80.134.52.146', 1858) EXTERNAL DYN
|
||||
2005Jul29 18:10:15 [74511] connect from foopub at ('1.2.3.4', 46513) EXTERNAL TRUSTED
|
||||
2005Jul29 14:41:00 [71805] connect from foobar at ('192.168.0.1', 41205) INTERNAL
|
||||
2005Jul29 14:41:15 [71806] connect from cncln.online.ln.cn at ('218.25.240.137', 35992) EXTERNAL
|
||||
</pre>
|
||||
<p>
|
||||
Certain obviously evil PTR names are blocked at this point:
|
||||
"localhost" (when IP is not 127.*) and ".".
|
||||
<pre>
|
||||
2005Jul29 14:49:50 [71918] connect from localhost at ('221.132.0.6', 50507) EXTERNAL
|
||||
2005Jul29 14:49:50 [71918] REJECT: PTR is localhost
|
||||
</pre>
|
||||
|
||||
<h3> HELO Check </h3>
|
||||
|
||||
The HELO name provided by the client is saved for later verification
|
||||
(for example by SPF). We could validate the HELO at this point
|
||||
by verifying that an A record for the HELO name matches the connect ip.
|
||||
However, currently we only block certain obvious problems.
|
||||
HELO names that look like an IP4 address
|
||||
and ones that match the <code>hello_blacklist</code> configuration
|
||||
are immediately rejected. The hello_blacklist typically contains
|
||||
the current MTAs own HELO name or email domains.
|
||||
Clients that attempt to skip HELO are immediately rejected.
|
||||
<pre>
|
||||
2005Jul29 18:10:15 [74512] hello from example.com
|
||||
2005Jul29 18:10:15 [74512] REJECT: spam from self: example.com
|
||||
2005Jul29 18:17:09 [74581] hello from 80.191.244.69
|
||||
2005Jul29 18:17:09 [74581] REJECT: numeric hello name: 80.191.244.69
|
||||
</pre>
|
||||
|
||||
<h3> MAIL FROM Check </h3>
|
||||
|
||||
Before calling our milter, sendmail checks a DNS blacklist to
|
||||
block banned sender domains. We never see a blocked domain.
|
||||
<p>
|
||||
The MAIL FROM address is saved for possible use by the smart-alias
|
||||
feature. First, the <code>internal_domains</code> is used for
|
||||
a simple screening if defined. If the MAIL FROM for an INTERNAL connection
|
||||
is NOT in <code>internal_domains</code>, then it is rejected (the
|
||||
PC is most likely infected and attempting to send out spam).
|
||||
If the MAIL FROM for an EXTERNAL connection IS in
|
||||
<code>internal_domains</code>, then the message is immediately rejected.
|
||||
This is quick and effective for most small company MTAs. For more
|
||||
complex mail networks, it is too simplistic, and should not be defined.
|
||||
SPF will handle the complex cases.
|
||||
|
||||
<h4> wiretap </h4>
|
||||
|
||||
The wiretap feature can screen and/or monitor mail to/from certain
|
||||
users. If the MAIL FROM is being wiretapped, the recipients are
|
||||
altered accordingly.
|
||||
|
||||
<h4> SPF check </h4>
|
||||
|
||||
Finally, the MAIL FROM, connect IP, and HELO name are checked against
|
||||
any SPF records published via DNS for the alleged sender (MAIL FROM).
|
||||
If there is no SPF record, we check for a local substitute under the
|
||||
domain defined in the <code>[spf]delegate</code> configuration.
|
||||
Further checks depend on the result.
|
||||
|
||||
<table border=1>
|
||||
<tr><th>NONE</th><td>
|
||||
If there is no SPF record (official or delegated), then we
|
||||
initiate a "three strikes and your out" regime, which looks for
|
||||
<b>some</b> form of validated identification.
|
||||
<ol>
|
||||
<li>We try a "best guess" SPF record of "v=spf1 a/24 mx/24 ptr". If this
|
||||
passes, good.
|
||||
<li> We try to validate the HELO name. First check for an SPF record.
|
||||
Otherwise, check whether the connect IP matches any A record for
|
||||
the HELO name, or any A record for any MX name for the HELO name,
|
||||
or is at least in the same /24 subnet as any of the above.
|
||||
(In other words, a HELO SPF "best guess" of "v=spf1 a/24 mx/24".)
|
||||
If so, good. We consider the HELO validated. If the HELO SPF
|
||||
check fails, we reject the email.
|
||||
</ol>
|
||||
<pre>
|
||||
2005Jul30 19:45:16 [93991] connect from [221.200.41.54] at ('221.200.41.54', 3581) EXTERNAL DYN
|
||||
2005Jul30 19:45:18 [93991] hello from adelphia.net
|
||||
2005Jul30 19:45:19 [93991] mail from <wendy.stubbsua@link-it.com> ()
|
||||
2005Jul30 19:45:19 [93991] REJECT: hello SPF: fail 550 access denied
|
||||
</pre>
|
||||
<ol>
|
||||
<li> If there is a validated PTR name, and it doesn't look
|
||||
like a dynamic name, good. We consider the connection validated.
|
||||
</ol>
|
||||
If any of the above can be validated, we continue on.
|
||||
If none of the above can be validated, and the <code>[SPF]reject_noptr</code>
|
||||
option is true, we reject the message immediately with the explanation
|
||||
that we need some form of valid identification before we accept an email.
|
||||
If <code>[SPF]reject_noptr</code> is false, we flag the message as
|
||||
needing Call Back Validation.
|
||||
The Call Back Valildation sends a DSN to the purported sender informing
|
||||
them of the lack of identification. If the message is legitimate, the
|
||||
sender needs to know that their email setup is broken and should be corrected.
|
||||
If the message is forged, the sender is informed of the forgery,
|
||||
and their need to publish an SPF record or at least use a valid HELO name.
|
||||
If the purported sender does not accept the DSN,
|
||||
then the message is rejected. The CBV status is cached to avoid
|
||||
annoying the purported sender with too many DSNs. Currently, the DSN
|
||||
is repeated to the same sender once per month.
|
||||
<p>
|
||||
In this example, although 3com.com has no SPF record, we assume that
|
||||
any legitimate mail from them will at least have a valid HELO or PTR.
|
||||
<pre>
|
||||
2005Jul30 23:52:03 [96777] connect from [222.252.233.200] at ('222.252.233.200', 29934) EXTERNAL DYN
|
||||
2005Jul30 23:52:03 [96777] hello from 3mail.3com.com
|
||||
2005Jul30 23:52:04 [96777] mail from <etec_nic_family@3mail.3com.com> ()
|
||||
2005Jul30 23:52:04 [96777] REJECT: no PTR, HELO or SPF
|
||||
</pre>
|
||||
</td></tr>
|
||||
|
||||
<tr><th>PASS</th><td>
|
||||
A pass result normally lets the email continue on, but the domain is
|
||||
tracked for reputation (and may be blocked), and may skip content scanning if
|
||||
it matches a whitelist.
|
||||
<pre>
|
||||
2005Jul24 17:44:26 [2104] mail from <gnucash-devel-bounces@gnucash.org> ('SIZE=4410',)
|
||||
2005Jul24 17:44:26 [2104] Received-SPF: pass (mail.bmsi.com: domain of gnucash.org
|
||||
designates 204.107.200.65 as permitted sender)
|
||||
client-ip=204.107.200.65; envelope-from=gnucash-devel-bounces@gnucash.org; helo=cvs.gnucash.org;
|
||||
</pre>
|
||||
</td></tr>
|
||||
|
||||
<tr><th>NEUTRAL</th><td>
|
||||
A neutral result normally lets the email continue on, but the domain is not
|
||||
tracked for reputation or matched against any whitelists.
|
||||
Highly forged domains listed in <code>[SPF]reject_neutral</code> are
|
||||
rejected.
|
||||
<pre>
|
||||
2005Jul24 17:41:37 [2070] connect from cp500627-a.dbsch1.nb.home.nl at ('84.27.225.3', 3465) EXTERNAL
|
||||
2005Jul24 17:41:37 [2070] hello from cp500627-a.dbsch1.nb.home.nl
|
||||
2005Jul24 17:41:38 [2070] mail from <nwarjejkw@yahoo.com> ()
|
||||
2005Jul24 17:41:38 [2070] REJECT: SPF neutral for nwarjejkw@yahoo.com
|
||||
</pre>
|
||||
</td></tr>
|
||||
|
||||
<tr><th>SOFTFAIL</th><td>
|
||||
A softfail result normally lets the email continue on, but the domain is not
|
||||
tracked for reputation or matched against any whitelists. Furthermore,
|
||||
the message is flagged as needing Call Back Validation,
|
||||
and the highly forged domains listed in <code>[SPF]reject_neutral</code> are
|
||||
rejected as well.
|
||||
<p>
|
||||
At present, we also require a valid HELO or PTR to avoid rejecting
|
||||
a softfail. But this should probably change to only require a
|
||||
successful CBV.
|
||||
<p>
|
||||
The Call Back Valildation sends a DSN to the purported sender informing
|
||||
them of the softfail. If the message is legitimate, the sender needs
|
||||
to know about the softfail so that their email setup can be corrected.
|
||||
If the message is forged, the sender is informed of the forgery, confirming
|
||||
that SPF is protecting their reputation and encouraging a rapid transition
|
||||
to a strict policy. If the purported sender does not accept the DSN,
|
||||
then the message is rejected. The CBV status is cached to avoid
|
||||
annoying the purported sender with too many DSNs. Currently, the DSN
|
||||
is repeated to the same sender once per month.
|
||||
<pre>
|
||||
2005Jul24 15:41:33 [801] mail from <Aitp@horafeliz.com> ()
|
||||
2005Jul24 15:41:33 [801] Received-SPF: softfail (mail.bmsi.com: transitioning domain of horafeliz.com
|
||||
does not designate 221.184.83.185 as permitted sender)
|
||||
client-ip=221.184.83.185; envelope-from=Aitp@horafeliz.com;
|
||||
helo=p8185-ipad30funabasi.chiba.ocn.ne.jp;
|
||||
2005Jul24 15:41:33 [801] rcpt to <david@example.com> ()
|
||||
2005Jul24 15:41:35 [801] Subject: Microsoft, Adobe, Macromedia, Corel software. Up to 80% discount.
|
||||
2005Jul24 15:41:35 [801] X-Mailer: Microsoft Outlook, Build 10.0.2605
|
||||
2005Jul24 15:41:35 [801] CBV: Aitp@horafeliz.com
|
||||
2005Jul24 15:41:38 [801] REJECT: CBV: 550 <Aitp@horafeliz.com>: User unknown
|
||||
</pre>
|
||||
</td></tr>
|
||||
|
||||
<tr><th>FAIL</th><td>
|
||||
The message is rejected with a reference the SPF why page.
|
||||
<pre>
|
||||
2005Jul30 19:53:27 [94070] connect from [212.70.52.16] at ('212.70.52.16', 3192) EXTERNAL DYN
|
||||
2005Jul30 19:53:27 [94070] hello from winzip.com
|
||||
2005Jul30 19:53:27 [94070] mail from <dan@winzip.com> ()
|
||||
2005Jul30 19:53:27 [94070] REJECT: SPF fail 550 SPF fail:
|
||||
see http://openspf.com/why.html?sender=dan@winzip.com&ip=212.70.52.16
|
||||
</pre>
|
||||
</td></tr>
|
||||
|
||||
<tr><th>PERMERROR</th><td>
|
||||
Permanent errors were called "unknown", and are still show that way
|
||||
in the log. The message is rejected. Previously, we enabled "lax" parsing
|
||||
of the SPF record, but rejecting is better because it informs the
|
||||
sender about their problem. The next milter version will
|
||||
look for a local substitute SPF record (as for a missing SPF record)
|
||||
before rejecting. This will inform the sender of their problem, but
|
||||
also let the receiver install a temporary workaround.
|
||||
<pre>
|
||||
2005Jul24 18:05:37 [2312] mail from <b-mihdbcgaacaa-becibijh-000-@msg.euxiphipops.com> ()
|
||||
2005Jul24 18:05:37 [2312] REJECT: SPF unknown 550 SPF Permanent Error:
|
||||
include mechanism missing domain: include
|
||||
</pre>
|
||||
The SPF record for msg.euxiphipops.com looked like this at the time of the
|
||||
above error:
|
||||
<pre>
|
||||
msg.euxiphipops.com TXT "v=spf1 mx ptr a include"
|
||||
</pre>
|
||||
</td></tr>
|
||||
|
||||
<tr><th>TEMPERROR</th><td>
|
||||
Temporary errors result in a 451 "Try again later" response. The sender
|
||||
should retry the message at a later time.
|
||||
<pre>
|
||||
2005Jul24 07:33:13 [29846] mail from <quickenloans@rate.quicken.com> ('SIZE=73775', 'BODY=8BITMIME')
|
||||
2005Jul24 07:33:43 [29846] TEMPFAIL: SPF error 450 SPF Temporary Error: DNS Timeout
|
||||
</pre>
|
||||
</td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
@@ -0,0 +1,92 @@
|
||||
<h2> Requirements </h2>
|
||||
|
||||
<menu>
|
||||
<li> While the miltermodule will work with python 1.5, you probably
|
||||
want to use python 2.0 or better. The python code uses a number of
|
||||
python 2 features. The email support requires python 2.4.
|
||||
<li> Python must be configured with thread support. This is because
|
||||
sendmail's libmilter requires thread support.
|
||||
<li> You must compile sendmail with libmilter enabled. In versions of
|
||||
sendmail prior to 8.12 libmilter is marked FFR (For Future Release) and
|
||||
is not installed by default.
|
||||
Sendmail 8.12 still does not enable libmilter by default. You must
|
||||
explicitly select the "MILTER" option when compiling.
|
||||
<li> Python milter has been tested against sendmail-8.11 and sendmail-8.12.
|
||||
<li> Python milter must be compiled for the specific version of sendmail
|
||||
it will run with. (Since the result is dynamically loaded, there could
|
||||
conceivably be multiple versions available and selected at startup - but
|
||||
that will have to wait.) This situation may only exist for sendmail
|
||||
versions prior to 8.12. The protocol seems designed for backward
|
||||
compatibility - and 8.12 is the first official milter release.
|
||||
<li> Mea Culpa! After reading the Python Style guide, I realize that
|
||||
my Python code is not up to snuff. Apparently mixed tabs and spaces
|
||||
are anathema to those using Windows editors, where tabs can be expanded using
|
||||
any arbitrary algorithm. Other than that, my
|
||||
intuition matched Guido's pretty well - although I like to indent by 2
|
||||
rather than 4. I will arrange to have tabs expanded to spaces when
|
||||
exporting new versions. Until then, beware!
|
||||
</menu>
|
||||
|
||||
<h3> <a name="aix4"> AIX 4.1.5 Requirements </a> </h3>
|
||||
To create sendmail RPMs for AIX, you can download my AIX 4.1.5 spec files
|
||||
for <a href="/aix/sendmail.spec">sendmail-8.11.5</a>
|
||||
or <a href="/aix/sendmail12.spec">sendmail-8.12.3</a>. If you have
|
||||
not already set it up, I use a <a href="/aix/aix.spec">dummy RPM package</a>
|
||||
to represent the stuff that comes with AIX. You might also want
|
||||
my <a href="/aix/python.spec">python-2.1.1</a> spec file for AIX. It
|
||||
does not include Tk or curses modules, sorry. If y'all trust me, you can
|
||||
download rpms for AIX 4.x from my <a href="/aix">AIX RPM directory</a>.
|
||||
<p>
|
||||
Sendmail-8.12 renames
|
||||
libsmutil.a to libsm.a. Unfortunately, libsm.a is an important AIX system
|
||||
shared library. Therefore, I rename libsm.a back to libsmutil.a for
|
||||
AIX. This presents a problem for setup.py.
|
||||
|
||||
<h3> <a name="rh72"> RedHat 7.2 Requirements </a> </h3>
|
||||
|
||||
If you are running Redhat 7.2, the distributed version of sendmail
|
||||
now enables libmilter by default. RedHat 7.2 bundles
|
||||
the development libraries with the main sendmail package, so
|
||||
there is no sendmail-devel package. However, they forgot to include the
|
||||
headers! So you'll have to get the SRPM and modify it. I suggest
|
||||
moving the static libs to a devel package and adding the headers. If
|
||||
this is too much trouble, you can get the <a href="mfapi.h">mfapi.h</a>
|
||||
header for sendmail-8.6.11 from here and manually install it as
|
||||
<code>/usr/include/libmilter/mfapi.h</code>.
|
||||
<p>
|
||||
If you do modify the SRPM, I suggest renaming libsmutil.a
|
||||
to libsm.a - just like sendmail-8.12 will. If you manually install
|
||||
mfapi.h or don't rename libsmutil.a, you'll
|
||||
need to force <code>libs = ["milter", "smutil"]</code> in setup.py.
|
||||
<p>
|
||||
If you have installed python2, and want
|
||||
python-milter to use python2, add <code>python=python2</code> to setup.cfg
|
||||
and build with <code>python2 setup.py bdist_rpm</code>.
|
||||
|
||||
<h3> <a name="rh62"> Redhat 6.2 Requirements </a> </h3>
|
||||
|
||||
If you are running Redhat 6.2, the distributed version of sendmail
|
||||
does not enable libmilter. You can download the Redhat 7.2 sendmail.spec
|
||||
modified to compile on RedHat 6.2:
|
||||
<a href="http://www.bmsi.com/linux/rh62/sendmail-rhmilter.spec">
|
||||
sendmail-rhmilter.spec</a>. The <a
|
||||
href="ftp://updates.redhat.com/7.0/en/os/SRPMS/sendmail-8.11.6-1.7.0.src.rpm">
|
||||
SRPM for sendmail-8.11.6</a> is available from
|
||||
<a href="http://www.redhat.com">Redhat</a> under
|
||||
<a href="http://www.redhat.com/support/errata/RHSA-2001-106.html">
|
||||
Errata for RH6.2</a>. But that doesn't include the latest security
|
||||
patches since RH6.2 is no longer supported.
|
||||
<p>
|
||||
If y'all trust me, you can pick up source and binary sendmail RPMs for RH6.2
|
||||
from my <a href="http://www.bmsi.com/linux/rh62">linux downloads</a> directory.
|
||||
The lastest RPMs were built by taking a RH7.2 SRPMS and removing some
|
||||
RPM features from the spec file that RH6.2 doesn't support, then
|
||||
recompiling on RH6.2. You can check this by installing the RH7.2 SRPM,
|
||||
then diffing my sendmail.spec with theirs. Then run
|
||||
"rpm -bb sendmail-rhmilter.spec" when you are satisfied.
|
||||
<p>
|
||||
If you have installed python2, and want
|
||||
python-milter to use python2, add <code>python=python2</code> to setup.cfg
|
||||
and build with <code>python2 setup.py bdist_rpm</code>.
|
||||
You'll need to install the sendmail-devel package to compile milter.
|
||||
|
||||
Reference in New Issue
Block a user