def subscribe(self, store, subscriber, role=MemberRole.member): """See `IMailingList`.""" if IAddress.providedBy(subscriber): member = store.query(Member).filter( Member.role == role, Member.list_id == self._list_id, Member._address == subscriber).first() if member: raise AlreadySubscribedError(self.fqdn_listname, subscriber.email, role) elif IUser.providedBy(subscriber): if subscriber.preferred_address is None: raise MissingPreferredAddressError(subscriber) member = store.query(Member).filter( Member.role == role, Member.list_id == self._list_id, Member._user == subscriber).first() if member: raise AlreadySubscribedError( self.fqdn_listname, subscriber.preferred_address.email, role) else: raise ValueError('subscriber must be an address or user') member = Member(role=role, list_id=self._list_id, subscriber=subscriber) member.preferences = Preferences() store.add(member) notify(SubscriptionEvent(self, member)) return member
def add_member(mlist, record, 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 record: a subscription request record. :type record: RequestRecord :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(record.email): raise MembershipIsBannedError(mlist, record.email) # Make sure there is a user linked with the given address. user_manager = getUtility(IUserManager) user = user_manager.make_user(record.email, record.display_name) user.preferences.preferred_language = record.language # Subscribe the address, not the user. # We're looking for two versions of the email address, the case # preserved version and the case insensitive version. We'll # subscribe the version with matching case if it exists, otherwise # we'll use one of the matching case-insensitively ones. It's # undefined which one we pick. case_preserved = None case_insensitive = None for address in user.addresses: if address.original_email == record.email: case_preserved = address if address.email == record.email.lower(): case_insensitive = address assert case_preserved is not None or case_insensitive is not None, ( 'Could not find a linked address for: {}'.format(record.email)) address = (case_preserved if case_preserved is not None else case_insensitive) # Create the member and set the appropriate preferences. It's # possible we're subscribing the lower cased version of the address; # if that's already subscribed re-issue the exception with the correct # email address (i.e. the one passed in here). try: member = mlist.subscribe(address, role) except AlreadySubscribedError as error: raise AlreadySubscribedError(error.fqdn_listname, record.email, error.role) member.preferences.preferred_language = record.language member.preferences.delivery_mode = record.delivery_mode return member
def subscribe(self, store, subscriber, role=MemberRole.member): """See `IMailingList`.""" member, email = self._get_subscriber(store, subscriber, role) if member is not None: raise AlreadySubscribedError(self.fqdn_listname, email, role) member = Member(role=role, list_id=self._list_id, subscriber=subscriber) member.preferences = Preferences() store.add(member) notify(SubscriptionEvent(self, member)) return member
def _step_sanity_checks(self): # Ensure that we have both an address and a user, even if the address # is not verified. We can't set the preferred address until it is # verified. if self.user is None: # The address has no linked user so create one, link it, and set # the user's preferred address. assert self.address is not None, 'No address or user' self.user = getUtility(IUserManager).make_user(self.address.email) if self.address is None: assert self.user.preferred_address is None, ( "Preferred address exists, but wasn't used in constructor") addresses = list(self.user.addresses) if len(addresses) == 0: raise AssertionError('User has no addresses: {}'.format( self.user)) # This is rather arbitrary, but we have no choice. self.address = addresses[0] assert self.user is not None and self.address is not None, ( 'Insane sanity check results') # Is this subscriber already a member? if (self.which is WhichSubscriber.user and self.user.preferred_address is not None): subscriber = self.user else: subscriber = self.address if self.mlist.is_subscribed(subscriber): # 2017-04-22 BAW: This branch actually *does* get covered, as I've # verified by a full coverage run, but diffcov for some reason # claims that the test added in the branch that added this code # does not cover the change. That seems like a bug in diffcov. raise AlreadySubscribedError( # pragma: nocover self.mlist.fqdn_listname, self.address.email, MemberRole.member) # Is this email address banned? if IBanManager(self.mlist).is_banned(self.address.email): raise MembershipIsBannedError(self.mlist, self.address.email) # Don't allow the list posting address. if self.address.email.lower() == self.mlist.posting_address: raise InvalidEmailAddressError('List posting address not allowed') # Check if there is already a subscription request for this email. pendings = getUtility(IPendings).find(mlist=self.mlist, pend_type='subscription') for token, pendable in pendings: if pendable['email'] == self.address.email: raise SubscriptionPendingError(self.mlist, self.address.email) # Start out with the subscriber being the token owner. self.push('verification_checks')
def subscribe(self, store, subscriber, role=MemberRole.member, send_welcome_message=None): """See `IMailingList`.""" member, email = self._get_subscriber(store, subscriber, role) test_email = email or subscriber.lower() # Allow list posting address only for nonmember role. if (test_email == self.posting_address and role != MemberRole.nonmember): raise InvalidEmailAddressError('List posting address not allowed') if member is not None: raise AlreadySubscribedError(self.fqdn_listname, email, role) if IBanManager(self).is_banned(test_email): raise MembershipIsBannedError(self, test_email) member = Member(role=role, list_id=self._list_id, subscriber=subscriber) member.preferences = Preferences() store.add(member) notify(SubscriptionEvent( self, member, send_welcome_message=send_welcome_message)) return member
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 case-insensitive address. # We're looking for two versions of the email address, the case # preserved version and the case insensitive version. We'll # subscribe the version with matching case if it exists, otherwise # we'll use one of the matching case-insensitively ones. It's # undefined which one we pick. case_preserved = None case_insensitive = None for address in user.addresses: if address.original_email == email: case_preserved = address if address.email == email.lower(): case_insensitive = address assert case_preserved is not None or case_insensitive is not None, ( 'Could not find a linked address for: {}'.format(email)) address = (case_preserved if case_preserved is not None else case_insensitive) # Create the member and set the appropriate preferences. It's # possible we're subscribing the lower cased version of the address; # if that's already subscribed re-issue the exception with the correct # email address (i.e. the one passed in here). try: member = mlist.subscribe(address, role) except AlreadySubscribedError as error: raise AlreadySubscribedError(error.fqdn_listname, email, error.role) member.preferences.preferred_language = language member.preferences.delivery_mode = delivery_mode return member