Example #1
0
    def test_nonverp_detectable_nonfatal_bounce(self):
        # Here's a bounce that is not VERPd, but which has a bouncing address
        # that can be parsed from a known bounce format.  The bounce is
        # non-fatal so no bounce event is registered.
        dsn = message_from_string(
            """\
From: [email protected]
To: [email protected]
Message-Id: <first>
Content-Type: multipart/report; report-type=delivery-status; boundary=AAA
MIME-Version: 1.0

--AAA
Content-Type: message/delivery-status

Action: delayed
Original-Recipient: rfc822; [email protected]

--AAA--
"""
        )
        self._bounceq.enqueue(dsn, self._msgdata)
        self._runner.run()
        get_queue_messages("bounces", expected_count=0)
        events = list(self._processor.events)
        self.assertEqual(len(events), 0)
    def test_nonverp_detectable_nonfatal_bounce(self):
        # Here's a bounce that is not VERPd, but which has a bouncing address
        # that can be parsed from a known bounce format.  The bounce is
        # non-fatal so no bounce event is registered and the bounce is not
        # reported as unrecognized.
        self._mlist.forward_unrecognized_bounces_to = (
            UnrecognizedBounceDisposition.site_owner)
        dsn = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>
Content-Type: multipart/report; report-type=delivery-status; boundary=AAA
MIME-Version: 1.0

--AAA
Content-Type: message/delivery-status

Action: delayed
Original-Recipient: rfc822; [email protected]

--AAA--
""")
        self._bounceq.enqueue(dsn, self._msgdata)
        mark = LogFileMark('mailman.bounce')
        self._runner.run()
        get_queue_messages('bounces', expected_count=0)
        events = list(self._processor.events)
        self.assertEqual(len(events), 0)
        # There should be nothing in the 'virgin' queue.
        get_queue_messages('virgin', expected_count=0)
        # There should be log event in the log file.
        log_lines = mark.read().splitlines()
        self.assertTrue(len(log_lines) > 0)
Example #3
0
    def test_verp_probe_bounce(self):
        # A VERP probe bounced.  The primary difference here is that the
        # registered bounce event will have a different context.  The
        # Message-Id will be different too, because of the way we're
        # simulating the probe bounce.
        #
        # Start be simulating a probe bounce.
        send_probe(self._member, self._msg)
        items = get_queue_messages('virgin', expected_count=1)
        message = items[0].msg
        bounce = message_from_string("""\
To: {0}
From: [email protected]
Message-Id: <second>

""".format(message['From']))
        self._bounceq.enqueue(bounce, self._msgdata)
        self._runner.run()
        get_queue_messages('bounces', expected_count=0)
        events = list(self._processor.events)
        self.assertEqual(len(events), 1)
        self.assertEqual(events[0].email, '*****@*****.**')
        self.assertEqual(events[0].list_id, 'test.example.com')
        self.assertEqual(events[0].message_id, '<second>')
        self.assertEqual(events[0].context, BounceContext.probe)
        self.assertEqual(events[0].processed, False)
Example #4
0
    def test_no_detectable_bounce_addresses(self):
        # A bounce message was received, but no addresses could be detected.
        # A message will be logged in the bounce log though, and the message
        # can be forwarded to someone who can do something about it.
        self._mlist.forward_unrecognized_bounces_to = (
            UnrecognizedBounceDisposition.site_owner)
        bogus = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <third>

""")
        self._bounceq.enqueue(bogus, self._msgdata)
        mark = LogFileMark('mailman.bounce')
        self._runner.run()
        self.assertEqual(len(get_queue_messages('bounces')), 0)
        events = list(self._processor.events)
        self.assertEqual(len(events), 0)
        line = mark.readline()
        self.assertEqual(
            line[-51:-1],
            'Bounce message w/no discernable addresses: <third>')
        # Here's the forwarded message to the site owners.
        forwards = get_queue_messages('virgin')
        self.assertEqual(len(forwards), 1)
        self.assertEqual(forwards[0].msg['to'], '*****@*****.**')
Example #5
0
    def test_no_detectable_bounce_addresses(self):
        # A bounce message was received, but no addresses could be detected.
        # A message will be logged in the bounce log though, and the message
        # can be forwarded to someone who can do something about it.
        self._mlist.forward_unrecognized_bounces_to = (
            UnrecognizedBounceDisposition.site_owner)
        bogus = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <third>

