Python Milter FAQ

    Compiling Python Milter

  1. Q. I have installed sendmail from source, but Python milter won't compile.

    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 RPM spec file 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.

  2. Q. Why is mfapi.h not found when I try to compile Python milter on RedHat 7.2?

    A. RedHat forgot to include the header in the RPM. See the RedHat 7.2 requirements.

    Running Python Milter

  3. Q. The sample.py milter prints a message, then just sits there.
    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
    

    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.

  4. Q. I've configured sendmail properly, but still nothing happens when I send myself mail!

    A. Sendmail only milters SMTP mail. Local mail is not miltered. You can pipe a raw message through sendmail to test your milter:

    $ cat rawtextmsg | sendmail myname@my.full.domain
    
    Now check your milter log.

  5. Q. Why do I get this ImportError exception?
    File "mime.py", line 370, in ?
        from sgmllib import declstringlit, declname
        ImportError: cannot import name declstringlit
    

    A. declstringlit 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.

  6. Q. Why do I get milter.error: cannot add recipient?
    
    

    A. You must tell libmilter how you might mutate the message with set_flags() before calling runmilter(). For instance, Milter.set_flags(Milter.ADDRCPT). You must add together all of ADDHDRS, CHGBODY, ADDRCPT, DELRCPT, CHGHDRS that apply.

    NOTE - recent versions default flags to enabling all features. You must now call set_flags() if you wish to disable features for efficiency.

  7. Q. Why does sendmail sometimes print something like: "...write(D) returned -1, expected 5: Broken pipe" in the sendmail log?

    A. Libmilter expects "rcpt to" shortly after getting "mail from". "Shortly" is defined by the timeout parameter you passed to Milter.runmilter() or milter.settimeout(). 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. Milter.runmilter() defaulted to 10 seconds in 0.3.4. In 0.3.5 it will keep the libmilter default of 2 hours.

  8. Q. Why does milter block messages with big5 encoding? What if I want to receive them?

    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.

    If you are running bms.py, then the block_chinese option in /etc/mail/pymilter.cfg controls this feature.

  9. Q. Why does sendmail coredump with milters on OpenBSD?

    A. Sendmail has a problem with unix sockets on old versions of OpenBSD. Use an internet domain socket instead. For example, in sendmail.cf use

    Xpythonfilter, S=inet:1234@localhost
    
    and change sample.py accordingly.

    OpenBSD users report that this problem has been fixed.

  10. 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!

    A. Configure sendmail to use virtusertable, and send all unknown addresses to /dev/null. For example,

    /etc/mail/virtusertable

    @mycorp.com	dev-null
    dan@mycorp.com	dan
    sally@mycorp.com	sally
    

    /etc/aliases

    dev-null:	/dev/null
    
    Now your milter will get to the eom callback, and can change the envelope recipient at will. Thanks to Dredd at milter.org for this solution.

  11. Q. I am having trouble with the setreply method. It always outputs "milter.error: cannot set reply".

    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:

    Xpythonfilter, S=local:/var/log/milter/pythonsock, F=T, T=C:5m;S:20s;R:60s;E:5m
    
  12. Q. So how do I use the SPF support? The sample.py milter doesn't seem to use it.

    A. The bms.py milter supports spf. The RedHat RPMs will set almost everything up for you. For other systems:

    1. 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).
    2. Copy pymilter.cfg to the /etc/mail or the directory you run bms.py in, and edit it. The comments should explain the options.
    3. Start bms.py in the background as arranged.
    4. 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.
    5. Arrange to rotate log files and remove old defang files in tempdir. The RedHat RPM uses logrotate for logfiles and a simple cron script using find to clean tempdir.