Пример #1
0
 def test_maybe_forward_discard(self):
     # When forward_unrecognized_bounces_to is set to discard, no bounce
     # messages are forwarded.
     self._mlist.forward_unrecognized_bounces_to = (
         UnrecognizedBounceDisposition.discard)
     # The only artifact of this call is a log file entry.
     mark = LogFileMark('mailman.bounce')
     maybe_forward(self._mlist, self._msg)
     get_queue_messages('virgin', expected_count=0)
     line = mark.readline()
     self.assertEqual(line[-40:-1],
                      'Discarding unrecognized bounce: <first>')
Пример #2
0
 def test_maybe_forward_discard(self):
     # When forward_unrecognized_bounces_to is set to discard, no bounce
     # messages are forwarded.
     self._mlist.forward_unrecognized_bounces_to = (
         UnrecognizedBounceDisposition.discard)
     # The only artifact of this call is a log file entry.
     mark = LogFileMark('mailman.bounce')
     maybe_forward(self._mlist, self._msg)
     get_queue_messages('virgin', expected_count=0)
     line = mark.readline()
     self.assertEqual(
         line[-40:-1],
         'Discarding unrecognized bounce: <first>')
Пример #3
0
    def test_maybe_forward_list_owner(self):
        # Set up some owner and moderator addresses.
        user_manager = getUtility(IUserManager)
        anne = user_manager.create_address('*****@*****.**')
        bart = user_manager.create_address('*****@*****.**')
        cris = user_manager.create_address('*****@*****.**')
        dave = user_manager.create_address('*****@*****.**')
        # Regular members.
        elle = user_manager.create_address('*****@*****.**')
        fred = user_manager.create_address('*****@*****.**')
        self._mlist.subscribe(anne, MemberRole.owner)
        self._mlist.subscribe(bart, MemberRole.owner)
        self._mlist.subscribe(cris, MemberRole.moderator)
        self._mlist.subscribe(dave, MemberRole.moderator)
        self._mlist.subscribe(elle, MemberRole.member)
        self._mlist.subscribe(fred, MemberRole.member)
        # When forward_unrecognized_bounces_to is set to owners, the
        # bounce is forwarded to the list owners and moderators.
        self._mlist.forward_unrecognized_bounces_to = (
            UnrecognizedBounceDisposition.administrators)
        maybe_forward(self._mlist, self._msg)
        items = get_queue_messages('virgin', expected_count=1)
        msg = items[0].msg
        self.assertEqual(msg['subject'], 'Uncaught bounce notification')
        self.assertEqual(msg['from'], '*****@*****.**')
        self.assertEqual(msg['to'], '*****@*****.**')
        # The first attachment is a notification message with a url.
        payload = msg.get_payload(0)
        self.assertEqual(payload.get_content_type(), 'text/plain')
        body = payload.get_payload()
        self.assertMultiLineEqual(
            body, """\
The attached message was received as a bounce, but either the bounce format
was not recognized, or no member addresses could be extracted from it.  This
mailing list has been configured to send all unrecognized bounce messages to
the list administrator(s).
""")
        # The second attachment should be a message/rfc822 containing the
        # original bounce message.
        payload = msg.get_payload(1)
        self.assertEqual(payload.get_content_type(), 'message/rfc822')
        bounce = payload.get_payload(0)
        self.assertEqual(bounce.as_string(), self._msg.as_string())
        # All of the owners and moderators, but none of the members, should be
        # recipients of this message.
        self.assertEqual(
            items[0].msgdata['recipients'],
            set([
                '*****@*****.**', '*****@*****.**', '*****@*****.**',
                '*****@*****.**'
            ]))
