<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Scott Yang's Playground &#187; Postfix</title>
	<atom:link href="http://scott.yang.id.au/tag/postfix/feed/" rel="self" type="application/rss+xml" />
	<link>http://scott.yang.id.au</link>
	<description>Faith, Technology and Randomness in Life, According to Scott</description>
	<lastBuildDate>Thu, 09 Feb 2012 09:01:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Greylisting Spams with Postfix + Gld</title>
		<link>http://scott.yang.id.au/2006/09/greylisting-spams-with-postfix-gld/</link>
		<comments>http://scott.yang.id.au/2006/09/greylisting-spams-with-postfix-gld/#comments</comments>
		<pubDate>Fri, 01 Sep 2006 11:20:09 +0000</pubDate>
		<dc:creator>scotty</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Postfix]]></category>
		<category><![CDATA[Spam]]></category>

		<guid isPermaLink="false">http://scott.yang.id.au/2006/09/greylisting-spams-with-postfix-gld/</guid>
		<description><![CDATA[HostingFu: Greylisting spams with Postfix + Gld. I have previously used only Amavisd + SpamAssassin + ClamAV, but the amount of incoming spams really work my poor server hard. After running greylisting for a month, spams virtually disappeared from my inbox. Highly recommended if you are running your own mail server.]]></description>
			<content:encoded><![CDATA[<p><a href="http://hostingfu.com/article/greylisting-spams-with-postfix-gld">HostingFu: Greylisting spams with Postfix + Gld</a>. I have previously used only <a href="http://scott.yang.id.au/2004/03/running-postfix-amavis-clam-antivirus/">Amavisd + SpamAssassin + ClamAV</a>, but the amount of incoming spams really work my poor server hard. After running greylisting for a month, spams virtually disappeared from my inbox. Highly recommended if you are running your own mail server.</p>
]]></content:encoded>
			<wfw:commentRss>http://scott.yang.id.au/2006/09/greylisting-spams-with-postfix-gld/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A recent Postfix log on spamming attempt</title>
		<link>http://scott.yang.id.au/2004/01/a-recent-postfix-log-on-spamming-attempt/</link>
		<comments>http://scott.yang.id.au/2004/01/a-recent-postfix-log-on-spamming-attempt/#comments</comments>
		<pubDate>Sun, 11 Jan 2004 08:44:15 +0000</pubDate>
		<dc:creator>scotty</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Postfix]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Spam]]></category>

		<guid isPermaLink="false">http://scott.yang.id.au/2004/01/a-recent-postfix-log-on-spamming-attempt/</guid>
		<description><![CDATA[I have received the following logs on my mail server regularly over the last 2-3 months, showing attempts of spammers trying to send me a junk mail. The log is generated by Postfix automatically, and send to my postmaster box. Out: 220 mx.yang.id.au ESMTP Postfix In: POST / HTTP/1.0 Out: 502 Error: command not implemented [...]]]></description>
			<content:encoded><![CDATA[<p>I have received the following logs on my mail server regularly over the last 2-3 months, showing attempts of spammers trying to send me a junk mail. The log is generated by <a href="http://www.postfix.org/">Postfix</a> automatically, and send to my postmaster box.</p>
<pre>
 <span style="color:#a00">Out: 220 mx.yang.id.au ESMTP Postfix</span>
 <span style="color:#080">In:  POST / HTTP/1.0</span>
 <span style="color:#a00">Out: 502 Error: command not implemented</span>
 <span style="color:#080">In:  Content-Type: text/plain</span>
 <span style="color:#a00">Out: 502 Error: command not implemented</span>
 <span style="color:#080">In:  Content-Length: 1111</span>
 <span style="color:#a00">Out: 502 Error: command not implemented</span>
 <span style="color:#080">In:  Host: mx.yang.id.au</span>
 <span style="color:#a00">Out: 502 Error: command not implemented</span>
 <span style="color:#080">In:  X-Forwarded-For: <em>[Spammer's fake real address]</em></span>
 <span style="color:#a00">Out: 502 Error: command not implemented</span>
 <span style="color:#080">In:  Connection: Keep-Alive</span>
 <span style="color:#a00">Out: 502 Error: command not implemented</span>
 <span style="color:#080">In:</span>
 <span style="color:#a00">Out: 500 Error: bad syntax</span>
 <span style="color:#080">In:  RSET</span>
 <span style="color:#a00">Out: 250 Ok</span>
 <span style="color:#080">In:  HELO yahoo.de</span>
 <span style="color:#a00">Out: 250 mx.yang.id.au</span>
 <span style="color:#080">In:  MAIL FROM:&lt;<em>Spammer's fake Hotmail address</em>&gt;</span>
 <span style="color:#a00">Out: 250 Ok</span>
 <span style="color:#080">In:  RCPT TO:<scotty@yang.id.au></span>
 <span style="color:#a00">Out: 554 Service unavailable; [<em>Spammer's real IP</em>] blocked using bl.spamcop.net,
     reason: Blocked - see http://www.spamcop.net/bl.shtml?<em>Spammer's real IP</em></span>
 <span style="color:#080">In:  DATA</span>
 <span style="color:#a00">Out: 554 Error: no valid recipients</span>
 <span style="color:#080">In:  To: &lt;<em>My real email address</em>&gt;</span>
 <span style="color:#a00">Out: 502 Error: command not implemented</span>
 <span style="color:#080">In:  From: "eddie" &lt;<em>Spammer's another fake Hotmail address</em>&gt;</span>
 <span style="color:#a00">Out: 221 Error: I can break rules, too. Goodbye.</span>
</pre>
<p>Lines that appear in <span style="color:#0c0">green</span> are requests sent out by spammer&#8217;s program. Lines that appear in <span style="color:#a00">red</span> are responses from my Postfix server. Fortunately I have used <a href="http://www.spamcop.net/">SpamCop</a> as my RBL to block these offending SMTP transactions by the IP address they are originating. Interestingly that it tried to issue HTTP commands when it first connects to the mail server. It does a POST to the root index, and obviously Postfix would not handle it. I wonder whether it is trying to find some exploits against unsecured mail server, testing for a open proxy server running at port 25 (why would people do that) or something else. Another interesting observation is the response given by Postfix &#8211; instead of dropping the connection after first few invalid commands have been entered, it actually allows the spammer to continue and issue a RSET to change conversation back to SMTP protocol. The connection should have been dropped after a few lines of bogus requests.</p>
<p>I did not go and look up the IP address of the offending host, but I suspect that it is probably one of the machines that have been infected by virus, and thus bow down to their <strike>dark lord</strike>, hmm, I mean spammer. Pitty that these zombies around the world have been aiding the ugly business of sending junk mails&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://scott.yang.id.au/2004/01/a-recent-postfix-log-on-spamming-attempt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automating Aliases Generation for Mailman and Postfix</title>
		<link>http://scott.yang.id.au/2003/01/automating-aliases-generation-for-mailman-and-postfix/</link>
		<comments>http://scott.yang.id.au/2003/01/automating-aliases-generation-for-mailman-and-postfix/#comments</comments>
		<pubDate>Fri, 10 Jan 2003 06:53:17 +0000</pubDate>
		<dc:creator>scotty</dc:creator>
				<category><![CDATA[Mailman]]></category>
		<category><![CDATA[Postfix]]></category>

		<guid isPermaLink="false">http://scott.yang.id.au/2003/01/automating-aliases-generation-for-mailman-and-postfix/</guid>
		<description><![CDATA[I have recently upgraded the mailing list manager software for FOCUS mailing list to Mailman 2.1. I have been running Mailman 2.0 since its beta days 2 years ago, and it has been a great piece of software. FOCUS mailing list is quite light in traffic (average 70-100 posts a month across all lists), and [...]]]></description>
			<content:encoded><![CDATA[<p>I have recently upgraded the mailing list manager software for <a href="http://list.focus-unsw.org/">FOCUS mailing list</a> to <a href="http://www.list.org/">Mailman 2.1</a>. I have been running Mailman 2.0 since its beta days 2 years ago, and it has been a great piece of software. FOCUS mailing list is quite light in traffic (average 70-100 posts a month across all lists), and Mailman with all its strength seems to be an over kill for this task. Nevertheless, I&#8217;ve also learnt a great deal of Python programming from its sources. Thanks to <a href="http://barry.warsaw.us/">Barry Warsaw</a> and all those who contribute to this project!</p>
<p>This article documents my quest to work around generating email aliases for Postfix whenever a mailing list is added ore removed.</p>
</p>
<h3 id="toc-why">Why?</h3>
<p>Setting up aliases between Mailman and MTA has always been tricky. For every mailing list hosted, you have to create several email aliases manually in order to pipe the incoming emails to Mailman&#8217;s scripts. For example, these aliases need to be appended to <tt>/etc/aliases</tt> (or <tt>/etc/postfix/aliases</tt> for Postfix) when a new mailing list <b>mbf</b> was added.</p>
<pre>
mbf:             "|/home/mailman/mail/mailman post mbf"
mbf-admin:       "|/home/mailman/mail/mailman admin mbf"
mbf-bounces:     "|/home/mailman/mail/mailman bounces mbf"
mbf-confirm:     "|/home/mailman/mail/mailman confirm mbf"
mbf-join:        "|/home/mailman/mail/mailman join mbf"
mbf-leave:       "|/home/mailman/mail/mailman leave mbf"
mbf-owner:       "|/home/mailman/mail/mailman owner mbf"
mbf-request:     "|/home/mailman/mail/mailman request mbf"
mbf-subscribe:   "|/home/mailman/mail/mailman subscribe mbf"
mbf-unsubscribe: "|/home/mailman/mail/mailman unsubscribe mbf"
</pre>
<p>Mailman 2.1 comes with automatic configuration for Postfix by generating aliases, virtual domain and associated configuration files every time a list is added or removed. However, it is not that flexible for me as I run quite a few virtual domains on my mail server, and the domain <tt>list.focus-unsw.org</tt> is dedicated for mailing lists. Instead of playing around the aliases file, I want to parse the &#8220;To:&#8221; address to determine which mailing list it is delivering to. Here&#8217;s my approach&#8230;</p>
<h3 id="toc-mailman-installation">Mailman Installation</h3>
<p>Grab the source and install Mailman as normal. That includes creating the <tt>mailman</tt> user, configuring, compiling and installing Mailman, setting up crontab, etc. However, don&#8217;t touch any MTA integration yet.</p>
<p>I am aiming to dedicate domain <tt>list.focus-unsw.org</tt> for mailing lists &#8211; any emails sent to this domain is assuming to be reserved for Mailman to consume. It includes assigning an <b>A</b> record for <tt>list.focus-unsw.org</tt>.</p>
<h3 id="toc-postfix-configuration">Postfix Configuration</h3>
<p>For <tt>/etc/postfix/main.cf</tt>, make sure you have the following configuration.</p>
<pre>
recipient_delimiter = +
virtual_maps = hash:/etc/postfix/virtual, regexp:/etc/postfix/virtual_regexp
</pre>
<p>Virtual domain mapping file &#8220;<tt>/etc/postfix/virtual_regexp</tt>&#8221; contains regular expressions to rewrite all the emails sending to <tt>list.focus-unsw.org</tt> to go to the user <tt>mailman</tt>. For emails sending to <tt>foo-bar@list.focus-unsw.org</tt>, I want to rewrite them to go to <tt>mailman+foo-bar</tt>. Append these to this file:</p>
<pre>
/^list.focus-unsw.org$/       IGNORED
/^(.*)@list.focus-unsw.org$/  mailman+$1
</pre>
<h3 id="toc-mailman-configuration">Mailman Configuration</h3>
<p>I am using a <tt>.forward</tt> to pipe all the emails sent to user <tt>mailman</tt> to Mailman&#8217;s mail handling script. However, Mailman&#8217;s script (<tt>$HOME/mail/mailman</tt> in 2.1) requires two arguments &#8211; a command and a list name. When Postfix is doing a local delivery, it will append <tt>Deliver-To:</tt> to the email header, detailing the exact recipient in the delivery. Therefore I wrote a Python script to sit between <tt>.forward</tt> and Mailman to parse the email, learn about the mailman command and list name from its <tt>Deliver-To:</tt> header, and then pipe the result to Mailman&#8217;s script with correct parameters.</p>
<p>Here&#8217;s the <tt>.forward</tt> file in Mailman&#8217;s home directory, which is <tt>/home/mailman</tt> in this case.</p>
<pre>
"|/home/mailman/mail/filter.py"
</pre>
<p><tt>filter.py</tt> is the Python script I wrote, which can be downloaded <a href="http://scott.yang.id.au/file/python/filter.zip">here</a>. It basically reads the email from standard input, line by line, until it reaches the <tt>Deliver-To:</tt> header. It then parse the header to work out required arguments to call <tt>/home/mailman/mail/mailman</tt>. It then pipes everything it receives to Mailman&#8217;s process. Here&#8217;s the syntax highlighted version:</p>
<pre lang="python">
#!/usr/bin/env python

from cStringIO import StringIO
import os
import re
import sys

output = StringIO()
found  = 0

re_search = re.compile(r'^Delivered-To:\s*mailman\+(\w+)(-(\w+))?@')

for line in sys.stdin:
    if not found:
	m = re_search.search(line)
        if m is not None:
            lst = m.group(1)
	    cmd = m.group(3)
	    if cmd is None:
		cmd = 'post'
	    elif cmd not in [
		'admin', 'bounces', 'confirm', 'join', 'leave', 'owner',
		'request', 'subscribe', 'unsubscribe',
	    ]:
		print &gt;&gt; sys.stderr, 'Invalid command "%s"' % cmd
		break

	    try:
		wrapper = "/home/mailman/mail/mailman '%s' '%s'" % \
		    (cmd, lst.replace("'", "\\'"))
		wrapper = os.popen(wrapper, "w")
	    except os.Error, ex:
		print &gt;&gt; sys.stderr, 'Cannot execute mailman.', ex
		break

	    wrapper.write(output.getvalue())
	    output = wrapper
	    found  = 1

	elif line.strip() == '':
	    print &gt;&gt; sys.stderr, 'Deliver-To header cannot be found.'
	    break

    output.write(line)

if not found:
    sys.exit(67)

if output.close() is not None:
    sys.exit(67)
</pre>
<h3 id="toc-conclusion">Conclusion</h3>
<p>After it is done, there is no modification needs to be done to both Postfix or Mailman whenever new mailing lists are created, or abandoned lists are purged. It is probably less efficient because for every mailing list post delivered, two processes (<tt>mailman</tt> and <tt>filter.py</tt>) need to be started instead of just one. I have been running this script (with modifications every now and then) for the last two years without any problem. Originally it was actually written in Perl, but I have since decided that Python is a much better scripting language :)</p>
]]></content:encoded>
			<wfw:commentRss>http://scott.yang.id.au/2003/01/automating-aliases-generation-for-mailman-and-postfix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

