<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>smtpd – Sample SMTP Servers — Python Module of the Week</title> <link rel="stylesheet" href="../_static/sphinxdoc.css" type="text/css" /> <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> <script type="text/javascript"> var DOCUMENTATION_OPTIONS = { URL_ROOT: '../', VERSION: '1.132', COLLAPSE_INDEX: false, FILE_SUFFIX: '.html', HAS_SOURCE: true }; </script> <script type="text/javascript" src="../_static/jquery.js"></script> <script type="text/javascript" src="../_static/underscore.js"></script> <script type="text/javascript" src="../_static/doctools.js"></script> <link rel="author" title="About these documents" href="../about.html" /> <link rel="top" title="Python Module of the Week" href="../index.html" /> <link rel="up" title="Internet Protocols and Support" href="../internet_protocols.html" /> <link rel="next" title="smtplib – Simple Mail Transfer Protocol client" href="../smtplib/index.html" /> <link rel="prev" title="SimpleXMLRPCServer – Implements an XML-RPC server." href="../SimpleXMLRPCServer/index.html" /> </head> <body> <div class="related"> <h3>Navigation</h3> <ul> <li class="right" style="margin-right: 10px"> <a href="../genindex.html" title="General Index" accesskey="I">index</a></li> <li class="right" > <a href="../py-modindex.html" title="Python Module Index" >modules</a> |</li> <li class="right" > <a href="../smtplib/index.html" title="smtplib – Simple Mail Transfer Protocol client" accesskey="N">next</a> |</li> <li class="right" > <a href="../SimpleXMLRPCServer/index.html" title="SimpleXMLRPCServer – Implements an XML-RPC server." accesskey="P">previous</a> |</li> <li><a href="../contents.html">PyMOTW</a> »</li> <li><a href="../internet_protocols.html" accesskey="U">Internet Protocols and Support</a> »</li> </ul> </div> <div class="sphinxsidebar"> <div class="sphinxsidebarwrapper"> <h3><a href="../contents.html">Table Of Contents</a></h3> <ul> <li><a class="reference internal" href="#">smtpd – Sample SMTP Servers</a><ul> <li><a class="reference internal" href="#smtpserver">SMTPServer</a></li> <li><a class="reference internal" href="#debuggingserver">DebuggingServer</a></li> <li><a class="reference internal" href="#pureproxy">PureProxy</a></li> <li><a class="reference internal" href="#mailmanproxy">MailmanProxy</a></li> </ul> </li> </ul> <h4>Previous topic</h4> <p class="topless"><a href="../SimpleXMLRPCServer/index.html" title="previous chapter">SimpleXMLRPCServer – Implements an XML-RPC server.</a></p> <h4>Next topic</h4> <p class="topless"><a href="../smtplib/index.html" title="next chapter">smtplib – Simple Mail Transfer Protocol client</a></p> <h3>This Page</h3> <ul class="this-page-menu"> <li><a href="../_sources/smtpd/index.txt" rel="nofollow">Show Source</a></li> </ul> <div id="searchbox" style="display: none"> <h3>Quick search</h3> <form class="search" action="../search.html" method="get"> <input type="text" name="q" size="18" /> <input type="submit" value="Go" /> <input type="hidden" name="check_keywords" value="yes" /> <input type="hidden" name="area" value="default" /> </form> <p class="searchtip" style="font-size: 90%"> Enter search terms or a module, class or function name. </p> </div> <script type="text/javascript">$('#searchbox').show(0);</script> </div> </div> <div class="document"> <div class="documentwrapper"> <div class="bodywrapper"> <div class="body"> <div class="section" id="module-smtpd"> <span id="smtpd-sample-smtp-servers"></span><h1>smtpd – Sample SMTP Servers<a class="headerlink" href="#module-smtpd" title="Permalink to this headline">¶</a></h1> <table class="docutils field-list" frame="void" rules="none"> <col class="field-name" /> <col class="field-body" /> <tbody valign="top"> <tr class="field"><th class="field-name">Purpose:</th><td class="field-body">Includes classes for implementing SMTP servers.</td> </tr> <tr class="field"><th class="field-name">Python Version:</th><td class="field-body">2.1 and later</td> </tr> </tbody> </table> <p>The <a class="reference internal" href="#module-smtpd" title="smtpd: Includes classes for implementing SMTP servers."><tt class="xref py py-mod docutils literal"><span class="pre">smtpd</span></tt></a> module includes classes for building simple mail transport protocol servers. It is the server-side of the protocol used by <a class="reference internal" href="../smtplib/index.html#module-smtplib" title="smtplib: Simple mail transfer protocol client."><tt class="xref py py-mod docutils literal"><span class="pre">smtplib</span></tt></a>.</p> <div class="section" id="smtpserver"> <h2>SMTPServer<a class="headerlink" href="#smtpserver" title="Permalink to this headline">¶</a></h2> <p>The base class for all of the provided example servers is <tt class="xref py py-class docutils literal"><span class="pre">SMTPServer</span></tt>. It handles communicating with the client, receiving the data, and provides a convenient hook to override to handle the message once it is fully available.</p> <p>The constructor arguments are the local address to listen for connections and the remote address for proxying. The method <tt class="xref py py-func docutils literal"><span class="pre">process_message()</span></tt> is provided as a hook to be overridden by your derived class. It is called when the message is completely received, and given these arguments:</p> <p>peer</p> <blockquote> The client’s address, a tuple containing IP and incoming port.</blockquote> <p>mailfrom</p> <blockquote> The “from” information out of the message envelope, given to the server by the client when the message is delivered. This does not necessarily match the <tt class="docutils literal"><span class="pre">From</span></tt> header in all cases.</blockquote> <p>rcpttos</p> <blockquote> The list of recipients from the message envelope. Again, this does not always match the <tt class="docutils literal"><span class="pre">To</span></tt> header, especially if someone is blind carbon copied.</blockquote> <p>data</p> <blockquote> The full <span class="target" id="index-0"></span><a class="rfc reference external" href="http://tools.ietf.org/html/rfc2822.html"><strong>RFC 2822</strong></a> message body.</blockquote> <p>Since the default implementation of <tt class="xref py py-func docutils literal"><span class="pre">process_message()</span></tt> raises <a class="reference internal" href="../exceptions/index.html#exceptions-notimplementederror"><em>NotImplementedError</em></a>, to demonstrate using <tt class="xref py py-class docutils literal"><span class="pre">SMTPServer</span></tt> we need to create a subclass and provide a useful implementation. This first example defines a server that prints information about the messages it receives.</p> <div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">smtpd</span> <span class="kn">import</span> <span class="nn">asyncore</span> <span class="k">class</span> <span class="nc">CustomSMTPServer</span><span class="p">(</span><span class="n">smtpd</span><span class="o">.</span><span class="n">SMTPServer</span><span class="p">):</span> <span class="k">def</span> <span class="nf">process_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">peer</span><span class="p">,</span> <span class="n">mailfrom</span><span class="p">,</span> <span class="n">rcpttos</span><span class="p">,</span> <span class="n">data</span><span class="p">):</span> <span class="k">print</span> <span class="s">'Receiving message from:'</span><span class="p">,</span> <span class="n">peer</span> <span class="k">print</span> <span class="s">'Message addressed from:'</span><span class="p">,</span> <span class="n">mailfrom</span> <span class="k">print</span> <span class="s">'Message addressed to :'</span><span class="p">,</span> <span class="n">rcpttos</span> <span class="k">print</span> <span class="s">'Message length :'</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="k">return</span> <span class="n">server</span> <span class="o">=</span> <span class="n">CustomSMTPServer</span><span class="p">((</span><span class="s">'127.0.0.1'</span><span class="p">,</span> <span class="mi">1025</span><span class="p">),</span> <span class="bp">None</span><span class="p">)</span> <span class="n">asyncore</span><span class="o">.</span><span class="n">loop</span><span class="p">()</span> </pre></div> </div> <p><tt class="xref py py-class docutils literal"><span class="pre">SMTPServer</span></tt> uses <a class="reference internal" href="../asyncore/index.html#module-asyncore" title="asyncore: Asynchronous I/O handler"><tt class="xref py py-mod docutils literal"><span class="pre">asyncore</span></tt></a>, so to run the server we call <tt class="docutils literal"><span class="pre">asyncore.loop()</span></tt>.</p> <p>Now, we need a client to send data. By adapting one of the examples from the <a class="reference internal" href="../smtplib/index.html#module-smtplib" title="smtplib: Simple mail transfer protocol client."><tt class="xref py py-mod docutils literal"><span class="pre">smtplib</span></tt></a> page, we can set up a client to send data to our test server running locally on port 1025.</p> <div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">smtplib</span> <span class="kn">import</span> <span class="nn">email.utils</span> <span class="kn">from</span> <span class="nn">email.mime.text</span> <span class="kn">import</span> <span class="n">MIMEText</span> <span class="c"># Create the message</span> <span class="n">msg</span> <span class="o">=</span> <span class="n">MIMEText</span><span class="p">(</span><span class="s">'This is the body of the message.'</span><span class="p">)</span> <span class="n">msg</span><span class="p">[</span><span class="s">'To'</span><span class="p">]</span> <span class="o">=</span> <span class="n">email</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">formataddr</span><span class="p">((</span><span class="s">'Recipient'</span><span class="p">,</span> <span class="s">'recipient@example.com'</span><span class="p">))</span> <span class="n">msg</span><span class="p">[</span><span class="s">'From'</span><span class="p">]</span> <span class="o">=</span> <span class="n">email</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">formataddr</span><span class="p">((</span><span class="s">'Author'</span><span class="p">,</span> <span class="s">'author@example.com'</span><span class="p">))</span> <span class="n">msg</span><span class="p">[</span><span class="s">'Subject'</span><span class="p">]</span> <span class="o">=</span> <span class="s">'Simple test message'</span> <span class="n">server</span> <span class="o">=</span> <span class="n">smtplib</span><span class="o">.</span><span class="n">SMTP</span><span class="p">(</span><span class="s">'127.0.0.1'</span><span class="p">,</span> <span class="mi">1025</span><span class="p">)</span> <span class="n">server</span><span class="o">.</span><span class="n">set_debuglevel</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span> <span class="c"># show communication with the server</span> <span class="k">try</span><span class="p">:</span> <span class="n">server</span><span class="o">.</span><span class="n">sendmail</span><span class="p">(</span><span class="s">'author@example.com'</span><span class="p">,</span> <span class="p">[</span><span class="s">'recipient@example.com'</span><span class="p">],</span> <span class="n">msg</span><span class="o">.</span><span class="n">as_string</span><span class="p">())</span> <span class="k">finally</span><span class="p">:</span> <span class="n">server</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span> </pre></div> </div> <p>Now if we run <tt class="docutils literal"><span class="pre">smtpd_custom.py</span></tt> in one terminal, and <tt class="docutils literal"><span class="pre">smtpd_senddata.py</span></tt> in another, we should see:</p> <div class="highlight-python"><pre>$ python smtpd_senddata.py send: 'ehlo farnsworth.local\r\n' reply: '502 Error: command "EHLO" not implemented\r\n' reply: retcode (502); Msg: Error: command "EHLO" not implemented send: 'helo farnsworth.local\r\n' reply: '250 farnsworth.local\r\n' reply: retcode (250); Msg: farnsworth.local send: 'mail FROM:<author@example.com>\r\n' reply: '250 Ok\r\n' reply: retcode (250); Msg: Ok send: 'rcpt TO:<recipient@example.com>\r\n' reply: '250 Ok\r\n' reply: retcode (250); Msg: Ok send: 'data\r\n' reply: '354 End data with <CR><LF>.<CR><LF>\r\n' reply: retcode (354); Msg: End data with <CR><LF>.<CR><LF> data: (354, 'End data with <CR><LF>.<CR><LF>') send: 'Content-Type: text/plain; charset="us-ascii"\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: 7bit\r\nTo: Recipient <recipient@example.com>\r\nFrom: Author <author@example.com>\r\nSubject: Simple test message\r\n\r\nThis is the body of the message.\r\n.\r\n' reply: '250 Ok\r\n' reply: retcode (250); Msg: Ok data: (250, 'Ok') send: 'quit\r\n' reply: '221 Bye\r\n' reply: retcode (221); Msg: Bye</pre> </div> <p>and</p> <div class="highlight-python"><pre>$ python smtpd_custom.py Receiving message from: ('127.0.0.1', 58541) Message addressed from: author@example.com Message addressed to : ['recipient@example.com'] Message length : 229</pre> </div> <p>The port number for the incoming message will vary each time. Notice that the <em>rcpttos</em> argument is a list of values and <em>mailfrom</em> is a single string.</p> <div class="admonition note"> <p class="first admonition-title">Note</p> <p class="last">To stop the server, press <tt class="docutils literal"><span class="pre">Ctrl-C</span></tt>.</p> </div> </div> <div class="section" id="debuggingserver"> <h2>DebuggingServer<a class="headerlink" href="#debuggingserver" title="Permalink to this headline">¶</a></h2> <p>The example above shows the arguments to <tt class="xref py py-func docutils literal"><span class="pre">process_message()</span></tt>, but <a class="reference internal" href="#module-smtpd" title="smtpd: Includes classes for implementing SMTP servers."><tt class="xref py py-mod docutils literal"><span class="pre">smtpd</span></tt></a> also includes a server specifically designed for more complete debugging, called <tt class="xref py py-class docutils literal"><span class="pre">DebuggingServer</span></tt>. It prints the entire incoming message to stdout and then stops processing (it does not proxy the message to a real mail server).</p> <div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">smtpd</span> <span class="kn">import</span> <span class="nn">asyncore</span> <span class="n">server</span> <span class="o">=</span> <span class="n">smtpd</span><span class="o">.</span><span class="n">DebuggingServer</span><span class="p">((</span><span class="s">'127.0.0.1'</span><span class="p">,</span> <span class="mi">1025</span><span class="p">),</span> <span class="bp">None</span><span class="p">)</span> <span class="n">asyncore</span><span class="o">.</span><span class="n">loop</span><span class="p">()</span> </pre></div> </div> <p>Using the <tt class="docutils literal"><span class="pre">smtpd_senddata.py</span></tt> client program from above, the output of the <tt class="xref py py-class docutils literal"><span class="pre">DebuggingServer</span></tt> is:</p> <div class="highlight-python"><pre>$ python smtpd_debug.py ---------- MESSAGE FOLLOWS ---------- Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit To: Recipient <recipient@example.com> From: Author <author@example.com> Subject: Simple test message X-Peer: 127.0.0.1 This is the body of the message. ------------ END MESSAGE ------------</pre> </div> </div> <div class="section" id="pureproxy"> <h2>PureProxy<a class="headerlink" href="#pureproxy" title="Permalink to this headline">¶</a></h2> <p>The <tt class="xref py py-class docutils literal"><span class="pre">PureProxy</span></tt> class implements a straightforward proxy server. Incoming messages are forwarded upstream to the server given as argument to the constructor.</p> <div class="admonition warning"> <p class="first admonition-title">Warning</p> <p class="last">The stdlib docs say, “running this has a good chance to make you into an open relay, so please be careful.”</p> </div> <p>Setting up the proxy server is just as easy as the debug server:</p> <div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">smtpd</span> <span class="kn">import</span> <span class="nn">asyncore</span> <span class="n">server</span> <span class="o">=</span> <span class="n">smtpd</span><span class="o">.</span><span class="n">PureProxy</span><span class="p">((</span><span class="s">'127.0.0.1'</span><span class="p">,</span> <span class="mi">1025</span><span class="p">),</span> <span class="p">(</span><span class="s">'mail'</span><span class="p">,</span> <span class="mi">25</span><span class="p">))</span> <span class="n">asyncore</span><span class="o">.</span><span class="n">loop</span><span class="p">()</span> </pre></div> </div> <p>It prints no output, though, so to verify that it is working we need to look at the mail server logs.</p> <div class="highlight-python"><pre>Oct 19 19:16:34 homer sendmail[6785]: m9JNGXJb006785: from=<author@example.com>, size=248, class=0, nrcpts=1, msgid=<200810192316.m9JNGXJb006785@homer.example.com>, proto=ESMTP, daemon=MTA, relay=[192.168.1.17]</pre> </div> </div> <div class="section" id="mailmanproxy"> <h2>MailmanProxy<a class="headerlink" href="#mailmanproxy" title="Permalink to this headline">¶</a></h2> <p><a class="reference internal" href="#module-smtpd" title="smtpd: Includes classes for implementing SMTP servers."><tt class="xref py py-mod docutils literal"><span class="pre">smtpd</span></tt></a> also includes a special proxy that acts as a front-end for <a class="reference external" href="http://www.gnu.org/software/mailman/index.html">Mailman</a>. If the local Mailman configuration recognizes the address, it is handled directly. Otherwise the message is delivered to the proxy.</p> <div class="admonition-see-also admonition seealso"> <p class="first admonition-title">See also</p> <dl class="last docutils"> <dt><a class="reference external" href="http://docs.python.org/lib/module-smtpd.html">smtpd</a></dt> <dd>Standard library documentation for this module.</dd> <dt><a class="reference internal" href="../smtplib/index.html#module-smtplib" title="smtplib: Simple mail transfer protocol client."><tt class="xref py py-mod docutils literal"><span class="pre">smtplib</span></tt></a></dt> <dd>Provides a client interface.</dd> <dt><tt class="xref py py-mod docutils literal"><span class="pre">email</span></tt></dt> <dd>Parses email messages.</dd> <dt><a class="reference internal" href="../asyncore/index.html#module-asyncore" title="asyncore: Asynchronous I/O handler"><tt class="xref py py-mod docutils literal"><span class="pre">asyncore</span></tt></a></dt> <dd>Base module for writing asynchronous servers.</dd> <dt><span class="target" id="index-1"></span><a class="rfc reference external" href="http://tools.ietf.org/html/rfc2822.html"><strong>RFC 2822</strong></a></dt> <dd>Defines the email message format.</dd> <dt><a class="reference external" href="http://www.gnu.org/software/mailman/index.html">GNU Mailman mailing list software</a></dt> <dd>An excellent example of Python software that works with email messages.</dd> </dl> </div> </div> </div> </div> </div> </div> <div class="clearer"></div> </div> <div class="related"> <h3>Navigation</h3> <ul> <li class="right" style="margin-right: 10px"> <a href="../genindex.html" title="General Index" >index</a></li> <li class="right" > <a href="../py-modindex.html" title="Python Module Index" >modules</a> |</li> <li class="right" > <a href="../smtplib/index.html" title="smtplib – Simple Mail Transfer Protocol client" >next</a> |</li> <li class="right" > <a href="../SimpleXMLRPCServer/index.html" title="SimpleXMLRPCServer – Implements an XML-RPC server." >previous</a> |</li> <li><a href="../contents.html">PyMOTW</a> »</li> <li><a href="../internet_protocols.html" >Internet Protocols and Support</a> »</li> </ul> </div> <div class="footer"> © Copyright Doug Hellmann. Last updated on Oct 24, 2010. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>. <br/><a href="http://creativecommons.org/licenses/by-nc-sa/3.0/us/" rel="license"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-nc-sa/3.0/us/88x31.png"/></a> </div> </body> </html>