""")
        self._bounceq.enqueue(bogus, self._msgdata)
        mark = LogFileMark('mailman.bounce')
        self._runner.run()
        get_queue_messages('bounces', expected_count=0)
        events = list(self._processor.events)
        self.assertEqual(len(events), 0)
        line = mark.readline()
        self.assertEqual(
            line[-51:-1],
            'Bounce message w/no discernable addresses: <third>')
        # Here's the forwarded message to the site owners.
        items = get_queue_messages('virgin', expected_count=1)
        self.assertEqual(items[0].msg['to'], '*****@*****.**')
Example #6
0
    def test_nonverp_detectable_fatal_bounce(self):
        # Here's a bounce that is not VERPd, but which has a bouncing address
        # that can be parsed from a known bounce format.  DSN is as good as
        # any, but we'll make the parsed address different for the fun of it.
        dsn = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>
Content-Type: multipart/report; report-type=delivery-status; boundary=AAA
MIME-Version: 1.0

--AAA
Content-Type: message/delivery-status

Action: fail
Original-Recipient: rfc822; [email protected]

--AAA--
""")
        self._bounceq.enqueue(dsn, self._msgdata)
        self._runner.run()
        self.assertEqual(len(get_queue_messages('bounces')), 0)
        events = list(self._processor.events)
        self.assertEqual(len(events), 1)
        self.assertEqual(events[0].email, '*****@*****.**')
        self.assertEqual(events[0].list_id, 'test.example.com')
        self.assertEqual(events[0].message_id, '<first>')
        self.assertEqual(events[0].context, BounceContext.normal)
        self.assertEqual(events[0].processed, False)
Example #7
0
    def test_nonverp_detectable_fatal_bounce(self):
        # Here's a bounce that is not VERPd, but which has a bouncing address
        # that can be parsed from a known bounce format.  DSN is as good as
        # any, but we'll make the parsed address different for the fun of it.
        dsn = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>
Content-Type: multipart/report; report-type=delivery-status; boundary=AAA
MIME-Version: 1.0

--AAA
Content-Type: message/delivery-status

Action: fail
Original-Recipient: rfc822; [email protected]

--AAA--
""")
        self._bounceq.enqueue(dsn, self._msgdata)
        self._runner.run()
        get_queue_messages('bounces', expected_count=0)
        events = list(self._processor.events)
        self.assertEqual(len(events), 1)
        self.assertEqual(events[0].email, '*****@*****.**')
        self.assertEqual(events[0].list_id, 'test.example.com')
        self.assertEqual(events[0].message_id, '<first>')
        self.assertEqual(events[0].context, BounceContext.normal)
        self.assertEqual(events[0].processed, False)
Example #8
0
    def test_verp_probe_bounce(self):
        # A VERP probe bounced.  The primary difference here is that the
        # registered bounce event will have a different context.  The
        # Message-Id will be different too, because of the way we're
        # simulating the probe bounce.
        #
        # Start be simulating a probe bounce.
        send_probe(self._member, self._msg)
        message = get_queue_messages('virgin')[0].msg
        bounce = message_from_string("""\
To: {0}
From: [email protected]
Message-Id: <second>

""".format(message['From']))
        self._bounceq.enqueue(bounce, self._msgdata)
        self._runner.run()
        self.assertEqual(len(get_queue_messages('bounces')), 0)
        events = list(self._processor.events)
        self.assertEqual(len(events), 1)
        self.assertEqual(events[0].email, '*****@*****.**')
        self.assertEqual(events[0].list_id, 'test.example.com')
        self.assertEqual(events[0].message_id, '<second>')
        self.assertEqual(events[0].context, BounceContext.probe)
        self.assertEqual(events[0].processed, False)
Example #9
0
    def test_arc_sign_raises_exception(self, mocked_sign_message):
        config.push(
            'arc_sign', """
        [ARC]
        enabled: yes
        authserv_id: test.example.org
        selector: dummy
        domain: example.org
        privkey: %s
        """ % (self.keyfile.name))

        self.addCleanup(config.pop, 'arc_sign')

        lst = create_list('*****@*****.**')
        msgdata = {}

        msg = """\
