summaryrefslogtreecommitdiff
path: root/Mailman/app/membership.py
blob: 6d2583098db0067bea5c4f53d2e7a33c308da899 (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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# Copyright (C) 2007-2008 by the Free Software Foundation, Inc.
#
# This program 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 2
# of the License, or (at your option) any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.

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

from __future__ import with_statement

from email.utils import formataddr

from Mailman import Errors
from Mailman import Message
from Mailman import Utils
from Mailman import i18n
from Mailman.configuration import config
from Mailman.interfaces import DeliveryMode, MemberRole

_ = i18n._
__i18n_templates__ = True



def add_member(mlist, address, realname, password, delivery_mode, language,
               ack=None, admin_notif=None, text=''):
    """Add a member right now.

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

    ack is a flag that specifies whether the user should get an
    acknowledgement of their being subscribed.  Default is to use the
    list's default flag value.

    admin_notif is a flag that specifies whether the list owner should get
    an acknowledgement of this subscription.  Default is to use the list's
    default flag value.
    """
    # Set up default flag values
    if ack is None:
        ack = mlist.send_welcome_msg
    if admin_notif is None:
        admin_notif = mlist.admin_notify_mchanges
    # Let's be extra cautious.
    Utils.ValidateEmail(address)
    if mlist.members.get_member(address) is not None:
        raise Errors.AlreadySubscribedError(address)
    # Check for banned address here too for admin mass subscribes and
    # confirmations.
    pattern = Utils.get_pattern(address, mlist.ban_list)
    if pattern:
        raise Errors.MembershipIsBanned(pattern)
    # Do the actual addition.  First, see if there's already a user linked
    # with the given address.
    user = config.db.user_manager.get_user(address)
    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_obj = config.db.user_manager.get_address(address)
        if address_obj is None:
            # Nope, we don't even know about this address, so create both the
            # user and address now.
            user = config.db.user_manager.create_user(address, realname)
            # Do it this way so we don't have to flush the previous change.
            address_obj = 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 = config.db.user_manager.create_user()
            user.real_name = (realname if realname else address_obj.real_name)
            user.link(address_obj)
        # Since created the user, then the member,  and set preferences on the
        # appropriate object.
        user.password = password
        user.preferences.preferred_language = language
        member = address_obj.subscribe(mlist, MemberRole.member)
        member.preferences.delivery_mode = delivery_mode
    else:
        # The user exists and is linked to the address.
        for address_obj in user.addresses:
            if address_obj.address == address:
                break
        else:
            raise AssertionError(
                'User should have had linked address: %s', address)
        # Create the member and set the appropriate preferences.
        member = address_obj.subscribe(mlist, MemberRole.member)
        member.preferences.preferred_language = language
        member.preferences.delivery_mode = delivery_mode
##     mlist.setMemberOption(email, config.Moderate,
##                          mlist.default_member_moderation)
    # Send notifications.
    if ack:
        send_welcome_message(mlist, address, language, delivery_mode, text)
    if admin_notif:
        with i18n.using_language(mlist.preferred_language):
            subject = _('$mlist.real_name subscription notification')
        if isinstance(realname, unicode):
            realname = realname.encode(Utils.GetCharSet(language), 'replace')
        text = Utils.maketext(
            'adminsubscribeack.txt',
            {'listname' : mlist.real_name,
             'member'   : formataddr((realname, address)),
             }, mlist=mlist)
        msg = Message.OwnerNotification(mlist, subject, text)
        msg.send(mlist)



def send_welcome_message(mlist, address, language, delivery_mode, text=''):
    if mlist.welcome_msg:
        welcome = Utils.wrap(mlist.welcome_msg) + '\n'
    else:
        welcome = ''
    # Find the IMember object which is subscribed to the mailing list, because
    # from there, we can get the member's options url.
    member = mlist.members.get_member(address)
    options_url = member.options_url
    # Get the text from the template.
    text += Utils.maketext(
        'subscribeack.txt', {
            'real_name'         : mlist.real_name,
            'posting_address'   : mlist.fqdn_listname,
            'listinfo_url'      : mlist.script_url('listinfo'),
            'optionsurl'        : options_url,
            'request_address'   : mlist.request_address,
            'welcome'           : welcome,
            }, lang=language, mlist=mlist)
    if delivery_mode is not DeliveryMode.regular:
        digmode = _(' (Digest mode)')
    else:
        digmode = ''
    msg = Message.UserNotification(
        address, mlist.request_address,
        _('Welcome to the "$mlist.real_name" mailing list${digmode}'),
        text, language)
    msg['X-No-Archive'] = 'yes'
    msg.send(mlist, verp=config.VERP_PERSONALIZED_DELIVERIES)



def delete_member(mlist, address, admin_notif=None, userack=None):
    if userack is None:
        userack = mlist.send_goodbye_msg
    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(address)
    language = member.preferred_language
    member.unsubscribe()
    # And send an acknowledgement to the user...
    if userack:
        send_goodbye_message(mlist, address, language)
    # ...and to the administrator.
    if admin_notif:
        user = config.db.user_manager.get_user(address)
        realname = user.real_name
        subject = _('$mlist.real_name unsubscription notification')
        text = Utils.maketext(
            'adminunsubscribeack.txt',
            {'listname': mlist.real_name,
             'member'  : formataddr((realname, address)),
             }, mlist=mlist)
        msg = Message.OwnerNotification(mlist, subject, text)
        msg.send(mlist)



def send_goodbye_message(mlist, address, language):
    if mlist.goodbye_msg:
        goodbye = Utils.wrap(mlist.goodbye_msg) + '\n'
    else:
        goodbye = ''
    msg = Message.UserNotification(
        address, mlist.bounces_address,
        _('You have been unsubscribed from the $mlist.real_name mailing list'),
        goodbye, language)
    msg.send(mlist, verp=config.VERP_PERSONALIZED_DELIVERIES)