Пример #4
0
 def _dispose(self, mlist, msg, msgdata):
     # List isn't doing bounce processing?
     if not mlist.process_bounces:
         return False
     # Try VERP detection first, since it's quick and easy
     context = BounceContext.normal
     addresses = StandardVERP().get_verp(mlist, msg)
     if len(addresses) > 0:
         # Scan the message to see if it contained permanent or temporary
         # failures.  We'll ignore temporary failures, but even if there
         # are no permanent failures, we'll assume VERP bounces are
         # permanent.
         temporary, permanent = all_failures(msg)
         if len(temporary) > 0:
             # This was a temporary failure, so just ignore it.
             return False
     else:
         # See if this was a probe message.
         addresses = ProbeVERP().get_verp(mlist, msg)
         if len(addresses) > 0:
             context = BounceContext.probe
         else:
             # That didn't give us anything useful, so try the old fashion
             # bounce matching modules.  Since Mailman currently doesn't
             # score temporary failures, if we get no permanent failures,
             # we're done, but we do need to check for temporary failures
             # to know if the bounce was recognized.
             temporary, addresses = all_failures(msg)
             if len(addresses) == 0 and len(temporary) > 0:
                 # This is a recognized temp fail so ignore it.
                 return False
     # If that still didn't return us any useful addresses, then send it on
     # or discard it.  The addresses will come back from flufl.bounce as
     # bytes/8-bit strings, but we must store them as unicodes in the
     # database.  Assume utf-8 encoding, but be cautious.
     if len(addresses) > 0:
         for address in addresses:
             if isinstance(address, bytes):
                 try:
                     address = address.decode('utf-8')
                 except UnicodeError:
                     log.exception('Ignoring non-UTF-8 encoded '
                                   'address: {}'.format(address))
                     continue
             self._processor.register(mlist, address, msg, context)
     else:
         log.info('Bounce message w/no discernable addresses: %s',
                  msg.get('message-id', 'n/a'))
         maybe_forward(mlist, msg)
     # Dequeue this message.
     return False
Пример #5
0
 def _dispose(self, mlist, msg, msgdata):
     # List isn't doing bounce processing?
     if not mlist.process_bounces:
         return False
     # Try VERP detection first, since it's quick and easy
     context = BounceContext.normal
     addresses = StandardVERP().get_verp(mlist, msg)
     if len(addresses) > 0:
         # Scan the message to see if it contained permanent or temporary
         # failures.  We'll ignore temporary failures, but even if there
         # are no permanent failures, we'll assume VERP bounces are
         # permanent.
         temporary, permanent = all_failures(msg)
         if len(temporary) > 0:
             # This was a temporary failure, so just ignore it.
             return False
     else:
         # See if this was a probe message.
         addresses = ProbeVERP().get_verp(mlist, msg)
         if len(addresses) > 0:
             context = BounceContext.probe
         else:
             # That didn't give us anything useful, so try the old fashion
             # bounce matching modules.  This returns only the permanently
             # failing addresses.  Since Mailman currently doesn't score
             # temporary failures, if we get no permanent failures, we're
             # done.s
             addresses = scan_message(msg)
     # If that still didn't return us any useful addresses, then send it on
     # or discard it.  The addresses will come back from flufl.bounce as
     # bytes/8-bit strings, but we must store them as unicodes in the
     # database.  Assume utf-8 encoding, but be cautious.
     if len(addresses) > 0:
         for address in addresses:
             if isinstance(address, bytes):
                 try:
                     address = address.decode('utf-8')
                 except UnicodeError:
                     log.exception('Ignoring non-UTF-8 encoded '
                                   'address: {}'.format(address))
                     continue
             self._processor.register(mlist, address, msg, context)
     else:
         log.info('Bounce message w/no discernable addresses: %s',
                  msg.get('message-id', 'n/a'))
         maybe_forward(mlist, msg)
     # Dequeue this message.
     return False