Message-ID: <*****@*****.**>
Date: Thu, 14 Jan 2015 15:00:01 -0800
From: John Q Doe <*****@*****.**>
To: [email protected]
Subject: Example 1

Hey gang,
This is a test message.
--J."""

        msg = message_from_string(msg)
        with self.assertRaises(DKIMException):
            ARCSign().process(lst, msg, msgdata)
        self.assertTrue(mocked_sign_message.called)
Example #10
0
    def setUp(self):
        self._mlist = create_list("*****@*****.**")
        self._mlist.send_welcome_message = False
        self._bounceq = config.switchboards["bounces"]
        self._runner = make_testable_runner(BounceRunner, "bounces")
        self._anne = getUtility(IUserManager).create_address("*****@*****.**")
        self._member = self._mlist.subscribe(self._anne, MemberRole.member)
        self._msg = message_from_string(
            """\
From: [email protected]
To: [email protected]
Message-Id: <first>

"""
        )
        self._msgdata = dict(listid="test.example.com")
        self._processor = getUtility(IBounceProcessor)
        config.push(
            "site owner",
            """
        [mailman]
        site_owner: [email protected]
        """,
        )
        self.addCleanup(config.pop, "site owner")
    def test_chain_validation_fail(self):
        # Set the log-level for dkimpy to CRITICAL To avoid error output from
        # logger.
        logging.getLogger('dkimpy').setLevel(logging.CRITICAL)
        config.push('dkim_and_cv', """
        [ARC]
        enabled: yes
        authserv_id: lists.example.org
        dkim: yes
        dmarc: no
        privkey: {}
        """.format(self.keyfile.name))
        self.addCleanup(config.pop, 'dkim_and_cv')

        lst = create_list('*****@*****.**')
        msgdata = {}

        msg = message_from_string("""MIME-Version: 1.0
Return-Path: <*****@*****.**>
ARC-Seal: a=rsa-sha256;
    b=dOdFEyhrk/tw5wl3vMIogoxhaVsKJkrkEhnAcq2XqOLSQhPpGzhGBJzR7k1sWGokon3TmQ
    7TX9zQLO6ikRpwd/pUswiRW5DBupy58fefuclXJAhErsrebfvfiueGyhHXV7C1LyJTztywzn
    QGG4SCciU/FTlsJ0QANrnLRoadfps=; cv=none; d=example.org; i=1; s=dummy;
    t=12345
ARC-Message-Signature: a=rsa-sha256;
    b=QsRzR/UqwRfVLBc1TnoQomlVw5qi6jp08q8lHpBSl4RehWyHQtY3uOIAGdghDk/mO+/Xpm
    9JA5UVrPyDV0f+2q/YAHuwvP11iCkBQkocmFvgTSxN8H+DwFFPrVVUudQYZV7UDDycXoM6UE
    cdfzLLzVNPOAHEDIi/uzoV4sUqZ18=;
    bh=KWSe46TZKCcDbH4klJPo+tjk5LWJnVRlP5pvjXFZYLQ=; c=relaxed/relaxed;
    d=example.org; h=from:to:date:subject:mime-version:arc-authentication-
    results; i=1; s=dummy; t=12345
ARC-Authentication-Results: i=1; lists.example.org;
    spf=pass [email protected];
    dkim=pass (1024-bit key) [email protected];
    dmarc=pass
Received: from segv.d1.example (segv.d1.example [72.52.75.15])
    by lists.example.org (8.14.5/8.14.5) with ESMTP id t0EKaNU9010123
    for <*****@*****.**>; Thu, 14 Jan 2015 15:01:30 -0800 (PST)
    (envelope-from [email protected])
Authentication-Results: lists.example.org;
    spf=pass [email protected];
    dkim=pass (1024-bit key) [email protected];
    dmarc=pass
Received: by 10.157.14.6 with HTTP; Tue, 3 Jan 2017 12:22:54 -0800 (PST)
Message-ID: <*****@*****.**>
Date: Thu, 14 Jan 2015 15:00:01 -0800
From: John Q Doe <*****@*****.**>
To: [email protected]
Subject: Example 1

