MTA connections¶
Outgoing connections to the outgoing mail transport agent (MTA) are mitigated
through a Connection
class, which can transparently manage multiple
sessions in a single connection.
>>> from mailman.mta.connection import Connection
The number of sessions per connections is specified when the Connection
object is created, as is the host and port number of the SMTP server. Zero
means there’s an unlimited number of sessions per connection.
>>> connection = Connection(
... config.mta.smtp_host, int(config.mta.smtp_port), 0)
At the start, there have been no connections to the server.
>>> smtpd.get_connection_count()
0
By sending a message to the server, a connection is opened.
>>> connection.sendmail('anne@example.com', ['bart@example.com'], """\
... From: anne@example.com
... To: bart@example.com
... Subject: aardvarks
...
... """)
{}
>>> smtpd.get_connection_count()
1
We can reset the connection count back to zero.
>>> from smtplib import SMTP
>>> def reset():
... smtpd = SMTP()
... smtpd.connect(config.mta.smtp_host, int(config.mta.smtp_port))
... smtpd.docmd('RSET')
>>> reset()
>>> smtpd.get_connection_count()
0
>>> connection.quit()
By providing an SMTP user name and password in the configuration file, Mailman will authenticate with the mail server after each new connection.
>>> config.push('auth', """
... [mta]
... smtp_user: testuser
... smtp_pass: testpass
... """)
>>> connection = Connection(
... config.mta.smtp_host, int(config.mta.smtp_port), 0,
... config.mta.smtp_user, config.mta.smtp_pass)
>>> connection.sendmail('anne@example.com', ['bart@example.com'], """\
... From: anne@example.com
... To: bart@example.com
... Subject: aardvarks
...
... """)
{}
>>> print(smtpd.get_authentication_credentials())
AHRlc3R1c2VyAHRlc3RwYXNz
>>> reset()
>>> config.pop('auth')
Sessions per connection¶
Let’s say we specify a maximum number of sessions per connection of 2. When the third message is sent, the connection is torn down and a new one is created.
The connection count starts at zero.
>>> connection = Connection(
... config.mta.smtp_host, int(config.mta.smtp_port), 2)
>>> smtpd.get_connection_count()
0
We send two messages through the Connection
object. Only one connection
is opened.
>>> connection.sendmail('anne@example.com', ['bart@example.com'], """\
... From: anne@example.com
... To: bart@example.com
... Subject: aardvarks
...
... """)
{}
>>> smtpd.get_connection_count()
1
>>> connection.sendmail('anne@example.com', ['bart@example.com'], """\
... From: anne@example.com
... To: bart@example.com
... Subject: aardvarks
...
... """)
{}
>>> smtpd.get_connection_count()
1
The third message would cause a third session, exceeding the maximum. So the current connection is closed and a new one opened.
>>> connection.sendmail('anne@example.com', ['bart@example.com'], """\
... From: anne@example.com
... To: bart@example.com
... Subject: aardvarks
...
... """)
{}
>>> smtpd.get_connection_count()
2
A fourth message does not cause a new connection to be made.
>>> connection.sendmail('anne@example.com', ['bart@example.com'], """\
... From: anne@example.com
... To: bart@example.com
... Subject: aardvarks
...
... """)
{}
>>> smtpd.get_connection_count()
2
But a fifth one does.
>>> connection.sendmail('anne@example.com', ['bart@example.com'], """\
... From: anne@example.com
... To: bart@example.com
... Subject: aardvarks
...
... """)
{}
>>> smtpd.get_connection_count()
3
No maximum¶
A value of zero means that there is an unlimited number of sessions per connection.
>>> connection = Connection(
... config.mta.smtp_host, int(config.mta.smtp_port), 0)
>>> reset()
Even after ten messages are sent, there’s still been only one connection to the server.
>>> connection.debug = True
>>> for i in range(10):
... # Ignore the results.
... results = connection.sendmail(
... 'anne@example.com', ['bart@example.com'], """\
... From: anne@example.com
... To: bart@example.com
... Subject: aardvarks
...
... """)
>>> smtpd.get_connection_count()
1
Development mode¶
By putting Mailman into development mode, you can force the recipients to a given hard-coded address. This allows you to test Mailman without worrying about accidental deliveries to unintended recipients.
>>> config.push('devmode', """
... [devmode]
... enabled: yes
... recipient: zperson@example.com
... """)
>>> smtpd.clear()
>>> connection.sendmail(
... 'anne@example.com',
... ['bart@example.com', 'cate@example.com'], """\
... From: anne@example.com
... To: bart@example.com
... Subject: aardvarks
...
... """)
{}
>>> messages = list(smtpd.messages)
>>> len(messages)
1
>>> print(messages[0].as_string())
From: anne@example.com
To: bart@example.com
Subject: aardvarks
X-Peer: ...
X-MailFrom: anne@example.com
X-RcptTo: zperson@example.com, zperson@example.com
>>> config.pop('devmode')