Пример #6
0
 def test_maybe_forward_list_owner(self):
     # Set up some owner and moderator addresses.
     user_manager = getUtility(IUserManager)
     anne = user_manager.create_address('*****@*****.**')
     bart = user_manager.create_address('*****@*****.**')
     cris = user_manager.create_address('*****@*****.**')
     dave = user_manager.create_address('*****@*****.**')
     # Regular members.
     elle = user_manager.create_address('*****@*****.**')
     fred = user_manager.create_address('*****@*****.**')
     self._mlist.subscribe(anne, MemberRole.owner)
     self._mlist.subscribe(bart, MemberRole.owner)
     self._mlist.subscribe(cris, MemberRole.moderator)
     self._mlist.subscribe(dave, MemberRole.moderator)
     self._mlist.subscribe(elle, MemberRole.member)
     self._mlist.subscribe(fred, MemberRole.member)
     # When forward_unrecognized_bounces_to is set to owners, the
     # bounce is forwarded to the list owners and moderators.
     self._mlist.forward_unrecognized_bounces_to = (
         UnrecognizedBounceDisposition.administrators)
     maybe_forward(self._mlist, self._msg)
     items = get_queue_messages('virgin')
     self.assertEqual(len(items), 1)
     msg = items[0].msg
     self.assertEqual(msg['subject'], 'Uncaught bounce notification')
     self.assertEqual(msg['from'], '*****@*****.**')
     self.assertEqual(msg['to'], '*****@*****.**')
     # The first attachment is a notification message with a url.
     payload = msg.get_payload(0)
     self.assertEqual(payload.get_content_type(), 'text/plain')
     body = payload.get_payload()
     self.assertEqual(
         body.splitlines()[-1],
         'http://lists.example.com/admin/[email protected]/bounce')
     # The second attachment should be a message/rfc822 containing the
     # original bounce message.
     payload = msg.get_payload(1)
     self.assertEqual(payload.get_content_type(), 'message/rfc822')
     bounce = payload.get_payload(0)
     self.assertEqual(bounce.as_string(), self._msg.as_string())
     # All of the owners and moderators, but none of the members, should be
     # recipients of this message.
     self.assertEqual(items[0].msgdata['recipients'],
                      set(['*****@*****.**', '*****@*****.**',
                           '*****@*****.**', '*****@*****.**']))
Пример #7
0
 def test_maybe_forward_list_owner(self):
     # Set up some owner and moderator addresses.
     user_manager = getUtility(IUserManager)
     anne = user_manager.create_address('*****@*****.**')
     bart = user_manager.create_address('*****@*****.**')
     cris = user_manager.create_address('*****@*****.**')
     dave = user_manager.create_address('*****@*****.**')
     # Regular members.
     elle = user_manager.create_address('*****@*****.**')
     fred = user_manager.create_address('*****@*****.**')
     self._mlist.subscribe(anne, MemberRole.owner)
     self._mlist.subscribe(bart, MemberRole.owner)
     self._mlist.subscribe(cris, MemberRole.moderator)
     self._mlist.subscribe(dave, MemberRole.moderator)
     self._mlist.subscribe(elle, MemberRole.member)
     self._mlist.subscribe(fred, MemberRole.member)
     # When forward_unrecognized_bounces_to is set to owners, the
     # bounce is forwarded to the list owners and moderators.
     self._mlist.forward_unrecognized_bounces_to = (
         UnrecognizedBounceDisposition.administrators)
     maybe_forward(self._mlist, self._msg)
     items = get_queue_messages('virgin')
     self.assertEqual(len(items), 1)
     msg = items[0].msg
     self.assertEqual(msg['subject'], 'Uncaught bounce notification')
     self.assertEqual(msg['from'], '*****@*****.**')
     self.assertEqual(msg['to'], '*****@*****.**')
     # The first attachment is a notification message with a url.
     payload = msg.get_payload(0)
     self.assertEqual(payload.get_content_type(), 'text/plain')
     body = payload.get_payload()
     self.assertEqual(
         body.splitlines()[-1],
         'http://lists.example.com/admin/[email protected]/bounce')
     # The second attachment should be a message/rfc822 containing the
     # original bounce message.
     payload = msg.get_payload(1)
     self.assertEqual(payload.get_content_type(), 'message/rfc822')
     bounce = payload.get_payload(0)
     self.assertEqual(bounce.as_string(), self._msg.as_string())
     # All of the owners and moderators, but none of the members, should be
     # recipients of this message.
     self.assertEqual(items[0].msgdata['recipients'],
                      set(['*****@*****.**', '*****@*****.**',
                           '*****@*****.**', '*****@*****.**']))