Hey gang(modified),
This is a test message.
--J.
""")

        ValidateAuthenticity().process(lst, msg, msgdata)
        res = ["lists.example.org; spf=pass [email protected]"
               "; dkim=pass [email protected]; dmarc=pass; arc=fail"]
        self.assertEqual(msg["Authentication-Results"], ''.join(res))
Example #12
0
    def test_mime_digest_format(self):
        # Make sure that the format of the MIME digest is as expected.
        self._mlist.digest_size_threshold = 0.6
        self._mlist.volume = 1
        self._mlist.next_digest_number = 1
        self._mlist.send_welcome_message = False
        # Subscribe some users receiving digests.
        anne = subscribe(self._mlist, 'Anne')
        anne.preferences.delivery_mode = DeliveryMode.mime_digests
        bart = subscribe(self._mlist, 'Bart')
        bart.preferences.delivery_mode = DeliveryMode.plaintext_digests
        # Fill the digest.
        process = config.handlers['to-digest'].process
        size = 0
        for i in range(1, 5):
            text = Template("""\
From: [email protected]
To: [email protected]
Subject: Test message $i
List-Post: <*****@*****.**>

Here is message $i
""").substitute(i=i)
            msg = message_from_string(text)
            process(self._mlist, msg, {})
            size += len(text)
            if size >= self._mlist.digest_size_threshold * 1024:
                break
        # Run the digest runner to create the MIME and RFC 1153 digests.
        runner = make_testable_runner(DigestRunner)
        runner.run()
        items = get_queue_messages('virgin', expected_count=2)
        # Find the MIME one.
        mime_digest = None
        for item in items:
            if item.msg.is_multipart():
                assert mime_digest is None, 'We got two MIME digests'
                mime_digest = item.msg
        fp = StringIO()
        # Verify the structure is what we expect.
        structure(mime_digest, fp)
        self.assertMultiLineEqual(
            fp.getvalue(), """\
multipart/mixed
    text/plain
    text/plain
    multipart/digest
        message/rfc822
            text/plain
        message/rfc822
            text/plain
        message/rfc822
            text/plain
        message/rfc822
            text/plain
    text/plain
""")
Example #13
0
    def setUp(self):
        self._processor = getUtility(IBounceProcessor)
        self._mlist = create_list('*****@*****.**')
        self._msg = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
Example #14
0
    def setUp(self):
        self._processor = getUtility(IBounceProcessor)
        self._mlist = create_list('*****@*****.**')
        self._msg = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
Example #15
0
    def test_mime_digest_format(self):
        # Make sure that the format of the MIME digest is as expected.
        self._mlist.digest_size_threshold = 0.6
        self._mlist.volume = 1
        self._mlist.next_digest_number = 1
        self._mlist.send_welcome_message = False
        # Subscribe some users receiving digests.
        anne = subscribe(self._mlist, 'Anne')
        anne.preferences.delivery_mode = DeliveryMode.mime_digests
        bart = subscribe(self._mlist, 'Bart')
        bart.preferences.delivery_mode = DeliveryMode.plaintext_digests
        # Fill the digest.
        process = config.handlers['to-digest'].process
        size = 0
        for i in range(1, 5):
            text = Template("""\
From: [email protected]
To: [email protected]
Subject: Test message $i
List-Post: <*****@*****.**>

Here is message $i
""").substitute(i=i)
            msg = message_from_string(text)
            process(self._mlist, msg, {})
            size += len(text)
            if size >= self._mlist.digest_size_threshold * 1024:
                break
        # Run the digest runner to create the MIME and RFC 1153 digests.
        runner = make_testable_runner(DigestRunner)
        runner.run()
        items = get_queue_messages('virgin')
        self.assertEqual(len(items), 2)
        # Find the MIME one.
        mime_digest = None
        for item in items:
            if item.msg.is_multipart():
                assert mime_digest is None, 'We got two MIME digests'
                mime_digest = item.msg
        fp = StringIO()
        # Verify the structure is what we expect.
        structure(mime_digest, fp)
        self.assertMultiLineEqual(fp.getvalue(), """\
multipart/mixed
    text/plain
    text/plain
    message/rfc822
        text/plain
    message/rfc822
        text/plain
    message/rfc822
        text/plain
    message/rfc822
        text/plain
    text/plain
