<?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>treibsand.com &#187; SMTP</title>
	<atom:link href="http://www.treibsand.com/tag/smtp/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.treibsand.com</link>
	<description></description>
	<lastBuildDate>Tue, 27 Dec 2011 12:46:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>SMTP Engine in Python</title>
		<link>http://www.treibsand.com/2007/03/15/smtpd_python/</link>
		<comments>http://www.treibsand.com/2007/03/15/smtpd_python/#comments</comments>
		<pubDate>Thu, 15 Mar 2007 13:10:31 +0000</pubDate>
		<dc:creator>Toast</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Mail]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[SMTP]]></category>

		<guid isPermaLink="false">http://test.treibsand.com/?p=43</guid>
		<description><![CDATA[Vor kurzem war ich dabei einen Contentfilter für Postfix zu schreiben. Einfache Contentfilter lassen sich ja sogar mit Shell Scripts machen, diese werden dann aber per Pipe aufgerufen, was mir nicht wirklich gefällt&#8230; Viel interessanter ist es einen Contentfilter per spawn einzubinden, was ein Program startet und es an einen Socket bindet, etwa so wie [...]]]></description>
			<content:encoded><![CDATA[<p>Vor kurzem war ich dabei einen Contentfilter für Postfix zu schreiben. Einfache Contentfilter lassen sich ja sogar mit Shell Scripts machen, diese werden dann aber per Pipe aufgerufen, was mir nicht wirklich gefällt&#8230; </p>
<p><span id="more-43"></span><br />
Viel interessanter ist es einen Contentfilter per spawn einzubinden, was ein Program startet und es an einen Socket bindet, etwa so wie inetd. Die Kommunikation zwischen Postfix und dem Contentfilter läuft dann per STDIN bzw. STDOUT&#8230;</p>
<p>Der Contentfilter muss aber SMTP sprechen können, da Postfix per STDIN Smtp Kommandos schickt. Somit musste ich eine SMTPD Klasse in Python schreiben. Da es allgemein wenig Dokumentiert ist, wie so etwas programmiert werden kann, stelle ich hier die Basis-Klasse zur<br />
Verfügung.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>, <span style="color: #dc143c;">string</span>, <span style="color: #dc143c;">os</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#---------------------------------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">class</span> SMTPServerEngine:
	ST_INIT = <span style="color: #ff4500;">0</span>
	ST_HELO = <span style="color: #ff4500;">1</span>
	ST_MAIL = <span style="color: #ff4500;">2</span>
	ST_RCPT = <span style="color: #ff4500;">3</span>
	ST_DATA = <span style="color: #ff4500;">4</span>
	ST_QUIT = <span style="color: #ff4500;">5</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
		<span style="color: #008000;">self</span>.<span style="color: black;">state</span> = SMTPServerEngine.<span style="color: black;">ST_INIT</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> chug<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
		<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
			data = <span style="color: #483d8b;">''</span>
			completeLine = <span style="color: #ff4500;">0</span>
			<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff7700;font-weight:bold;">not</span> completeLine:
				lump = <span style="color: #dc143c;">os</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">stdin</span>.<span style="color: black;">fileno</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: #ff4500;">1024</span><span style="color: black;">&#41;</span>
				<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>lump<span style="color: black;">&#41;</span>:
					data += lump
					<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span>= <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> data<span style="color: black;">&#91;</span>-<span style="color: #ff4500;">2</span>:<span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>'</span>:
						completeLine = <span style="color: #ff4500;">1</span>
						<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">state</span> <span style="color: #66cc66;">!</span>= SMTPServerEngine.<span style="color: black;">ST_DATA</span>:
							rsp, keep = <span style="color: #008000;">self</span>.<span style="color: black;">doCommand</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span>
						<span style="color: #ff7700;font-weight:bold;">else</span>:
							rsp = <span style="color: #008000;">self</span>.<span style="color: black;">doData</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span>
&nbsp;
						<span style="color: #ff7700;font-weight:bold;">if</span> rsp == <span style="color: #008000;">None</span>:
							<span style="color: #ff7700;font-weight:bold;">continue</span>
&nbsp;
						<span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span>rsp + <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>
						<span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span>.<span style="color: black;">flush</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
						<span style="color: #ff7700;font-weight:bold;">if</span> keep == <span style="color: #ff4500;">0</span>:	
							<span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
							<span style="color: #ff7700;font-weight:bold;">return</span>	
				<span style="color: #ff7700;font-weight:bold;">else</span>:
					<span style="color: #ff7700;font-weight:bold;">return</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">return</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> doCommand<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, data<span style="color: black;">&#41;</span>:
		<span style="color: #483d8b;">&quot;&quot;&quot;Process a single SMTP Command&quot;&quot;&quot;</span>
		<span style="color: #dc143c;">cmd</span> = data<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>:<span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span>
		<span style="color: #dc143c;">cmd</span> = <span style="color: #dc143c;">string</span>.<span style="color: black;">upper</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">cmd</span><span style="color: black;">&#41;</span>
		keep = <span style="color: #ff4500;">1</span>
		<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">cmd</span> == <span style="color: #483d8b;">&quot;HELO&quot;</span>:
			<span style="color: #008000;">self</span>.<span style="color: black;">state</span> = SMTPServerEngine.<span style="color: black;">ST_HELO</span>
		<span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #dc143c;">cmd</span> == <span style="color: #483d8b;">&quot;RSET&quot;</span>:
			<span style="color: #008000;">self</span>.<span style="color: black;">dataAccum</span> = <span style="color: #483d8b;">&quot;&quot;</span>
			<span style="color: #008000;">self</span>.<span style="color: black;">state</span> = SMTPServerEngine.<span style="color: black;">ST_INIT</span>
		<span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #dc143c;">cmd</span> == <span style="color: #483d8b;">&quot;NOOP&quot;</span>:
			<span style="color: #ff7700;font-weight:bold;">pass</span>
		<span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #dc143c;">cmd</span> == <span style="color: #483d8b;">&quot;QUIT&quot;</span>:
			keep = <span style="color: #ff4500;">0</span>
		<span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #dc143c;">cmd</span> == <span style="color: #483d8b;">&quot;MAIL&quot;</span>:
			<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">state</span> <span style="color: #66cc66;">!</span>= SMTPServerEngine.<span style="color: black;">ST_HELO</span>:
				<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;503 Bad command sequence&quot;</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
			<span style="color: #008000;">self</span>.<span style="color: black;">state</span> = SMTPServerEngine.<span style="color: black;">ST_MAIL</span>
		<span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #dc143c;">cmd</span> == <span style="color: #483d8b;">&quot;RCPT&quot;</span>:
			<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">state</span> <span style="color: #66cc66;">!</span>= SMTPServerEngine.<span style="color: black;">ST_MAIL</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">state</span> <span style="color: #66cc66;">!</span>= SMTPServerEngine.<span style="color: black;">ST_RCPT</span><span style="color: black;">&#41;</span>:
				<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;503 Bad command sequence&quot;</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
			<span style="color: #008000;">self</span>.<span style="color: black;">state</span> = SMTPServerEngine.<span style="color: black;">ST_RCPT</span>
		<span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #dc143c;">cmd</span> == <span style="color: #483d8b;">&quot;DATA&quot;</span>:
			<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">state</span> <span style="color: #66cc66;">!</span>= SMTPServerEngine.<span style="color: black;">ST_RCPT</span>:
				<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;503 Bad command sequence&quot;</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
			<span style="color: #008000;">self</span>.<span style="color: black;">state</span> = SMTPServerEngine.<span style="color: black;">ST_DATA</span>
			<span style="color: #008000;">self</span>.<span style="color: black;">dataAccum</span> = <span style="color: #483d8b;">&quot;&quot;</span>
			<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;354 OK, Enter data, terminated with a <span style="color: #000099; font-weight: bold;">\\</span>r<span style="color: #000099; font-weight: bold;">\\</span>n.<span style="color: #000099; font-weight: bold;">\\</span>r<span style="color: #000099; font-weight: bold;">\\</span>n&quot;</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">else</span>:
			<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;505 Eh? WTF was that?&quot;</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">return</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;250 OK&quot;</span>, keep<span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">def</span> doData<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, data<span style="color: black;">&#41;</span>:
		<span style="color: #483d8b;">&quot;&quot;&quot;
		Process SMTP Data. Accumulates client DATA until the
		terminator is found.
		&quot;&quot;&quot;</span>
		<span style="color: #008000;">self</span>.<span style="color: black;">dataAccum</span> = <span style="color: #008000;">self</span>.<span style="color: black;">dataAccum</span> + data
		<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">dataAccum</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">4</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">self</span>.<span style="color: black;">dataAccum</span><span style="color: black;">&#91;</span>-<span style="color: #ff4500;">5</span>:<span style="color: black;">&#93;</span> == <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>.<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>'</span>:
			<span style="color: #008000;">self</span>.<span style="color: black;">dataAccum</span> = <span style="color: #008000;">self</span>.<span style="color: black;">dataAccum</span><span style="color: black;">&#91;</span>:-<span style="color: #ff4500;">5</span><span style="color: black;">&#93;</span>
			<span style="color: #008000;">self</span>.<span style="color: black;">state</span> = SMTPServerEngine.<span style="color: black;">ST_HELO</span>
&nbsp;
			<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;250 OK - message accepted&quot;</span>
		<span style="color: #ff7700;font-weight:bold;">else</span>:
			<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">None</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;">#---------------------------------------------------------------------------------------------</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
	<span style="color: #ff7700;font-weight:bold;">try</span>:
		<span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;220 localhost<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>
		<span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span>.<span style="color: black;">flush</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
			engine = SMTPServerEngine<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
			engine.<span style="color: black;">chug</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">SystemExit</span>:
		<span style="color: #ff7700;font-weight:bold;">pass</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.treibsand.com/2007/03/15/smtpd_python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

