[code.view]

[top] / python / PyMOTW / docs / smtpd / index.html


<!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 &mdash; 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> &raquo;</li>
          <li><a href="../internet_protocols.html" accesskey="U">Internet Protocols and Support</a> &raquo;</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 &#8211; 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 &#8211; Implements an XML-RPC server.</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="../smtplib/index.html"
                        title="next chapter">smtplib &#8211; 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 &#8211; 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&#8217;s address, a tuple containing IP and incoming port.</blockquote>
<p>mailfrom</p>
<blockquote>
The &#8220;from&#8221; 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">&#39;Receiving message from:&#39;</span><span class="p">,</span> <span class="n">peer</span>
        <span class="k">print</span> <span class="s">&#39;Message addressed from:&#39;</span><span class="p">,</span> <span class="n">mailfrom</span>
        <span class="k">print</span> <span class="s">&#39;Message addressed to  :&#39;</span><span class="p">,</span> <span class="n">rcpttos</span>
        <span class="k">print</span> <span class="s">&#39;Message length        :&#39;</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">&#39;127.0.0.1&#39;</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">&#39;This is the body of the message.&#39;</span><span class="p">)</span>
<span class="n">msg</span><span class="p">[</span><span class="s">&#39;To&#39;</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">&#39;Recipient&#39;</span><span class="p">,</span> <span class="s">&#39;recipient@example.com&#39;</span><span class="p">))</span>
<span class="n">msg</span><span class="p">[</span><span class="s">&#39;From&#39;</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">&#39;Author&#39;</span><span class="p">,</span> <span class="s">&#39;author@example.com&#39;</span><span class="p">))</span>
<span class="n">msg</span><span class="p">[</span><span class="s">&#39;Subject&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;Simple test message&#39;</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">&#39;127.0.0.1&#39;</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">&#39;author@example.com&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s">&#39;recipient@example.com&#39;</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:&lt;author@example.com&gt;\r\n'
reply: '250 Ok\r\n'
reply: retcode (250); Msg: Ok
send: 'rcpt TO:&lt;recipient@example.com&gt;\r\n'
reply: '250 Ok\r\n'
reply: retcode (250); Msg: Ok
send: 'data\r\n'
reply: '354 End data with &lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;\r\n'
reply: retcode (354); Msg: End data with &lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;
data: (354, 'End data with &lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;')
send: 'Content-Type: text/plain; charset="us-ascii"\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: 7bit\r\nTo: Recipient &lt;recipient@example.com&gt;\r\nFrom: Author &lt;author@example.com&gt;\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">&#39;127.0.0.1&#39;</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 &lt;recipient@example.com&gt;
From: Author &lt;author@example.com&gt;
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, &#8220;running this has a good chance to make you
into an open relay, so please be careful.&#8221;</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">&#39;127.0.0.1&#39;</span><span class="p">,</span> <span class="mi">1025</span><span class="p">),</span> <span class="p">(</span><span class="s">&#39;mail&#39;</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=&lt;author@example.com&gt;, size=248, class=0, nrcpts=1, msgid=&lt;200810192316.m9JNGXJb006785@homer.example.com&gt;, 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> &raquo;</li>
          <li><a href="../internet_protocols.html" >Internet Protocols and Support</a> &raquo;</li> 
      </ul>
    </div>
    <div class="footer">
      &copy; 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>

[top] / python / PyMOTW / docs / smtpd / index.html

contact | logmethods.com