""")
Example #16
0
    def setUp(self):
        self.mlist = create_list('*****@*****.**')
        self.msg = message_from_string("""\
From: [email protected]
To: [email protected]
Subject: A test message
Message-ID: <first>
Date: Tue, 14 Jun 2011 21:12:00 -0400

Nothing.
""")
Example #17
0
    def setUp(self):
        self.mlist = create_list('*****@*****.**')
        self.msg = message_from_string("""\
From: [email protected]
To: [email protected]
Subject: A test message
Message-ID: <first>
Date: Tue, 14 Jun 2011 21:12:00 -0400

Nothing.
""")
Example #18
0
    def setUp(self):
        self._mlist = create_list('*****@*****.**')
        self._outq = config.switchboards['out']
        self._runner = make_testable_runner(OutgoingRunner, 'out', run_once)
        self._msg = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
        self._msgdata = {}
Example #19
0
    def setUp(self):
        self._mlist = create_list('*****@*****.**')
        self._outq = config.switchboards['out']
        self._runner = make_testable_runner(OutgoingRunner, 'out', run_once)
        self._msg = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
        self._msgdata = {}
Example #20
0
    def setUp(self):
        self._mlist = create_list('*****@*****.**')
        self._retryq = config.switchboards['retry']
        self._outq = config.switchboards['out']
        self._runner = make_testable_runner(RetryRunner, 'retry')
        self._msg = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
        self._msgdata = dict(listid='test.example.com')
Example #21
0
    def setUp(self):
        self._mlist = create_list('*****@*****.**')
        self._retryq = config.switchboards['retry']
        self._outq = config.switchboards['out']
        self._runner = make_testable_runner(RetryRunner, 'retry')
        self._msg = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
        self._msgdata = dict(listid='test.example.com')
Example #22
0
    def test_bug876774(self):
        # LP: #876774, see above.
        bounce = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
        self._bounceq.enqueue(bounce, dict(listid='test.example.com'))
        self.assertEqual(len(self._bounceq.files), 1)
        self._runner.run()
        get_queue_messages('bounces', expected_count=0)
        events = list(self._processor.events)
        self.assertEqual(len(events), 0)
Example #23
0
    def setUp(self):
        self.mlist = create_list('*****@*****.**')
        self.msg = message_from_string("""\
From: [email protected]
To: [email protected]
Subject: A test message
Message-ID: <first>
Date: Tue, 14 Jun 2011 21:12:00 -0400

