summaryrefslogtreecommitdiff
path: root/Mailman/queue/docs/outgoing.txt
blob: 7b5ba6f540f06fa788f51aa2de384847840b5eb9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
The outgoing handler
====================

Mailman's outgoing queue is used as the wrapper around SMTP delivery to the
upstream mail server.  The ToOutgoing handler does little more than drop the
message into the outgoing queue, after calculating whether the message should
be VERP'd or not.  VERP means Variable Envelope Return Path; we're using that
term somewhat incorrectly, but within the spirit of the standard, which
basically describes how to encode the recipient's address in the originator
headers for unambigous bounce processing.

    >>> from Mailman.handlers.to_outgoing import process
    >>> from Mailman.queue import Switchboard
    >>> from Mailman.configuration import config
    >>> mlist = config.db.list_manager.create(u'_xtest@example.com')
    >>> switchboard = Switchboard(config.OUTQUEUE_DIR)

    >>> def queue_size():
    ...     size = len(switchboard.files)
    ...     for filebase in switchboard.files:
    ...         msg, msgdata = switchboard.dequeue(filebase)
    ...         switchboard.finish(filebase)
    ...     return size

Craft a message destined for the outgoing queue.  Include some random metadata
as if this message had passed through some other handlers.

    >>> msg = message_from_string("""\
    ... Subject: Here is a message
    ...
    ... Something of great import.
    ... """)

When certain conditions are met, the message will be VERP'd.  For example, if
the message metadata already has a VERP key, this message will be VERP'd.

    >>> msgdata = dict(foo=1, bar=2, verp=True)
    >>> process(mlist, msg, msgdata)
    >>> print msg.as_string()
    Subject: Here is a message
    <BLANKLINE>
    Something of great import.
    >>> msgdata['verp']
    True

While the queued message will not be changed, the queued metadata will have an
additional key set: the mailing list name.

    >>> filebase = switchboard.files[0]
    >>> qmsg, qmsgdata = switchboard.dequeue(filebase)
    >>> switchboard.finish(filebase)
    >>> print qmsg.as_string()
    Subject: Here is a message
    <BLANKLINE>
    Something of great import.
    >>> sorted(qmsgdata.items())    
    [('_parsemsg', False),
     ('bar', 2), ('foo', 1),
     ('listname', u'_xtest@example.com'),
     ('received_time', ...),
     ('verp', True), ('version', 3)]
    >>> queue_size()
    0

If the list is set to personalize deliveries, and the global configuration
option to VERP personalized deliveries is set, then the message will be
VERP'd.

    # Save the original value for clean up.
    >>> verp_personalized_delivieries = config.VERP_PERSONALIZED_DELIVERIES
    >>> config.VERP_PERSONALIZED_DELIVERIES = True
    >>> from Mailman.interfaces import Personalization
    >>> mlist.personalize = Personalization.individual
    >>> msgdata = dict(foo=1, bar=2)
    >>> process(mlist, msg, msgdata)
    >>> msgdata['verp']
    True
    >>> queue_size()
    1

However, if the global configuration variable prohibits VERP'ing, even
personalized lists will not VERP.

    >>> config.VERP_PERSONALIZED_DELIVERIES = False
    >>> msgdata = dict(foo=1, bar=2)
    >>> process(mlist, msg, msgdata)
    >>> print msgdata.get('verp')
    None
    >>> queue_size()
    1

If the list is not personalized, then the message may still be VERP'd based on
the global configuration variable VERP_DELIVERY_INTERVAL.  This variable tells
Mailman how often to VERP even non-personalized mailing lists.  It can be set
to zero, which means non-personalized messages will never be VERP'd.

    # Save the original value for clean up.
    >>> verp_delivery_interval = config.VERP_DELIVERY_INTERVAL
    >>> config.VERP_DELIVERY_INTERVAL = 0
    >>> mlist.personalize = Personalization.none
    >>> msgdata = dict(foo=1, bar=2)
    >>> process(mlist, msg, msgdata)
    >>> print msgdata.get('verp')
    None
    >>> queue_size()
    1

If the interval is set to 1, then every message will be VERP'd.

    >>> config.VERP_DELIVERY_INTERVAL = 1
    >>> for i in range(10):
    ...     msgdata = dict(foo=1, bar=2)
    ...     process(mlist, msg, msgdata)
    ...     print i, msgdata['verp']
    0 True
    1 True
    2 True
    3 True
    4 True
    5 True
    6 True
    7 True
    8 True
    9 True
    >>> queue_size()
    10

If the interval is set to some other number, then one out of that many posts
will be VERP'd.

    >>> config.VERP_DELIVERY_INTERVAL = 3
    >>> for i in range(10):
    ...     mlist.post_id = i
    ...     msgdata = dict(foo=1, bar=2)
    ...     process(mlist, msg, msgdata)
    ...     print i, msgdata.get('verp', False)
    0 True
    1 False
    2 False
    3 True
    4 False
    5 False
    6 True
    7 False
    8 False
    9 True
    >>> queue_size()
    10


Clean up
========

    >>> config.VERP_PERSONALIZED_DELIVERIES = verp_personalized_delivieries
    >>> config.VERP_DELIVERY_INTERVAL = verp_delivery_interval