1 # Copyright (C) 2007-2015 by the Free Software Foundation, Inc.
3 # This file is part of GNU Mailman.
5 # GNU Mailman is free software: you can redistribute it and/or modify it under
6 # the terms of the GNU General Public License as published by the Free
7 # Software Foundation, either version 3 of the License, or (at your option)
10 # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 # You should have received a copy of the GNU General Public License along with
16 # GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
18 """Application support for membership management."""
23 'handle_SubscriptionEvent',
27 from email
.utils
import formataddr
28 from mailman
.app
.notifications
import (
29 send_goodbye_message
, send_welcome_message
)
30 from mailman
.core
.i18n
import _
31 from mailman
.email
.message
import OwnerNotification
32 from mailman
.interfaces
.bans
import IBanManager
33 from mailman
.interfaces
.member
import (
34 AlreadySubscribedError
, MemberRole
, MembershipIsBannedError
,
35 NotAMemberError
, SubscriptionEvent
)
36 from mailman
.interfaces
.usermanager
import IUserManager
37 from mailman
.utilities
.i18n
import make
38 from zope
.component
import getUtility
42 def add_member(mlist
, record
, role
=MemberRole
.member
):
43 """Add a member right now.
45 The member's subscription must be approved by whatever policy the list
48 :param mlist: The mailing list to add the member to.
49 :type mlist: `IMailingList`
50 :param record: a subscription request record.
51 :type record: RequestRecord
52 :param role: The membership role for this subscription.
53 :type role: `MemberRole`
54 :return: The just created member.
56 :raises AlreadySubscribedError: if the user is already subscribed to
58 :raises InvalidEmailAddressError: if the email address is not valid.
59 :raises MembershipIsBannedError: if the membership is not allowed.
61 # Check to see if the email address is banned.
62 if IBanManager(mlist
).is_banned(record
.email
):
63 raise MembershipIsBannedError(mlist
, record
.email
)
64 # Make sure there is a user linked with the given address.
65 user_manager
= getUtility(IUserManager
)
66 user
= user_manager
.make_user(record
.email
, record
.display_name
)
67 user
.preferences
.preferred_language
= record
.language
68 # Subscribe the address, not the user.
69 # We're looking for two versions of the email address, the case
70 # preserved version and the case insensitive version. We'll
71 # subscribe the version with matching case if it exists, otherwise
72 # we'll use one of the matching case-insensitively ones. It's
73 # undefined which one we pick.
75 case_insensitive
= None
76 for address
in user
.addresses
:
77 if address
.original_email
== record
.email
:
78 case_preserved
= address
79 if address
.email
== record
.email
.lower():
80 case_insensitive
= address
81 assert case_preserved
is not None or case_insensitive
is not None, (
82 'Could not find a linked address for: {}'.format(record
.email
))
83 address
= (case_preserved
if case_preserved
is not None
84 else case_insensitive
)
85 # Create the member and set the appropriate preferences. It's
86 # possible we're subscribing the lower cased version of the address;
87 # if that's already subscribed re-issue the exception with the correct
88 # email address (i.e. the one passed in here).
90 member
= mlist
.subscribe(address
, role
)
91 except AlreadySubscribedError
as error
:
92 raise AlreadySubscribedError(
93 error
.fqdn_listname
, record
.email
, error
.role
)
94 member
.preferences
.preferred_language
= record
.language
95 member
.preferences
.delivery_mode
= record
.delivery_mode
100 def delete_member(mlist
, email
, admin_notif
=None, userack
=None):
101 """Delete a member right now.
103 :param mlist: The mailing list to remove the member from.
104 :type mlist: `IMailingList`
105 :param email: The email address to unsubscribe.
107 :param admin_notif: Whether the list administrator should be notified that
108 this member was deleted.
109 :type admin_notif: bool, or None to let the mailing list's
110 `admin_notify_mchange` attribute decide.
111 :raises NotAMemberError: if the address is not a member of the
115 userack
= mlist
.send_goodbye_message
116 if admin_notif
is None:
117 admin_notif
= mlist
.admin_notify_mchanges
118 # Delete a member, for which we know the approval has been made.
119 member
= mlist
.members
.get_member(email
)
121 raise NotAMemberError(mlist
, email
)
122 language
= member
.preferred_language
124 # And send an acknowledgement to the user...
126 send_goodbye_message(mlist
, email
, language
)
127 # ...and to the administrator.
129 user
= getUtility(IUserManager
).get_user(email
)
130 display_name
= user
.display_name
131 subject
= _('$mlist.display_name unsubscription notification')
132 text
= make('adminunsubscribeack.txt',
134 listname
=mlist
.display_name
,
135 member
=formataddr((display_name
, email
)),
137 msg
= OwnerNotification(mlist
, subject
, text
,
138 roster
=mlist
.administrators
)
143 def handle_SubscriptionEvent(event
):
144 if not isinstance(event
, SubscriptionEvent
):
146 # Only send a notification message if the mailing list is configured to do
147 # so, and the member being added is a list member (as opposed to a
148 # moderator, non-member, or owner).
149 member
= event
.member
150 if member
.role
is not MemberRole
.member
:
152 mlist
= member
.mailing_list
153 if not mlist
.send_welcome_message
:
155 send_welcome_message(mlist
, member
, member
.preferred_language
)