Nothing.
""")
        # Python 2.7 has assertMultiLineEqual.  Let this work without bounds.
        self.maxDiff = None
        self.eq = getattr(self, 'assertMultiLineEqual', self.assertEqual)
Example #24
0
    def test_bug876774(self):
        # LP: #876774, see above.
        bounce = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
        self._bounceq.enqueue(bounce, dict(listid='test.example.com'))
        self.assertEqual(len(self._bounceq.files), 1)
        self._runner.run()
        self.assertEqual(len(get_queue_messages('bounces')), 0)
        events = list(self._processor.events)
        self.assertEqual(len(events), 0)
Example #25
0
    def setUp(self):
        # Push a config where actual delivery is handled by a dummy function.
        # We generally don't care what this does, since we're just testing the
        # setting of the 'verp' key in the metadata.
        config.push('fake outgoing', """
        [mta]
        outgoing: mailman.runners.tests.test_outgoing.raise_socket_error
        """)
        self._mlist = create_list('*****@*****.**')
        self._outq = config.switchboards['out']
        self._runner = make_testable_runner(OutgoingRunner, 'out', run_once)
        self._msg = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
Example #26
0
    def setUp(self):
        # Push a config where actual delivery is handled by a dummy function.
        # We generally don't care what this does, since we're just testing the
        # setting of the 'verp' key in the metadata.
        config.push('fake outgoing', """
        [mta]
        outgoing: mailman.runners.tests.test_outgoing.raise_socket_error
        """)
        self.addCleanup(config.pop, 'fake outgoing')
        self._mlist = create_list('*****@*****.**')
        self._outq = config.switchboards['out']
        self._runner = make_testable_runner(OutgoingRunner, 'out', run_once)
        self._msg = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
Example #27
0
    def setUp(self):
        self._mlist = create_list('*****@*****.**')
        self._bounceq = config.switchboards['bounces']
        self._runner = make_testable_runner(BounceRunner, 'bounces')
        self._anne = getUtility(IUserManager).create_address(
            '*****@*****.**')
        self._member = self._mlist.subscribe(self._anne, MemberRole.member)
        self._msg = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
        self._msgdata = dict(listname='*****@*****.**')
        self._processor = getUtility(IBounceProcessor)
        config.push('site owner', """
        [mailman]
        site_owner: [email protected]
        """)
    def test_authentication_whitelist_hit(self):
        config.push('just_dkim', """
        [ARC]
        enabled: yes
        authserv_id: example.com
        dkim: yes
        dmarc: no
        privkey: {}
        """.format(self.keyfile.name))
        self.addCleanup(config.pop, 'just_dkim')

        lst = create_list('*****@*****.**')
        msgdata = {}

        msg = message_from_string("""DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=valimail.com; s=google2048;
        h=mime-version:from:date:message-id:subject:to;
        bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=;
        b=gntRk4rCVYIGkpO09ROkbs3n4YSIcp/Pi7tUnSIgs8uS+uZ2a77dG+/qlSvnk+mWET
         IBrkt1YpDzev/0ITTDy/zgTHjPiQIFcg9Q+3hn3sTz8ExCyM8/YYgoPqSs3oUXn3jwXk
         N/wpMuF29LTVp1gpkYzaoCDNPGd1Wag6Vh2lw65S7ruECCAdBm5XeSnvTOzIC0E/jmEt
         3hvaPiKAohCAsC5JAN89EATPOjnYJL4Q6X6p2qUsusz/8tkHuYvReHmxQkjQ0/N3fPP0
         6VfkIrPOHympq6qDUizbjiBmgiMWKnarrptblJvyt66/aIHx+QamP6LUA+/RUFY1q7TG
         MSDg==
Authentication-Results: example.com; spf=pass smtp.mailfrom=gmail.com
MIME-Version: 1.0
From: Gene Shuman <*****@*****.**>
Date: Wed, 25 Jan 2017 16:13:31 -0800
Message-ID:
  <CANtLugNVcUMfjVH22FN=+A6Y_Ss+QX_=GnJ3xGfDY1iuEbbuRA@mail.gmail.com>
Subject: Test
To: [email protected]
Content-Type: text/plain; charset=UTF-8

This is a test!
""")

        ValidateAuthenticity().process(lst, msg, msgdata)

        res = ["example.com; spf=pass smtp.mailfrom=gmail.com"
               "; dkim=pass header.d=valimail.com; arc=none"]
        self.assertEqual(msg["Authentication-Results"], ''.join(res))
Example #29
0
    def setUp(self):
        global temporary_failures, permanent_failures
        del temporary_failures[:]
        del permanent_failures[:]
        self._processor = getUtility(IBounceProcessor)
        # Push a config where actual delivery is handled by a dummy function.
        # We generally don't care what this does, since we're just testing the
        # setting of the 'verp' key in the metadata.
        config.push('fake outgoing', """
       [mta]
       outgoing: mailman.runners.tests.test_outgoing.raise_SomeRecipientsFailed
        """)
        self._mlist = create_list('*****@*****.**')
        self._outq = config.switchboards['out']
        self._runner = make_testable_runner(OutgoingRunner, 'out', run_once)
        self._msg = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
Example #30
0
    def setUp(self):
        self._mlist = create_list('*****@*****.**')
        self._mlist.send_welcome_message = False
        self._bounceq = config.switchboards['bounces']
        self._runner = make_testable_runner(BounceRunner, 'bounces')
        self._anne = getUtility(IUserManager).create_address(
            '*****@*****.**')
        self._member = self._mlist.subscribe(self._anne, MemberRole.member)
        self._msg = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
        self._msgdata = dict(listid='test.example.com')
        self._processor = getUtility(IBounceProcessor)
        config.push('site owner', """
        [mailman]
        site_owner: [email protected]
        """)
        self.addCleanup(config.pop, 'site owner')
Example #31
0
    def test_nonfatal_verp_detection(self):
        # A VERPd bounce was received, but the error was nonfatal.
        nonfatal = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>
Content-Type: multipart/report; report-type=delivery-status; boundary=AAA
MIME-Version: 1.0

--AAA
Content-Type: message/delivery-status

Action: delayed
Original-Recipient: rfc822; [email protected]

--AAA--
""")
        self._bounceq.enqueue(nonfatal, self._msgdata)
        self._runner.run()
        get_queue_messages('bounces', expected_count=0)
        events = list(self._processor.events)
        self.assertEqual(len(events), 0)
