File: //usr/share/doc/python3-aiosmtpd/html/smtp.html
<!DOCTYPE html>
<html class="writer-html5" lang="en" data-content_root="./">
<head>
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>The SMTP Module — aiosmtpd 1.4.4.post2 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="_static/css/theme.css?v=86f27845" />
<link rel="stylesheet" type="text/css" href="_static/aiosmtpd.css?v=4cc6bf70" />
<script src="_static/jquery.js?v=8dae8fb0"></script>
<script src="_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
<script src="_static/documentation_options.js?v=ad49bbf5"></script>
<script src="_static/doctools.js?v=888ff710"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/js/theme.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="The LMTP class" href="lmtp.html" />
<link rel="prev" title="Programmatic usage" href="controller.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="index.html" class="icon icon-home">
aiosmtpd
</a>
<div class="version">
1.4.4.post2
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="intro.html">Introduction</a></li>
<li class="toctree-l1"><a class="reference internal" href="concepts.html">Concepts</a></li>
<li class="toctree-l1"><a class="reference internal" href="cli.html">Command line usage</a></li>
<li class="toctree-l1"><a class="reference internal" href="controller.html">Programmatic usage</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">The SMTP Module</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#subclassing">Subclassing</a></li>
<li class="toctree-l2"><a class="reference internal" href="#server-hooks">Server hooks</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#ehlo_hook"><code class="docutils literal notranslate"><span class="pre">ehlo_hook()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#rset_hook"><code class="docutils literal notranslate"><span class="pre">rset_hook()</span></code></a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#module-aiosmtpd.smtp">aiosmtpd.smtp</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#aiosmtpd.smtp.AuthenticatorType"><code class="docutils literal notranslate"><span class="pre">AuthenticatorType</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#aiosmtpd.smtp.auth_mechanism"><code class="docutils literal notranslate"><span class="pre">auth_mechanism()</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#aiosmtpd.smtp.AuthResult"><code class="docutils literal notranslate"><span class="pre">AuthResult</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#aiosmtpd.smtp.LoginPassword"><code class="docutils literal notranslate"><span class="pre">LoginPassword</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="#aiosmtpd.smtp.SMTP"><code class="docutils literal notranslate"><span class="pre">SMTP</span></code></a><ul>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.handler"><code class="docutils literal notranslate"><span class="pre">SMTP.handler</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.decode_data"><code class="docutils literal notranslate"><span class="pre">SMTP.decode_data</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.ident"><code class="docutils literal notranslate"><span class="pre">SMTP.ident</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.timeout"><code class="docutils literal notranslate"><span class="pre">SMTP.timeout</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.auth_required"><code class="docutils literal notranslate"><span class="pre">SMTP.auth_required</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.auth_require_tls"><code class="docutils literal notranslate"><span class="pre">SMTP.auth_require_tls</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.auth_exclude_mechanism"><code class="docutils literal notranslate"><span class="pre">SMTP.auth_exclude_mechanism</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.auth_callback"><code class="docutils literal notranslate"><span class="pre">SMTP.auth_callback</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.authenticator"><code class="docutils literal notranslate"><span class="pre">SMTP.authenticator</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.command_call_limit"><code class="docutils literal notranslate"><span class="pre">SMTP.command_call_limit</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.proxy_protocol_timeout"><code class="docutils literal notranslate"><span class="pre">SMTP.proxy_protocol_timeout</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.line_length_limit"><code class="docutils literal notranslate"><span class="pre">SMTP.line_length_limit</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.local_part_limit"><code class="docutils literal notranslate"><span class="pre">SMTP.local_part_limit</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.AuthLoginUsernameChallenge"><code class="docutils literal notranslate"><span class="pre">SMTP.AuthLoginUsernameChallenge</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.AuthLoginPasswordChallenge"><code class="docutils literal notranslate"><span class="pre">SMTP.AuthLoginPasswordChallenge</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.event_handler"><code class="docutils literal notranslate"><span class="pre">SMTP.event_handler</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.data_size_limit"><code class="docutils literal notranslate"><span class="pre">SMTP.data_size_limit</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.enable_SMTPUTF8"><code class="docutils literal notranslate"><span class="pre">SMTP.enable_SMTPUTF8</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.hostname"><code class="docutils literal notranslate"><span class="pre">SMTP.hostname</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.tls_context"><code class="docutils literal notranslate"><span class="pre">SMTP.tls_context</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.require_starttls"><code class="docutils literal notranslate"><span class="pre">SMTP.require_starttls</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.session"><code class="docutils literal notranslate"><span class="pre">SMTP.session</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.envelope"><code class="docutils literal notranslate"><span class="pre">SMTP.envelope</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.transport"><code class="docutils literal notranslate"><span class="pre">SMTP.transport</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.loop"><code class="docutils literal notranslate"><span class="pre">SMTP.loop</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.authenticated"><code class="docutils literal notranslate"><span class="pre">SMTP.authenticated</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP._create_session"><code class="docutils literal notranslate"><span class="pre">SMTP._create_session()</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP._create_envelope"><code class="docutils literal notranslate"><span class="pre">SMTP._create_envelope()</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.push"><code class="docutils literal notranslate"><span class="pre">SMTP.push()</span></code></a></li>
<li class="toctree-l4"><a class="reference internal" href="#aiosmtpd.smtp.SMTP.challenge_auth"><code class="docutils literal notranslate"><span class="pre">SMTP.challenge_auth()</span></code></a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#enabling-starttls">Enabling STARTTLS</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="lmtp.html">The LMTP class</a></li>
<li class="toctree-l1"><a class="reference internal" href="handlers.html">Handlers</a></li>
<li class="toctree-l1"><a class="reference internal" href="auth.html">Authentication System</a></li>
<li class="toctree-l1"><a class="reference internal" href="proxyprotocol.html">PROXY Protocol Support</a></li>
<li class="toctree-l1"><a class="reference internal" href="migrating.html">Migrating from smtpd to aiosmtpd</a></li>
<li class="toctree-l1"><a class="reference internal" href="testing.html">Testing</a></li>
<li class="toctree-l1"><a class="reference internal" href="manpage.html">aiosmtpd</a></li>
<li class="toctree-l1"><a class="reference internal" href="NEWS.html">NEWS for aiosmtpd</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="index.html">aiosmtpd</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item active">The SMTP Module</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/smtp.rst.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="the-smtp-module">
<span id="smtp"></span><h1>The SMTP Module<a class="headerlink" href="#the-smtp-module" title="Link to this heading"></a></h1>
<p>At the heart of this module is the <code class="docutils literal notranslate"><span class="pre">SMTP</span></code> class in the <code class="docutils literal notranslate"><span class="pre">aiosmtpd.smtp</span></code> module.
This class implements the <span class="target" id="index-0"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc5321.html"><strong>RFC 5321</strong></a> Simple Mail Transport Protocol.
Often you won’t run an <code class="docutils literal notranslate"><span class="pre">SMTP</span></code> instance directly,
but instead will use a <a class="reference internal" href="controller.html#controller"><span class="std std-ref">Controller</span></a> instance to run the server in a subthread.</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">aiosmtpd.controller</span> <span class="kn">import</span> <span class="n">Controller</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">SMTP</span></code> class is itself a subclass of <a class="reference external" href="https://docs.python.org/3.6/library/asyncio-stream.html#streamreaderprotocol"><code class="docutils literal notranslate"><span class="pre">StreamReaderProtocol</span></code></a></p>
<section id="subclassing">
<span id="subclass"></span><h2>Subclassing<a class="headerlink" href="#subclassing" title="Link to this heading"></a></h2>
<p>While behavior for common SMTP commands can be specified using <a class="reference internal" href="handlers.html#handlers"><span class="std std-ref">handlers</span></a>, more complex specializations such as adding custom SMTP commands
require subclassing the <code class="docutils literal notranslate"><span class="pre">SMTP</span></code> class.</p>
<p>For example, let’s say you wanted to add a new SMTP command called <code class="docutils literal notranslate"><span class="pre">PING</span></code>.
All methods implementing <code class="docutils literal notranslate"><span class="pre">SMTP</span></code> commands are prefixed with <code class="docutils literal notranslate"><span class="pre">smtp_</span></code>; they
must also be coroutines. Here’s how you could implement this use case:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">asyncio</span>
<span class="gp">>>> </span><span class="kn">from</span> <span class="nn">aiosmtpd.smtp</span> <span class="kn">import</span> <span class="n">SMTP</span> <span class="k">as</span> <span class="n">Server</span><span class="p">,</span> <span class="n">syntax</span>
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">MyServer</span><span class="p">(</span><span class="n">Server</span><span class="p">):</span>
<span class="gp">... </span> <span class="nd">@syntax</span><span class="p">(</span><span class="s1">'PING [ignored]'</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">async</span> <span class="k">def</span> <span class="nf">smtp_PING</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">push</span><span class="p">(</span><span class="s1">'259 Pong'</span><span class="p">)</span>
</pre></div>
</div>
<p>Now let’s run this server in a controller:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">aiosmtpd.handlers</span> <span class="kn">import</span> <span class="n">Sink</span>
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">MyController</span><span class="p">(</span><span class="n">Controller</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">factory</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">return</span> <span class="n">MyServer</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">handler</span><span class="p">)</span>
<span class="gp">>>> </span><span class="n">controller</span> <span class="o">=</span> <span class="n">MyController</span><span class="p">(</span><span class="n">Sink</span><span class="p">())</span>
<span class="gp">>>> </span><span class="n">controller</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
</pre></div>
</div>
<p>We can now connect to this server with an <code class="docutils literal notranslate"><span class="pre">SMTP</span></code> client.</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">smtplib</span> <span class="kn">import</span> <span class="n">SMTP</span> <span class="k">as</span> <span class="n">Client</span>
<span class="gp">>>> </span><span class="n">client</span> <span class="o">=</span> <span class="n">Client</span><span class="p">(</span><span class="n">controller</span><span class="o">.</span><span class="n">hostname</span><span class="p">,</span> <span class="n">controller</span><span class="o">.</span><span class="n">port</span><span class="p">)</span>
</pre></div>
</div>
<p>Let’s ping the server. Since the <code class="docutils literal notranslate"><span class="pre">PING</span></code> command isn’t an official <code class="docutils literal notranslate"><span class="pre">SMTP</span></code>
command, we have to use the lower level interface to talk to it.</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">code</span><span class="p">,</span> <span class="n">message</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">docmd</span><span class="p">(</span><span class="s1">'PING'</span><span class="p">)</span>
<span class="gp">>>> </span><span class="n">code</span>
<span class="go">259</span>
<span class="gp">>>> </span><span class="n">message</span>
<span class="go">b'Pong'</span>
</pre></div>
</div>
<p>Because we prefixed the <code class="docutils literal notranslate"><span class="pre">smtp_PING()</span></code> method with the <code class="docutils literal notranslate"><span class="pre">@syntax()</span></code>
decorator, the command shows up in the <code class="docutils literal notranslate"><span class="pre">HELP</span></code> output.</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">client</span><span class="o">.</span><span class="n">help</span><span class="p">()</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">'utf-8'</span><span class="p">))</span>
<span class="go">Supported commands: AUTH DATA EHLO HELO HELP MAIL NOOP PING QUIT RCPT RSET VRFY</span>
</pre></div>
</div>
<p>And we can get more detailed help on the new command.</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">client</span><span class="o">.</span><span class="n">help</span><span class="p">(</span><span class="s1">'PING'</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">'utf-8'</span><span class="p">))</span>
<span class="go">Syntax: PING [ignored]</span>
</pre></div>
</div>
<p>Don’t forget to <code class="docutils literal notranslate"><span class="pre">stop()</span></code> the controller when you’re done.</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">controller</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
</pre></div>
</div>
</section>
<section id="server-hooks">
<h2>Server hooks<a class="headerlink" href="#server-hooks" title="Link to this heading"></a></h2>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>These methods are deprecated. See <a class="reference internal" href="handlers.html#hooks"><span class="std std-ref">handler hooks</span></a>
instead.</p>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">SMTP</span></code> server class also implements some hooks which your subclass can
override to provide additional responses.</p>
<dl class="py function">
<dt class="sig sig-object py" id="ehlo_hook">
<span class="sig-name descname"><span class="pre">ehlo_hook</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#ehlo_hook" title="Link to this definition"></a></dt>
<dd><p>This hook makes it possible for subclasses to return additional <code class="docutils literal notranslate"><span class="pre">EHLO</span></code>
responses. This method, called <em>asynchronously</em> and taking no arguments,
can do whatever it wants, including (most commonly) pushing new
<code class="docutils literal notranslate"><span class="pre">250-<command></span></code> responses to the client. This hook is called just
before the standard <code class="docutils literal notranslate"><span class="pre">250</span> <span class="pre">HELP</span></code> which ends the <code class="docutils literal notranslate"><span class="pre">EHLO</span></code> response from the
server.</p>
<div class="deprecated">
<p><span class="versionmodified deprecated">Deprecated since version 1.2.</span></p>
</div>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="rset_hook">
<span class="sig-name descname"><span class="pre">rset_hook</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#rset_hook" title="Link to this definition"></a></dt>
<dd><p>This hook makes it possible to return additional <code class="docutils literal notranslate"><span class="pre">RSET</span></code> responses. This
method, called <em>asynchronously</em> and taking no arguments, is called just
before the standard <code class="docutils literal notranslate"><span class="pre">250</span> <span class="pre">OK</span></code> which ends the <code class="docutils literal notranslate"><span class="pre">RSET</span></code> response from the
server.</p>
<div class="deprecated">
<p><span class="versionmodified deprecated">Deprecated since version 1.2.</span></p>
</div>
</dd></dl>
</section>
<section id="module-aiosmtpd.smtp">
<span id="aiosmtpd-smtp"></span><span id="smtp-api"></span><h2>aiosmtpd.smtp<a class="headerlink" href="#module-aiosmtpd.smtp" title="Link to this heading"></a></h2>
<dl class="py data">
<dt class="sig sig-object py" id="aiosmtpd.smtp.AuthenticatorType">
<span class="sig-prename descclassname"><span class="pre">aiosmtpd.smtp.</span></span><span class="sig-name descname"><span class="pre">AuthenticatorType</span></span><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">Callable[[SMTP,</span> <span class="pre">Session,</span> <span class="pre">Envelope,</span> <span class="pre">str,</span> <span class="pre">Any],</span> <span class="pre">AuthResult]</span></em><a class="headerlink" href="#aiosmtpd.smtp.AuthenticatorType" title="Link to this definition"></a></dt>
<dd></dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="aiosmtpd.smtp.auth_mechanism">
<span class="sig-prename descclassname"><span class="pre">@</span></span><span class="sig-prename descclassname"><span class="pre">aiosmtpd.smtp.</span></span><span class="sig-name descname"><span class="pre">auth_mechanism</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">actual_name</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#aiosmtpd.smtp.auth_mechanism" title="Link to this definition"></a></dt>
<dd><dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>actual_name</strong> (<em>str</em>) – Name of the AUTH Mechanism implemented by the method.
See <a class="reference internal" href="auth.html#authmech"><span class="std std-ref">AUTH Mechanism Hooks</span></a> for more info.</p>
</dd>
</dl>
<p>This decorator specifies the actual name of the AUTH Mechanism implemented
by the method being decorated, regardless of the method’s name.</p>
<div class="admonition important">
<p class="admonition-title">Important</p>
<p>The decorated method’s name MUST still start with <code class="docutils literal notranslate"><span class="pre">auth_</span></code></p>
</div>
</dd></dl>
<dl class="py class">
<dt class="sig sig-object py" id="aiosmtpd.smtp.AuthResult">
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">aiosmtpd.smtp.</span></span><span class="sig-name descname"><span class="pre">AuthResult</span></span><a class="headerlink" href="#aiosmtpd.smtp.AuthResult" title="Link to this definition"></a></dt>
<dd><p>Contains the result of the Authentication Procedure.</p>
<p>For more info, please see <a class="reference internal" href="auth.html#AuthResult" title="AuthResult"><code class="xref py py-class docutils literal notranslate"><span class="pre">AuthResult</span></code></a></p>
</dd></dl>
<dl class="py class">
<dt class="sig sig-object py" id="aiosmtpd.smtp.LoginPassword">
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">aiosmtpd.smtp.</span></span><span class="sig-name descname"><span class="pre">LoginPassword</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">login</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">bytes</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">password</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">bytes</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#aiosmtpd.smtp.LoginPassword" title="Link to this definition"></a></dt>
<dd><p>A subclass of <code class="xref py py-class docutils literal notranslate"><span class="pre">typing.NamedTuple</span></code> that holds the Authentication Data for the
built-in <code class="docutils literal notranslate"><span class="pre">LOGIN</span></code> and <code class="docutils literal notranslate"><span class="pre">PLAIN</span></code> AUTH Mechanisms.</p>
<p>It is to be used for Authentication purposes by <a class="reference internal" href="auth.html#Authenticator" title="Authenticator"><code class="xref py py-func docutils literal notranslate"><span class="pre">Authenticator()</span></code></a></p>
<p>For more information, please refer to the <a class="reference internal" href="auth.html#auth"><span class="std std-ref">Authentication System</span></a> page.</p>
</dd></dl>
<dl class="py class">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP">
<em class="property"><span class="pre">class</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">aiosmtpd.smtp.</span></span><span class="sig-name descname"><span class="pre">SMTP</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">handler</span></span></em>, <em class="sig-param"><span class="o"><span class="pre">*</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">data_size_limit</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">33554432</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">enable_SMTPUTF8</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">decode_data</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">hostname</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">ident</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">tls_context</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">require_starttls</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">300</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">auth_required</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">auth_require_tls</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">auth_exclude_mechanism</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">auth_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">authenticator</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">command_call_limit</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">proxy_protocol_timeout</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">loop</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#aiosmtpd.smtp.SMTP" title="Link to this definition"></a></dt>
<dd><div class="line-block">
<div class="line"><br /></div>
<div class="line"><span class="parthead">Parameters</span></div>
</div>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.handler">
<span class="sig-name descname"><span class="pre">handler</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.handler" title="Link to this definition"></a></dt>
<dd><p>An instance of a <a class="reference internal" href="handlers.html#handlers"><span class="std std-ref">handler</span></a> class that optionally can implement
<a class="reference internal" href="handlers.html#hooks"><span class="std std-ref">Handler Hooks</span></a>.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py">
<span class="sig-name descname"><span class="pre">data_size_limit</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">int</span></em><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">33554432</span></em></dt>
<dd><p>The limit in number of bytes that is accepted for client SMTP commands.
It is returned to ESMTP clients in the <code class="docutils literal notranslate"><span class="pre">250-SIZE</span></code> response.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py">
<span class="sig-name descname"><span class="pre">enable_SMTPUTF8</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">bool</span></em><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">False</span></em></dt>
<dd><p>When <code class="docutils literal notranslate"><span class="pre">True</span></code>, causes the ESMTP <code class="docutils literal notranslate"><span class="pre">SMTPUTF8</span></code> option to be returned to the client,
and allows for UTF-8 content to be accepted, as defined in <span class="target" id="index-1"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc6531.html"><strong>RFC 6531</strong></a>.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.decode_data">
<span class="sig-name descname"><span class="pre">decode_data</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">bool</span></em><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">False</span></em><a class="headerlink" href="#aiosmtpd.smtp.SMTP.decode_data" title="Link to this definition"></a></dt>
<dd><p>When <code class="docutils literal notranslate"><span class="pre">True</span></code>, attempts to decode byte content in the <code class="docutils literal notranslate"><span class="pre">DATA</span></code> command,
assigning the string value to the <a class="reference internal" href="concepts.html#sessions-and-envelopes"><span class="std std-ref">envelope’s</span></a>
<code class="docutils literal notranslate"><span class="pre">content</span></code> attribute.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py">
<span class="sig-name descname"><span class="pre">hostname</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">str</span><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><span class="pre">None</span></em><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">None</span></em></dt>
<dd><p>The first part of the string returned in the <code class="docutils literal notranslate"><span class="pre">220</span></code> greeting response
given to clients when they first connect to the server.
If not given, the system’s fully-qualified domain name is used.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.ident">
<span class="sig-name descname"><span class="pre">ident</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">str</span><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><span class="pre">None</span></em><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">None</span></em><a class="headerlink" href="#aiosmtpd.smtp.SMTP.ident" title="Link to this definition"></a></dt>
<dd><p>The second part of the string returned in the <code class="docutils literal notranslate"><span class="pre">220</span></code> greeting response
that identifies the software name and version of the SMTP server
to the client.
If not given, a default Python SMTP ident is used.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py">
<span class="sig-name descname"><span class="pre">tls_context</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">ssl.SSLContext</span><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><span class="pre">None</span></em><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">None</span></em></dt>
<dd><p>An instance of <code class="xref py py-class docutils literal notranslate"><span class="pre">ssl.SSLContext</span></code>.
Providing this will enable support for <code class="docutils literal notranslate"><span class="pre">STARTTLS</span></code> ESMTP/LMTP option
as defined in <span class="target" id="index-2"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc3207.html"><strong>RFC 3207</strong></a>.</p>
<p>See <a class="reference internal" href="#tls"><span class="std std-ref">Enabling STARTTLS</span></a> for a more in-depth discussion on enabling <code class="docutils literal notranslate"><span class="pre">STARTTLS</span></code>.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py">
<span class="sig-name descname"><span class="pre">require_starttls</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">bool</span></em><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">False</span></em></dt>
<dd><p>If set to <code class="docutils literal notranslate"><span class="pre">True</span></code>,
then client must send <code class="docutils literal notranslate"><span class="pre">STARTTLS</span></code> before “restricted” ESMTP commands can be issued.</p>
<p>“Restricted” ESMTP commands are all commands not in the set
<code class="docutils literal notranslate"><span class="pre">{"NOOP",</span> <span class="pre">"EHLO",</span> <span class="pre">"STARTTLS",</span> <span class="pre">"QUIT"}</span></code></p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.timeout">
<span class="sig-name descname"><span class="pre">timeout</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">int</span><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><span class="pre">float</span></em><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">300</span></em><a class="headerlink" href="#aiosmtpd.smtp.SMTP.timeout" title="Link to this definition"></a></dt>
<dd><p>The number of seconds to wait between valid SMTP commands.
After this time the connection will be closed by the server.</p>
<p>The default is 300 seconds, as per <span class="target" id="index-3"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2821.html"><strong>RFC 2821</strong></a>.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.auth_required">
<span class="sig-name descname"><span class="pre">auth_required</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">bool</span></em><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">False</span></em><a class="headerlink" href="#aiosmtpd.smtp.SMTP.auth_required" title="Link to this definition"></a></dt>
<dd><p>Specifies whether SMTP Authentication is mandatory or not for the session.
This impacts some SMTP commands such as <code class="docutils literal notranslate"><span class="pre">HELP</span></code>, <code class="docutils literal notranslate"><span class="pre">MAIL</span> <span class="pre">FROM</span></code>, <code class="docutils literal notranslate"><span class="pre">RCPT</span> <span class="pre">TO</span></code>, and others.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.auth_require_tls">
<span class="sig-name descname"><span class="pre">auth_require_tls</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">bool</span></em><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">True</span></em><a class="headerlink" href="#aiosmtpd.smtp.SMTP.auth_require_tls" title="Link to this definition"></a></dt>
<dd><p>Specifies whether <code class="docutils literal notranslate"><span class="pre">STARTTLS</span></code> must be used before AUTH exchange or not.</p>
<p>If you set this to <code class="docutils literal notranslate"><span class="pre">False</span></code> then AUTH exchange can be done outside a TLS context,
but the class will warn you of security considerations.</p>
<p>Has no effect if <a class="reference internal" href="#aiosmtpd.smtp.SMTP.require_starttls" title="aiosmtpd.smtp.SMTP.require_starttls"><code class="xref py py-attr docutils literal notranslate"><span class="pre">require_starttls</span></code></a> is <code class="docutils literal notranslate"><span class="pre">True</span></code>.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.auth_exclude_mechanism">
<span class="sig-name descname"><span class="pre">auth_exclude_mechanism</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">Iterable</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">]</span></span><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><span class="pre">None</span></em><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">None</span></em><a class="headerlink" href="#aiosmtpd.smtp.SMTP.auth_exclude_mechanism" title="Link to this definition"></a></dt>
<dd><p>Specifies which AUTH mechanisms to NOT use.</p>
<p>This is the only way to completely disable the built-in AUTH mechanisms.</p>
<p>See <a class="reference internal" href="auth.html#auth"><span class="std std-ref">Authentication System</span></a> for a more in-depth discussion on AUTH mechanisms.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 1.2.2.</span></p>
</div>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.auth_callback">
<span class="sig-name descname"><span class="pre">auth_callback</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">Callable</span><span class="p"><span class="pre">[</span></span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">bytes</span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">bytes</span><span class="p"><span class="pre">]</span></span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">bool</span><span class="p"><span class="pre">]</span></span></em><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">login_always_fail</span></em><a class="headerlink" href="#aiosmtpd.smtp.SMTP.auth_callback" title="Link to this definition"></a></dt>
<dd><p>A function that accepts three arguments:
<code class="docutils literal notranslate"><span class="pre">mechanism:</span> <span class="pre">str</span></code>, <code class="docutils literal notranslate"><span class="pre">login:</span> <span class="pre">bytes</span></code>, and <code class="docutils literal notranslate"><span class="pre">password:</span> <span class="pre">bytes</span></code>.
Based on these args, the function must return a <code class="docutils literal notranslate"><span class="pre">bool</span></code>
that indicates whether the client’s authentication attempt
is accepted/successful or not.</p>
<div class="deprecated">
<p><span class="versionmodified deprecated">Deprecated since version 1.3: </span>Use <a class="reference internal" href="#aiosmtpd.smtp.SMTP.authenticator" title="aiosmtpd.smtp.SMTP.authenticator"><code class="xref py py-attr docutils literal notranslate"><span class="pre">authenticator</span></code></a> instead. This parameter <strong>will be removed in version 2.0</strong>.</p>
</div>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.authenticator">
<span class="sig-name descname"><span class="pre">authenticator</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">aiosmtpd.smtp.AuthenticatorType</span></em><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">None</span></em><a class="headerlink" href="#aiosmtpd.smtp.SMTP.authenticator" title="Link to this definition"></a></dt>
<dd><p>A function whose signature is identical to <code class="docutils literal notranslate"><span class="pre">aiosmtpd.smtp.AuthenticatorType</span></code>.</p>
<p>See <a class="reference internal" href="auth.html#Authenticator" title="Authenticator"><code class="xref py py-func docutils literal notranslate"><span class="pre">Authenticator()</span></code></a> for more information.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 1.3.</span></p>
</div>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.command_call_limit">
<span class="sig-name descname"><span class="pre">command_call_limit</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">int</span><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><span class="pre">Dict</span><span class="p"><span class="pre">[</span></span><span class="pre">str</span><span class="p"><span class="pre">,</span></span><span class="w"> </span><span class="pre">int</span><span class="p"><span class="pre">]</span></span><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><span class="pre">None</span></em><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">None</span></em><a class="headerlink" href="#aiosmtpd.smtp.SMTP.command_call_limit" title="Link to this definition"></a></dt>
<dd><p>If not <code class="docutils literal notranslate"><span class="pre">None</span></code> sets the maximum time a certain SMTP command can be invoked.
This is to prevent DoS due to malicious client connecting and never disconnecting,
due to continual sending of SMTP commands to prevent timeout.</p>
<p>The handling differs based on the type:</p>
<blockquote class="highlights">
<div><p>If <a class="reference internal" href="#aiosmtpd.smtp.SMTP.command_call_limit" title="aiosmtpd.smtp.SMTP.command_call_limit"><code class="xref py py-attr docutils literal notranslate"><span class="pre">command_call_limit</span></code></a> is of type <code class="docutils literal notranslate"><span class="pre">int</span></code>,
then the value is the call limit for ALL SMTP commands.</p>
<p>If <a class="reference internal" href="#aiosmtpd.smtp.SMTP.command_call_limit" title="aiosmtpd.smtp.SMTP.command_call_limit"><code class="xref py py-attr docutils literal notranslate"><span class="pre">command_call_limit</span></code></a> is of type <code class="docutils literal notranslate"><span class="pre">dict</span></code>,
it must be a <code class="docutils literal notranslate"><span class="pre">Dict[str,</span> <span class="pre">int]</span></code>
(the type of the values will be enforced).
The keys will be the SMTP Command to set the limit for,
the values will be the call limit per SMTP Command.</p>
<blockquote class="highlights">
<div><p>A special key of <code class="docutils literal notranslate"><span class="pre">"*"</span></code> is used to set the ‘default’ call limit for commands not
explicitly declared in <a class="reference internal" href="#aiosmtpd.smtp.SMTP.command_call_limit" title="aiosmtpd.smtp.SMTP.command_call_limit"><code class="xref py py-attr docutils literal notranslate"><span class="pre">command_call_limit</span></code></a>.
If <code class="docutils literal notranslate"><span class="pre">"*"</span></code> is not given,
then the ‘default’ call limit will be set to <code class="docutils literal notranslate"><span class="pre">aiosmtpd.smtp.CALL_LIMIT_DEFAULT</span></code></p>
</div></blockquote>
</div></blockquote>
<p>Other types – or a <code class="docutils literal notranslate"><span class="pre">Dict</span></code> whose any value is not an <code class="docutils literal notranslate"><span class="pre">int</span></code> – will raise a
<code class="docutils literal notranslate"><span class="pre">TypeError</span></code> exception.</p>
<p>Examples:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># All commands have a limit of 10 calls</span>
<span class="n">SMTP</span><span class="p">(</span><span class="o">...</span><span class="p">,</span> <span class="n">command_call_limit</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
<span class="c1"># Commands RCPT and NOOP have their own limits; others have an implicit limit</span>
<span class="c1"># of 20 (CALL_LIMIT_DEFAULT)</span>
<span class="n">SMTP</span><span class="p">(</span><span class="o">...</span><span class="p">,</span> <span class="n">command_call_limit</span><span class="o">=</span><span class="p">{</span><span class="s2">"RCPT"</span><span class="p">:</span> <span class="mi">30</span><span class="p">,</span> <span class="s2">"NOOP"</span><span class="p">:</span> <span class="mi">5</span><span class="p">})</span>
<span class="c1"># Commands RCPT and NOOP have their own limits; others set to 3</span>
<span class="n">SMTP</span><span class="p">(</span><span class="o">...</span><span class="p">,</span> <span class="n">command_call_limit</span><span class="o">=</span><span class="p">{</span><span class="s2">"RCPT"</span><span class="p">:</span> <span class="mi">20</span><span class="p">,</span> <span class="s2">"NOOP"</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span> <span class="s2">"*"</span><span class="p">:</span> <span class="mi">3</span><span class="p">})</span>
</pre></div>
</div>
<p>If not given (or set to <code class="docutils literal notranslate"><span class="pre">None</span></code>), then command call limit will not be enforced.
<strong>This will change in version 2.0</strong>.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 1.2.3.</span></p>
</div>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.proxy_protocol_timeout">
<span class="sig-name descname"><span class="pre">proxy_protocol_timeout</span></span><em class="property"><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="pre">int</span><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><span class="pre">float</span><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><span class="pre">None</span></em><em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span><span class="w"> </span><span class="pre">None</span></em><a class="headerlink" href="#aiosmtpd.smtp.SMTP.proxy_protocol_timeout" title="Link to this definition"></a></dt>
<dd><p>If given (not <code class="docutils literal notranslate"><span class="pre">None</span></code>), activates support for <strong>PROXY Protocol</strong>.</p>
<p>Please read the <a class="reference external" href="ProxyProtocol">PROXY Protocol Support documentation</a>
for a more in-depth explanation.</p>
<p>If not given (or <code class="docutils literal notranslate"><span class="pre">None</span></code>), disables support for PROXY Protocol.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>When PROXY protocol support is activated,
<a class="reference internal" href="#aiosmtpd.smtp.SMTP" title="aiosmtpd.smtp.SMTP"><code class="xref py py-class docutils literal notranslate"><span class="pre">SMTP</span></code></a>’s behavior changes:
It no longer immediately sends <code class="docutils literal notranslate"><span class="pre">220</span></code> greeting upon client connection,
but instead it will wait for client to first send the PROXY protocol header.</p>
<p>This is in accordance to the PROXY Protocol standard.</p>
</div>
<div class="versionadded">
<p><span class="versionmodified added">New in version 1.4.</span></p>
</div>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py">
<span class="sig-name descname"><span class="pre">loop</span></span></dt>
<dd><p>The asyncio event loop to use.
If not given, <code class="xref py py-meth docutils literal notranslate"><span class="pre">asyncio.new_event_loop()</span></code> will be called to create the event loop.</p>
</dd></dl>
<div class="line-block">
<div class="line"><br /></div>
<div class="line"><span class="parthead">Attributes & Methods</span></div>
</div>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.line_length_limit">
<span class="sig-name descname"><span class="pre">line_length_limit</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.line_length_limit" title="Link to this definition"></a></dt>
<dd><p>The maximum line length, in octets (not characters; one UTF-8 character
may result in more than one octet).
Defaults to <code class="docutils literal notranslate"><span class="pre">1001</span></code> in compliance with
<span class="target" id="index-4"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc5321.html#section-4.5.3.1.6"><strong>RFC 5321 § 4.5.3.1.6</strong></a></p>
<div class="admonition attention">
<p class="admonition-title">Attention</p>
<p>This sets the <em>stream limit</em> of <code class="xref py py-meth docutils literal notranslate"><span class="pre">asyncio.StreamReader.readuntil()</span></code>,
thus impacting how the method works.
In previous versions of aiosmtpd, the limit is not set.
To return to the behavior of the previous versions, set
<a class="reference internal" href="#aiosmtpd.smtp.SMTP.line_length_limit" title="aiosmtpd.smtp.SMTP.line_length_limit"><code class="xref py py-attr docutils literal notranslate"><span class="pre">line_length_limit</span></code></a> to <code class="docutils literal notranslate"><span class="pre">2**16</span></code> <em>before</em> instantiating the
<a class="reference internal" href="#aiosmtpd.smtp.SMTP" title="aiosmtpd.smtp.SMTP"><code class="xref py py-class docutils literal notranslate"><span class="pre">SMTP</span></code></a> class.</p>
</div>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.local_part_limit">
<span class="sig-name descname"><span class="pre">local_part_limit</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.local_part_limit" title="Link to this definition"></a></dt>
<dd><p>The maximum lengh (in octets) of the local part of email addresses.</p>
<p><span class="target" id="index-5"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc5321.html#section-4.5.3.1.1"><strong>RFC 5321 § 4.5.3.1.1</strong></a> specifies a maximum length of 64 octets,
but this requirement is flexible and can be relaxed at the server’s discretion
(see <span class="target" id="index-6"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc5321.html#section-4.5.3.1"><strong>§ 4.5.3.1</strong></a>).</p>
<p>Setting this to <cite>0</cite> (the default) disables this limit completely.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.AuthLoginUsernameChallenge">
<span class="sig-name descname"><span class="pre">AuthLoginUsernameChallenge</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.AuthLoginUsernameChallenge" title="Link to this definition"></a></dt>
<dd><p>A <code class="docutils literal notranslate"><span class="pre">str</span></code> containing the base64-encoded challenge to be sent as the first challenge
in the <code class="docutils literal notranslate"><span class="pre">AUTH</span> <span class="pre">LOGIN</span></code> mechanism.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.AuthLoginPasswordChallenge">
<span class="sig-name descname"><span class="pre">AuthLoginPasswordChallenge</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.AuthLoginPasswordChallenge" title="Link to this definition"></a></dt>
<dd><p>A <code class="docutils literal notranslate"><span class="pre">str</span></code> containing the base64-encoded challenge to be sent as the second challenge
in the <code class="docutils literal notranslate"><span class="pre">AUTH</span> <span class="pre">LOGIN</span></code> mechanism.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.event_handler">
<span class="sig-name descname"><span class="pre">event_handler</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.event_handler" title="Link to this definition"></a></dt>
<dd><p>The <em>handler</em> instance passed into the constructor.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.data_size_limit">
<span class="sig-name descname"><span class="pre">data_size_limit</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.data_size_limit" title="Link to this definition"></a></dt>
<dd><p>The value of the <em>data_size_limit</em> argument passed into the constructor.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.enable_SMTPUTF8">
<span class="sig-name descname"><span class="pre">enable_SMTPUTF8</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.enable_SMTPUTF8" title="Link to this definition"></a></dt>
<dd><p>The value of the <em>enable_SMTPUTF8</em> argument passed into the constructor.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.hostname">
<span class="sig-name descname"><span class="pre">hostname</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.hostname" title="Link to this definition"></a></dt>
<dd><p>The <code class="docutils literal notranslate"><span class="pre">220</span></code> greeting hostname. This will either be the value of the
<em>hostname</em> argument passed into the constructor, or the system’s fully
qualified host name.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.tls_context">
<span class="sig-name descname"><span class="pre">tls_context</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.tls_context" title="Link to this definition"></a></dt>
<dd><p>The value of the <em>tls_context</em> argument passed into the constructor.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.require_starttls">
<span class="sig-name descname"><span class="pre">require_starttls</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.require_starttls" title="Link to this definition"></a></dt>
<dd><p>True if both the <em>tls_context</em> argument to the constructor was given
<strong>and</strong> the <em>require_starttls</em> flag was True.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.session">
<span class="sig-name descname"><span class="pre">session</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.session" title="Link to this definition"></a></dt>
<dd><p>The active <a class="reference internal" href="concepts.html#sessions-and-envelopes"><span class="std std-ref">session</span></a> object, if there is
one, otherwise None.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.envelope">
<span class="sig-name descname"><span class="pre">envelope</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.envelope" title="Link to this definition"></a></dt>
<dd><p>The active <a class="reference internal" href="concepts.html#sessions-and-envelopes"><span class="std std-ref">envelope</span></a> object, if there is
one, otherwise None.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.transport">
<span class="sig-name descname"><span class="pre">transport</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.transport" title="Link to this definition"></a></dt>
<dd><p>The active <a class="reference external" href="https://docs.python.org/3/library/asyncio-protocol.html#asyncio-transport">asyncio transport</a> if there is one, otherwise None.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.loop">
<span class="sig-name descname"><span class="pre">loop</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.loop" title="Link to this definition"></a></dt>
<dd><p>The event loop being used. This will either be the given <em>loop</em>
argument, or the new event loop that was created.</p>
</dd></dl>
<dl class="py attribute">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.authenticated">
<span class="sig-name descname"><span class="pre">authenticated</span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.authenticated" title="Link to this definition"></a></dt>
<dd><p>A flag that indicates whether authentication had succeeded.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP._create_session">
<span class="sig-name descname"><span class="pre">_create_session</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#aiosmtpd.smtp.SMTP._create_session" title="Link to this definition"></a></dt>
<dd><p>A method subclasses can override to return custom <code class="docutils literal notranslate"><span class="pre">Session</span></code> instances.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP._create_envelope">
<span class="sig-name descname"><span class="pre">_create_envelope</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#aiosmtpd.smtp.SMTP._create_envelope" title="Link to this definition"></a></dt>
<dd><p>A method subclasses can override to return custom <code class="docutils literal notranslate"><span class="pre">Envelope</span></code> instances.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.push">
<em class="property"><span class="pre">async</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">push</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">status</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.push" title="Link to this definition"></a></dt>
<dd><p>The method that subclasses and handlers should use to return statuses to
SMTP clients. This is a coroutine. <em>status</em> can be a bytes object, but
for convenience it is more likely to be a string. If it’s a string, it
must be ASCII, unless <em>enable_SMTPUTF8</em> is True in which case it will be
encoded as UTF-8.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py">
<span class="sig-name descname"><span class="pre">smtp_<COMMAND>(arg)</span></span></dt>
<dd><p>Coroutine methods implementing the SMTP protocol commands. For example,
<code class="docutils literal notranslate"><span class="pre">smtp_HELO()</span></code> implements the SMTP <code class="docutils literal notranslate"><span class="pre">HELO</span></code> command. Subclasses can
override these, or add new command methods to implement custom
extensions to the SMTP protocol. <em>arg</em> is the rest of the SMTP command
given by the client, or None if nothing but the command was given.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="aiosmtpd.smtp.SMTP.challenge_auth">
<em class="property"><span class="pre">async</span><span class="w"> </span></em><span class="sig-name descname"><span class="pre">challenge_auth</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">challenge</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">encode_to_b64</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">log_client_response</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">→</span> <span class="sig-return-typehint"><span class="pre">_Missing</span><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><span class="pre">bytes</span></span></span><a class="headerlink" href="#aiosmtpd.smtp.SMTP.challenge_auth" title="Link to this definition"></a></dt>
<dd><dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>challenge</strong> (<em>AnyStr</em>) – The SMTP AUTH challenge to send to the client.
May be in plaintext, may be in base64. Do NOT prefix with “334 “!</p></li>
<li><p><strong>encode_to_b64</strong> (<em>bool</em>) – If true, will perform base64-encoding before sending
the challenge to the client.</p></li>
<li><p><strong>log_client_response</strong> (<em>bool</em>) – If true, will perform logging of client response</p></li>
</ul>
</dd>
<dt class="field-even">Returns<span class="colon">:</span></dt>
<dd class="field-even"><p>Response from client (already base64-decoded) or <code class="docutils literal notranslate"><span class="pre">MISSING</span></code> (see description)</p>
</dd>
</dl>
<p>This method will return <code class="docutils literal notranslate"><span class="pre">MISSING</span></code> if either of these scenarios happen:</p>
<blockquote>
<div><ul class="simple">
<li><p>client aborted the <code class="docutils literal notranslate"><span class="pre">AUTH</span></code> procedure by sending <code class="docutils literal notranslate"><span class="pre">b"*"</span></code>, or</p></li>
<li><p>client response to the challenge cannot be base64-decoded.</p></li>
</ul>
</div></blockquote>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Setting <code class="docutils literal notranslate"><span class="pre">log_client_response=True</span></code> might cause leakage of sensitive information!</p>
<p><span class="boldital">DO NOT TURN ON</span> UNLESS ABSOLUTELY NECESSARY!</p>
</div>
</dd></dl>
</dd></dl>
</section>
<section id="enabling-starttls">
<span id="tls"></span><h2>Enabling STARTTLS<a class="headerlink" href="#enabling-starttls" title="Link to this heading"></a></h2>
<p>To enable <span class="target" id="index-7"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc3207.html"><strong>RFC 3207</strong></a> <code class="docutils literal notranslate"><span class="pre">STARTTLS</span></code>,
you must supply the <em>tls_context</em> argument to the <a class="reference internal" href="#aiosmtpd.smtp.SMTP" title="aiosmtpd.smtp.SMTP"><code class="xref py py-class docutils literal notranslate"><span class="pre">SMTP</span></code></a> class.
<em>tls_context</em> is created with the <code class="xref py py-func docutils literal notranslate"><span class="pre">ssl.create_default_context()</span></code> call
from the <code class="xref py py-mod docutils literal notranslate"><span class="pre">ssl</span></code> module, as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">context</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">create_default_context</span><span class="p">(</span><span class="n">ssl</span><span class="o">.</span><span class="n">Purpose</span><span class="o">.</span><span class="n">CLIENT_AUTH</span><span class="p">)</span>
</pre></div>
</div>
<p>The context must be initialized with a server certificate, private key, and/or
intermediate CA certificate chain with the
<code class="xref py py-meth docutils literal notranslate"><span class="pre">ssl.SSLContext.load_cert_chain()</span></code> method. This can be done with
separate files, or an all in one file. Files must be in PEM format.</p>
<p>For example, if you wanted to use a self-signed certification for localhost,
which is easy to create but doesn’t provide much security, you could use the
<em class="manpage">openssl(1)</em> command like so:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
-days 365 -nodes -subj '/CN=localhost'
</pre></div>
</div>
<p>and then in Python:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">context</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">create_default_context</span><span class="p">(</span><span class="n">ssl</span><span class="o">.</span><span class="n">Purpose</span><span class="o">.</span><span class="n">CLIENT_AUTH</span><span class="p">)</span>
<span class="n">context</span><span class="o">.</span><span class="n">load_cert_chain</span><span class="p">(</span><span class="s1">'cert.pem'</span><span class="p">,</span> <span class="s1">'key.pem'</span><span class="p">)</span>
</pre></div>
</div>
<p>Now pass the <code class="docutils literal notranslate"><span class="pre">context</span></code> object to the <em>tls_context</em> argument in the <code class="docutils literal notranslate"><span class="pre">SMTP</span></code>
constructor.</p>
<p>Note that a number of exceptions can be generated by these methods, and by SSL
connections, which you must be prepared to handle. Additional documentation
is available in Python’s <code class="xref py py-mod docutils literal notranslate"><span class="pre">ssl</span></code> module, and should be reviewed before use; in
particular if client authentication and/or advanced error handling is desired.</p>
<p>If <em>require_starttls</em> is <code class="docutils literal notranslate"><span class="pre">True</span></code>, a TLS session must be initiated for the
server to respond to any commands other than <code class="docutils literal notranslate"><span class="pre">EHLO</span></code>/<code class="docutils literal notranslate"><span class="pre">LHLO</span></code>, <code class="docutils literal notranslate"><span class="pre">NOOP</span></code>,
<code class="docutils literal notranslate"><span class="pre">QUIT</span></code>, and <code class="docutils literal notranslate"><span class="pre">STARTTLS</span></code>.</p>
<p>If <em>require_starttls</em> is <code class="docutils literal notranslate"><span class="pre">False</span></code> (the default), use of TLS is not required;
the client <em>may</em> upgrade the connection to TLS, or may use any supported
command over an insecure connection.</p>
<p>If <em>tls_context</em> is not supplied, the <code class="docutils literal notranslate"><span class="pre">STARTTLS</span></code> option will not be
advertised, and the <code class="docutils literal notranslate"><span class="pre">STARTTLS</span></code> command will not be accepted.
<em>require_starttls</em> is meaningless in this case, and should be set to
<code class="docutils literal notranslate"><span class="pre">False</span></code>.</p>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="controller.html" class="btn btn-neutral float-left" title="Programmatic usage" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<a href="lmtp.html" class="btn btn-neutral float-right" title="The LMTP class" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<div role="contentinfo">
<p>© Copyright 2015-2024, The aiosmtpd Developers.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>