~sumanah/mailman/mailman

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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# Copyright (C) 2007-2015 by the Free Software Foundation, Inc.
#
# This file is part of GNU Mailman.
#
# GNU Mailman is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# GNU Mailman.  If not, see <http://www.gnu.org/licenses/>.

"""Application support for membership management."""

__all__ = [
    'add_member',
    'delete_member',
    'handle_SubscriptionEvent',
    ]


from email.utils import formataddr
from mailman.app.notifications import (
    send_goodbye_message, send_welcome_message)
from mailman.config import config
from mailman.core.i18n import _
from mailman.email.message import OwnerNotification
from mailman.interfaces.bans import IBanManager
from mailman.interfaces.member import (
    MemberRole, MembershipIsBannedError, NotAMemberError, SubscriptionEvent)
from mailman.interfaces.usermanager import IUserManager
from mailman.utilities.i18n import make
from zope.component import getUtility



def add_member(mlist, email, display_name, password, delivery_mode, language,
               role=MemberRole.member):
    """Add a member right now.

    The member's subscription must be approved by whatever policy the list
    enforces.

    :param mlist: The mailing list to add the member to.
    :type mlist: `IMailingList`
    :param email: The email address to subscribe.
    :type email: str
    :param display_name: The subscriber's full name.
    :type display_name: str
    :param password: The subscriber's plain text password.
    :type password: str
    :param delivery_mode: The delivery mode the subscriber has chosen.
    :type delivery_mode: DeliveryMode
    :param language: The language that the subscriber is going to use.
    :type language: str
    :param role: The membership role for this subscription.
    :type role: `MemberRole`
    :return: The just created member.
    :rtype: `IMember`
    :raises AlreadySubscribedError: if the user is already subscribed to
        the mailing list.
    :raises InvalidEmailAddressError: if the email address is not valid.
    :raises MembershipIsBannedError: if the membership is not allowed.
    """
    # Check to see if the email address is banned.
    if IBanManager(mlist).is_banned(email):
        raise MembershipIsBannedError(mlist, email)
    # See if there's already a user linked with the given address.
    user_manager = getUtility(IUserManager)
    user = user_manager.get_user(email)
    if user is None:
        # A user linked to this address does not yet exist.  Is the address
        # itself known but just not linked to a user?
        address = user_manager.get_address(email)
        if address is None:
            # Nope, we don't even know about this address, so create both the
            # user and address now.
            user = user_manager.create_user(email, display_name)
            # Do it this way so we don't have to flush the previous change.
            address = list(user.addresses)[0]
        else:
            # The address object exists, but it's not linked to a user.
            # Create the user and link it now.
            user = user_manager.create_user()
            user.display_name = (
                display_name if display_name else address.display_name)
            user.link(address)
        # Encrypt the password using the currently selected hash scheme.
        user.password = config.password_context.encrypt(password)
        user.preferences.preferred_language = language
        member = mlist.subscribe(address, role)
        member.preferences.delivery_mode = delivery_mode
    else:
        # The user exists and is linked to the address.
        for address in user.addresses:
            if address.email == email:
                break
        else:
            raise AssertionError(
                'User should have had linked address: {0}'.format(address))
        # Create the member and set the appropriate preferences.
        member = mlist.subscribe(address, role)
        member.preferences.preferred_language = language
        member.preferences.delivery_mode = delivery_mode
    return member



def delete_member(mlist, email, admin_notif=None, userack=None):
    """Delete a member right now.

    :param mlist: The mailing list to remove the member from.
    :type mlist: `IMailingList`
    :param email: The email address to unsubscribe.
    :type email: string
    :param admin_notif: Whether the list administrator should be notified that
        this member was deleted.
    :type admin_notif: bool, or None to let the mailing list's
        `admin_notify_mchange` attribute decide.
    :raises NotAMemberError: if the address is not a member of the
        mailing list.
    """
    if userack is None:
        userack = mlist.send_goodbye_message
    if admin_notif is None:
        admin_notif = mlist.admin_notify_mchanges
    # Delete a member, for which we know the approval has been made.
    member = mlist.members.get_member(email)
    if member is None:
        raise NotAMemberError(mlist, email)
    language = member.preferred_language
    member.unsubscribe()
    # And send an acknowledgement to the user...
    if userack:
        send_goodbye_message(mlist, email, language)
    # ...and to the administrator.
    if admin_notif:
        user = getUtility(IUserManager).get_user(email)
        display_name = user.display_name
        subject = _('$mlist.display_name unsubscription notification')
        text = make('adminunsubscribeack.txt',
                    mailing_list=mlist,
                    listname=mlist.display_name,
                    member=formataddr((display_name, email)),
                    )
        msg = OwnerNotification(mlist, subject, text,
                                roster=mlist.administrators)
        msg.send(mlist)



def handle_SubscriptionEvent(event):
    if not isinstance(event, SubscriptionEvent):
        return
    # Only send a notification message if the mailing list is configured to do
    # so, and the member being added is a list member (as opposed to a
    # moderator, non-member, or owner).
    member = event.member
    if member.role is not MemberRole.member:
        return
    mlist = member.mailing_list
    if not mlist.send_welcome_message:
        return
    send_welcome_message(mlist, member, member.preferred_language)