Example #32
0
    def setUp(self):
        global temporary_failures, permanent_failures
        del temporary_failures[:]
        del permanent_failures[:]
        self._processor = getUtility(IBounceProcessor)
        # Push a config where actual delivery is handled by a dummy function.
        # We generally don't care what this does, since we're just testing the
        # setting of the 'verp' key in the metadata.
        config.push('fake outgoing', """
       [mta]
       outgoing: mailman.runners.tests.test_outgoing.raise_SomeRecipientsFailed
        """)
        self.addCleanup(config.pop, 'fake outgoing')
        self._mlist = create_list('*****@*****.**')
        self._outq = config.switchboards['out']
        self._runner = make_testable_runner(OutgoingRunner, 'out', run_once)
        self._msg = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
Example #33
0
    def test_nonfatal_verp_detection(self):
        # A VERPd bounce was received, but the error was nonfatal.
        nonfatal = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>
Content-Type: multipart/report; report-type=delivery-status; boundary=AAA
MIME-Version: 1.0

--AAA
Content-Type: message/delivery-status

Action: delayed
Original-Recipient: rfc822; [email protected]

--AAA--
""")
        self._bounceq.enqueue(nonfatal, self._msgdata)
        self._runner.run()
        self.assertEqual(len(get_queue_messages('bounces')), 0)
        events = list(self._processor.events)
        self.assertEqual(len(events), 0)
Example #34
0
    def test_arc_sign_message_no_chain_validation(self):
        config.push(
            'arc_sign', """
        [ARC]
        enabled: yes
        authserv_id: lists.example.org
        selector: dummy
        domain:   example.org
        privkey: %s
        """ % (self.keyfile.name))

        self.addCleanup(config.pop, 'arc_sign')

        lst = create_list('*****@*****.**')
        msgdata = {}

        msg = """Authentication-Results: lists.example.org;
        spf=pass [email protected];
        dkim=pass (1024-bit key) [email protected]; dmarc=pass
MIME-Version: 1.0
Return-Path: <*****@*****.**>
Received: by 10.157.14.6 with HTTP; Tue, 3 Jan 2017 12:22:54 -0800 (PST)
Message-ID: <*****@*****.**>
Date: Thu, 14 Jan 2015 15:00:01 -0800
From: John Q Doe <*****@*****.**>
To: [email protected]
Subject: Example 1

Hey gang,
This is a test message.
--J."""

        msg = message_from_string(msg)
        ARCSign().process(lst, msg, msgdata)

        self.assertEqual("ARC-Authentication-Results" in msg, False)
        self.assertEqual("ARC-Message-Signature" in msg, False)
        self.assertEqual("ARC-Seal" in msg, False)
Example #35
0
    def setUp(self):
        global captured_mlist, captured_msg, captured_msgdata
        # Push a config where actual delivery is handled by a dummy function.
        # We generally don't care what this does, since we're just testing the
        # setting of the 'verp' key in the metadata.
        config.push('fake outgoing', """
        [mta]
        outgoing: mailman.runners.tests.test_outgoing.capture
        """)
        self.addCleanup(config.pop, 'fake outgoing')
        # Reset the captured data.
        captured_mlist = None
        captured_msg = None
        captured_msgdata = None
        self._mlist = create_list('*****@*****.**')
        self._outq = config.switchboards['out']
        self._runner = make_testable_runner(OutgoingRunner, 'out')
        self._msg = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
Example #36
0
    def setUp(self):
        global captured_mlist, captured_msg, captured_msgdata
        # Push a config where actual delivery is handled by a dummy function.
        # We generally don't care what this does, since we're just testing the
        # setting of the 'verp' key in the metadata.
        config.push(
            'fake outgoing', """
        [mta]
        outgoing: mailman.runners.tests.test_outgoing.capture
        """)
        # Reset the captured data.
        captured_mlist = None
        captured_msg = None
        captured_msgdata = None
        self._mlist = create_list('*****@*****.**')
        self._outq = config.switchboards['out']
        self._runner = make_testable_runner(OutgoingRunner, 'out')
        self._msg = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>

""")
Example #37
0
    def test_nonverp_detectable_nonfatal_bounce(self):
        # Here's a bounce that is not VERPd, but which has a bouncing address
        # that can be parsed from a known bounce format.  The bounce is
        # non-fatal so no bounce event is registered.
        dsn = message_from_string("""\
From: [email protected]
To: [email protected]
Message-Id: <first>
Content-Type: multipart/report; report-type=delivery-status; boundary=AAA
MIME-Version: 1.0

--AAA
Content-Type: message/delivery-status

Action: delayed
Original-Recipient: rfc822; [email protected]

--AAA--
""")
        self._bounceq.enqueue(dsn, self._msgdata)
        self._runner.run()
        get_queue_messages('bounces', expected_count=0)
        events = list(self._processor.events)
        self.assertEqual(len(events), 0)
