def __init__(self): """Create a basic deliverer.""" username = (config.mta.smtp_user if config.mta.smtp_user else None) password = (config.mta.smtp_pass if config.mta.smtp_pass else None) self._connection = Connection( config.mta.smtp_host, int(config.mta.smtp_port), int(config.mta.max_sessions_per_connection), username, password)
def __init__(self): """Create a basic deliverer.""" self._connection = Connection( config.mta.smtp_host, int(config.mta.smtp_port), int(config.mta.max_sessions_per_connection), config.mta.smtp_user if config.mta.smtp_user else None, config.mta.smtp_pass if config.mta.smtp_pass else None, as_SecureMode(config.mta.smtp_secure_mode), as_boolean(config.mta.smtp_verify_cert), as_boolean(config.mta.smtp_verify_hostname), )
def test_authentication_good_path(self): # Logging in with the correct user name and password succeeds. connection = Connection( config.mta.smtp_host, int(config.mta.smtp_port), 0, 'testuser', 'testpass') connection.sendmail('*****@*****.**', ['*****@*****.**'], """\ From: [email protected] To: [email protected] Subject: aardvarks """) self.assertEqual(self.layer.smtpd.get_authentication_credentials(), 'AHRlc3R1c2VyAHRlc3RwYXNz')
def test_not_supported(self): connection = Connection( config.mta.smtp_host, int(config.mta.smtp_port), 0, secure_mode=SecureMode.STARTTLS, verify_cert=False ) msg_text = """\ From: [email protected] To: [email protected] Subject: aardvarks """ LogFileMark('mailman.smtp') with self.assertRaises(SMTPNotSupportedError): connection.sendmail( '*****@*****.**', ['*****@*****.**'], msg_text)
def test_authentication_error(self): # Logging in to the MTA with a bad user name and password produces a # 571 Bad Authentication error. with self.assertRaises(SMTPAuthenticationError) as cm: connection = Connection( config.mta.smtp_host, int(config.mta.smtp_port), 0, 'baduser', 'badpass') connection.sendmail('*****@*****.**', ['*****@*****.**'], """\ From: [email protected] To: [email protected] Subject: aardvarks """) self.assertEqual(cm.exception.smtp_code, 571) self.assertEqual(cm.exception.smtp_error, b'Bad authentication')
class BaseDelivery: """Base delivery class.""" def __init__(self): """Create a basic deliverer.""" username = (config.mta.smtp_user if config.mta.smtp_user else None) password = (config.mta.smtp_pass if config.mta.smtp_pass else None) self._connection = Connection( config.mta.smtp_host, int(config.mta.smtp_port), int(config.mta.max_sessions_per_connection), username, password) def _deliver_to_recipients(self, mlist, msg, msgdata, recipients): """Low-level delivery to a set of recipients. :param mlist: The mailing list being delivered to. :type mlist: `IMailingList` :param msg: The original message being delivered. :type msg: `Message` :param msgdata: Additional message metadata for this delivery. :type msgdata: dictionary :param recipients: The recipients of this message. :type recipients: sequence :return: delivery failures as defined by `smtplib.SMTP.sendmail` :rtype: dictionary """ # Do the actual sending. sender = self._get_sender(mlist, msg, msgdata) message_id = msg['message-id'] # Since the recipients can be a set or a list, sort the recipients by # email address for predictability and testability. try: refused = self._connection.sendmail(sender, sorted(recipients), msg.as_string()) except smtplib.SMTPRecipientsRefused as error: log.error('%s recipients refused: %s', message_id, error) refused = error.recipients except smtplib.SMTPResponseException as error: log.error('%s response exception: %s', message_id, error) refused = dict( # recipient -> (code, error) (recipient, (error.smtp_code, error.smtp_error)) for recipient in recipients) except (socket.error, IOError, smtplib.SMTPException) as error: # MTA not responding, or other socket problems, or any other # kind of SMTPException. In that case, nothing got delivered, # so treat this as a temporary failure. We use error code 444 # for this (temporary, unspecified failure, cf RFC 5321). log.error('%s low level smtp error: %s', message_id, error) error = str(error) refused = dict( # recipient -> (code, error) (recipient, (444, error)) for recipient in recipients) return refused def _get_sender(self, mlist, msg, msgdata): """Return the envelope sender to use. The message metadata can override the calculation of the sender, but otherwise it falls to the list's -bounces robot. If this message is not intended for any specific mailing list, the site owner's address is used. :param mlist: The mailing list being delivered to. :type mlist: `IMailingList` :param msg: The original message being delivered. :type msg: `Message` :param msgdata: Additional message metadata for this delivery. :type msgdata: dictionary :return: The envelope sender. :rtype: string """ sender = msgdata.get('sender') if sender is None: return (config.mailman.site_owner if mlist is None else mlist.bounces_address) return sender
class BaseDelivery: """Base delivery class.""" def __init__(self): """Create a basic deliverer.""" username = config.mta.smtp_user if config.mta.smtp_user else None password = config.mta.smtp_pass if config.mta.smtp_pass else None self._connection = Connection( config.mta.smtp_host, int(config.mta.smtp_port), int(config.mta.max_sessions_per_connection), username, password, ) def _deliver_to_recipients(self, mlist, msg, msgdata, recipients): """Low-level delivery to a set of recipients. :param mlist: The mailing list being delivered to. :type mlist: `IMailingList` :param msg: The original message being delivered. :type msg: `Message` :param msgdata: Additional message metadata for this delivery. :type msgdata: dictionary :param recipients: The recipients of this message. :type recipients: sequence :return: delivery failures as defined by `smtplib.SMTP.sendmail` :rtype: dictionary """ # Do the actual sending. sender = self._get_sender(mlist, msg, msgdata) message_id = msg["message-id"] try: refused = self._connection.sendmail(sender, recipients, msg.as_string()) except smtplib.SMTPRecipientsRefused as error: log.error("%s recipients refused: %s", message_id, error) refused = error.recipients except smtplib.SMTPResponseException as error: log.error("%s response exception: %s", message_id, error) refused = dict( # recipient -> (code, error) (recipient, (error.smtp_code, error.smtp_error)) for recipient in recipients ) except (socket.error, IOError, smtplib.SMTPException) as error: # MTA not responding, or other socket problems, or any other # kind of SMTPException. In that case, nothing got delivered, # so treat this as a temporary failure. We use error code 444 # for this (temporary, unspecified failure, cf RFC 5321). log.error("%s low level smtp error: %s", message_id, error) error = str(error) refused = dict( # recipient -> (code, error) (recipient, (444, error)) for recipient in recipients ) return refused def _get_sender(self, mlist, msg, msgdata): """Return the envelope sender to use. The message metadata can override the calculation of the sender, but otherwise it falls to the list's -bounces robot. If this message is not intended for any specific mailing list, the site owner's address is used. :param mlist: The mailing list being delivered to. :type mlist: `IMailingList` :param msg: The original message being delivered. :type msg: `Message` :param msgdata: Additional message metadata for this delivery. :type msgdata: dictionary :return: The envelope sender. :rtype: string """ sender = msgdata.get("sender") if sender is None: return config.mailman.site_owner if mlist is None else mlist.bounces_address return sender
def setUp(self): self.connection = Connection(config.mta.smtp_host, int(config.mta.smtp_port), 0) self.msg_text = """\
class TestConnectionCount(unittest.TestCase): layer = SMTPLayer def setUp(self): self.connection = Connection(config.mta.smtp_host, int(config.mta.smtp_port), 0) self.msg_text = """\ From: [email protected] To: [email protected] Subject: aardvarks """ def test_count_0(self): # So far, no connections. self.assertEqual(SMTPLayer.smtpd.get_connection_count(), 0) def test_count_1(self): self.connection.sendmail('*****@*****.**', ['*****@*****.**'], self.msg_text) self.assertEqual(SMTPLayer.smtpd.get_connection_count(), 1) def test_count_2(self): self.connection.sendmail('*****@*****.**', ['*****@*****.**'], self.msg_text) self.connection.quit() self.connection.sendmail('*****@*****.**', ['*****@*****.**'], self.msg_text) self.connection.quit() self.assertEqual(SMTPLayer.smtpd.get_connection_count(), 2) def test_count_reset(self): self.connection.sendmail('*****@*****.**', ['*****@*****.**'], self.msg_text) self.connection.quit() self.connection.sendmail('*****@*****.**', ['*****@*****.**'], self.msg_text) self.connection.quit() # Issue the fake SMTP command to reset the count. client = SMTP() client.connect(config.mta.smtp_host, int(config.mta.smtp_port)) client.docmd('RSET') self.assertEqual(SMTPLayer.smtpd.get_connection_count(), 0)
def setUp(self): super().setUp() self.connection = Connection( config.mta.smtp_host, int(config.mta.smtp_port), 0, secure_mode=SecureMode.STARTTLS, verify_cert=False )
def test_exception_is_raised_from_connect(self, mocked_SMTP): connection = Connection( config.mta.smtp_host, int(config.mta.smtp_port), 0) with self.assertRaises(Exception): connection._connect() self.assertTrue(mocked_SMTP.called)
def setUp(self): super().setUp() self.connection = Connection( config.mta.smtp_host, int(config.mta.smtp_port), 0)