Ejemplo n.º 1
0
 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)
Ejemplo n.º 2
0
 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')
Ejemplo n.º 4
0
    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)
Ejemplo n.º 6
0
    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')
Ejemplo n.º 7
0
 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)
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
 def setUp(self):
     self.connection = Connection(config.mta.smtp_host,
                                  int(config.mta.smtp_port), 0)
     self.msg_text = """\
Ejemplo n.º 11
0
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)