~nkarageuzian/mailman/bug-1312884

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
====================
The pending database
====================

The pending database is where various types of events which need confirmation
are stored.  These can include email address registration events, held
messages (but only for user confirmation), auto-approvals, and probe bounces.
This is not where messages held for administrator approval are kept.

In order to pend an event, you first need a pending database.

    >>> from mailman.interfaces.pending import IPendings
    >>> from zope.component import getUtility
    >>> pendingdb = getUtility(IPendings)

The pending database can add any ``IPendable`` to the database, returning a
token that can be used in urls and such.
::

    >>> from zope.interface import implementer
    >>> from mailman.interfaces.pending import IPendable
    >>> @implementer(IPendable)
    ... class SimplePendable(dict):
    ...     pass

    >>> subscription = SimplePendable(
    ...     type='subscription',
    ...     address='aperson@example.com',
    ...     display_name='Anne Person',
    ...     language='en',
    ...     password='xyz')
    >>> token = pendingdb.add(subscription)
    >>> len(token)
    40

There's not much you can do with tokens except to `confirm` them, which
basically means returning the ``IPendable`` structure (as a dictionary) from
the database that matches the token.  If the token isn't in the database, None
is returned.

    >>> pendable = pendingdb.confirm(bytes('missing'))
    >>> print(pendable)
    None
    >>> pendable = pendingdb.confirm(token)
    >>> dump_msgdata(pendable)
    address     : aperson@example.com
    display_name: Anne Person
    language    : en
    password    : xyz
    type        : subscription

After confirmation, the token is no longer in the database.

    >>> print(pendingdb.confirm(token))
    None

There are a few other things you can do with the pending database.  When you
confirm a token, you can leave it in the database, or in other words, not
expunge it.

    >>> event_1 = SimplePendable(type='one')
    >>> token_1 = pendingdb.add(event_1)
    >>> event_2 = SimplePendable(type='two')
    >>> token_2 = pendingdb.add(event_2)
    >>> event_3 = SimplePendable(type='three')
    >>> token_3 = pendingdb.add(event_3)
    >>> pendable = pendingdb.confirm(token_1, expunge=False)
    >>> dump_msgdata(pendable)
    type: one
    >>> pendable = pendingdb.confirm(token_1, expunge=True)
    >>> dump_msgdata(pendable)
    type: one
    >>> print(pendingdb.confirm(token_1))
    None

An event can be given a lifetime when it is pended, otherwise it just uses a
default lifetime.

    >>> from datetime import timedelta
    >>> yesterday = timedelta(days=-1)
    >>> event_4 = SimplePendable(type='four')
    >>> token_4 = pendingdb.add(event_4, lifetime=yesterday)

Every once in a while the pending database is cleared of old records.

    >>> pendingdb.evict()
    >>> print(pendingdb.confirm(token_4))
    None
    >>> pendable = pendingdb.confirm(token_2)
    >>> dump_msgdata(pendable)
    type: two