Example #38
0
    def test_arc_sign_message(self):
        config.push(
            'arc_sign', """
        [ARC]
        enabled: yes
        authserv_id: lists.example.org
        selector: dummy
        domain: example.org
        sig_headers: mime-version, date, from, to, subject
        privkey: %s
        """ % (self.keyfile.name))

        self.addCleanup(config.pop, 'arc_sign')

        lst = create_list('*****@*****.**')
        msgdata = {'ARC-Standardize': True}

        msg = """Authentication-Results: lists.example.org; arc=none;
        spf=pass [email protected];
        dkim=pass (1024-bit key) [email protected]; dmarc=pass
MIME-Version: 1.0
Return-Path: <*****@*****.**>
Received: by 10.157.14.6 with HTTP; Tue, 3 Jan 2017 12:22:54 -0800 (PST)
Message-ID: <*****@*****.**>
Date: Thu, 14 Jan 2015 15:00:01 -0800
From: John Q Doe <*****@*****.**>
To: [email protected]
Subject: Example 1

Hey gang,
This is a test message.
--J."""

        msg = message_from_string(msg)

        ARCSign().process(lst, msg, msgdata)

        res = [
            "i=1;lists.example.org;arc=none;spf=passsmtp.mfrom=jqd@d1"
            ".example;dkim=pass(1024-bitkey)[email protected];dmar"
            "c=pass"
        ]
        self.assertEqual("".join(msg["ARC-Authentication-Results"].split()),
                         "".join(res))

        sig = """a=rsa-sha256;
b=XWeK9DxQ8MUm+Me5GLZ5lQ3L49RdoFv7m7VlrAkKb3/C7jjw33TrTY0KYI5lkowvEGnAtm
5lAqLz67FxA/VrJc2JiYFQR/mBoJLLz/hh9y77byYmSO9tLfIDe2A83+6QsXHO3K6PxTz7+v
rCB4wHD9GADeUKVfHzmpZhFuYOa88=;
bh=KWSe46TZKCcDbH4klJPo+tjk5LWJnVRlP5pvjXFZYLQ=; c=relaxed/relaxed;
d=example.org; h=mime-version:date:from:to:subject;
i=1; s=dummy; t=12345"""
        sig = set("".join(sig.split()).split(";"))
        expected = "".join(msg["ARC-Message-Signature"].split()).split(";")
        expected = set(expected)
        self.assertEqual(sig, expected)

        seal = "".join([
            "a=rsa-sha256;b=Pg8Yyk1AgYy2l+kb6iy+mY106AXm5EdgDwJ"
            "hLP7+XyT6yaS38ZUho+bmgSDorV+LyARH4A967A/oWMX3coyC7"
            "pAGyI+hA3+JifL7P3/aIVP4ooRJ/WUgT79snPuulxE15jg6FgQ"
            "E68ObA1/hy77BxdbD9EQxFGNcr/wCKQoeKJ8=; cv=none; d="
            "example.org; i=1; s=dummy; t=12345"
        ])
        seal = set("".join(seal.split()).split(";"))
        expected = set("".join(msg["ARC-Seal"].split()).split(";"))
        self.assertEqual(seal, expected)