From e116cfac469673fad8446d93cddecdfdf6344039 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 13 May 2011 10:25:38 +0200 Subject: Add bounce registration and bounce events. --- src/mailman/interfaces/bounce.py | 48 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) (limited to 'src/mailman/interfaces/bounce.py') diff --git a/src/mailman/interfaces/bounce.py b/src/mailman/interfaces/bounce.py index 22e2467b8..e6d9e8ccd 100644 --- a/src/mailman/interfaces/bounce.py +++ b/src/mailman/interfaces/bounce.py @@ -22,12 +22,13 @@ from __future__ import absolute_import, unicode_literals __metaclass__ = type __all__ = [ 'IBounceDetector', + 'IBounceEvent', + 'IBounceProcessor', 'Stop', ] -from flufl.enum import Enum -from zope.interface import Interface +from zope.interface import Attribute, Interface @@ -52,3 +53,46 @@ class IBounceDetector(Interface): returned to halt any bounce processing pipeline. :rtype: A set strings, or `Stop` """ + + + +class IBounceEvent(Interface): + """Registration record for a single bounce event.""" + + list_name = Attribute( + """The name of the mailing list that received this bounce.""") + + email = Attribute( + """The email address that bounced.""") + + timestamp = Attribute( + """The timestamp for when the bounce was received.""") + + message_id = Attribute( + """The Message-ID of the bounce message.""") + + where = Attribute( + """Where was the bounce detected?""") + + processed = Attribute( + """Has this bounce event been processed?""") + + + +class IBounceProcessor(Interface): + """Manager/processor of bounce events.""" + + def register(mlist, email, msg, where=None): + """Register a bounce event. + + :param mlist: The mailing list that the bounce occurred on. + :type mlist: IMailingList + :param email: The email address that is bouncing. + :type email: str + :param msg: The bounce message. + :type msg: email.message.Message + :param where: A description of where the bounce was detected. + :type where: str + :return: The registered bounce event. + :rtype: IBounceEvent + """ -- cgit v1.2.3-70-g09d2 From 2cf1012747a2553b030f3c435b12701ea4441afc Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 13 May 2011 16:16:11 +0200 Subject: * BounceEvent.where -> BounceEvent.context * Add BounceContext enum --- src/mailman/interfaces/bounce.py | 25 +++++++++++++++++++++---- src/mailman/model/bounce.py | 10 ++++++---- src/mailman/model/docs/bounce.rst | 24 ++++++++++++++++-------- 3 files changed, 43 insertions(+), 16 deletions(-) (limited to 'src/mailman/interfaces/bounce.py') diff --git a/src/mailman/interfaces/bounce.py b/src/mailman/interfaces/bounce.py index e6d9e8ccd..168ca7ee0 100644 --- a/src/mailman/interfaces/bounce.py +++ b/src/mailman/interfaces/bounce.py @@ -21,6 +21,7 @@ from __future__ import absolute_import, unicode_literals __metaclass__ = type __all__ = [ + 'BounceContext', 'IBounceDetector', 'IBounceEvent', 'IBounceProcessor', @@ -28,6 +29,7 @@ __all__ = [ ] +from flufl.enum import Enum from zope.interface import Attribute, Interface @@ -39,6 +41,19 @@ from zope.interface import Attribute, Interface Stop = object() + +class BounceContext(Enum): + """The context in which the bounce was detected.""" + + # This is a normal bounce detection. IOW, Mailman received a bounce in + # response to a mailing list post. + normal = 1 + + # A probe email bounced. This can be considered a bit more serious, since + # it occurred in response to a specific message to a specific user. + probe = 2 + + class IBounceDetector(Interface): """Detect a bounce in an email message.""" @@ -71,7 +86,7 @@ class IBounceEvent(Interface): message_id = Attribute( """The Message-ID of the bounce message.""") - where = Attribute( + context = Attribute( """Where was the bounce detected?""") processed = Attribute( @@ -82,7 +97,7 @@ class IBounceEvent(Interface): class IBounceProcessor(Interface): """Manager/processor of bounce events.""" - def register(mlist, email, msg, where=None): + def register(mlist, email, msg, context=None): """Register a bounce event. :param mlist: The mailing list that the bounce occurred on. @@ -91,8 +106,10 @@ class IBounceProcessor(Interface): :type email: str :param msg: The bounce message. :type msg: email.message.Message - :param where: A description of where the bounce was detected. - :type where: str + :param context: In what context was the bounce detected? The default + is 'normal' context (i.e. we received a normal bounce for the + address). + :type context: BounceContext :return: The registered bounce event. :rtype: IBounceEvent """ diff --git a/src/mailman/model/bounce.py b/src/mailman/model/bounce.py index 855fb472f..8abe3d149 100644 --- a/src/mailman/model/bounce.py +++ b/src/mailman/model/bounce.py @@ -29,8 +29,10 @@ __all__ = [ from storm.locals import Bool, Int, DateTime, Unicode from zope.interface import implements -from mailman.interfaces.bounce import IBounceEvent, IBounceProcessor +from mailman.interfaces.bounce import ( + BounceContext, IBounceEvent, IBounceProcessor) from mailman.database.model import Model +from mailman.database.types import Enum from mailman.utilities.datetime import now @@ -43,15 +45,15 @@ class BounceEvent(Model): email = Unicode() timestamp = DateTime() message_id = Unicode() - where = Unicode() + context = Enum() processed = Bool() - def __init__(self, list_name, email, msg, where): + def __init__(self, list_name, email, msg, context=None): self.list_name = list_name self.email = email self.timestamp = now() self.message_id = msg['message-id'] - self.where = where + self.context = (BounceContext.normal if context is None else context) self.processed = False diff --git a/src/mailman/model/docs/bounce.rst b/src/mailman/model/docs/bounce.rst index 6c59a68ee..41784cd9c 100644 --- a/src/mailman/model/docs/bounce.rst +++ b/src/mailman/model/docs/bounce.rst @@ -56,21 +56,29 @@ Bounce events have a flag indicating whether they've been processed or not. >>> event.processed False -When a bounce is registered, you can also include an informative string which -indicates where the bounce was detected. This is essentially a semantics-free -field. -:: +When a bounce is registered, you can indicate the bounce context. >>> msg = message_from_string("""\ ... From: mail-daemon@example.org ... To: test-bounces@example.com ... Message-ID: - ... + ... ... """) +If no context is given, then a default one is used. + + >>> event = processor.register(mlist, 'bart@example.com', msg) + >>> print event.message_id + + >>> print event.context + BounceContext.normal + +A probe bounce carries more weight than just a normal bounce. + + >>> from mailman.interfaces.bounce import BounceContext >>> event = processor.register( - ... mlist, 'bart@example.com', msg, 'Some place') + ... mlist, 'bart@example.com', msg, BounceContext.probe) >>> print event.message_id - >>> print event.where - Some place + >>> print event.context + BounceContext.probe -- cgit v1.2.3-70-g09d2