def validate(self, email): """Validate an email address. :param address: An email address. :type address: string :raise InvalidEmailAddressError: when the address is deemed invalid. """ if not self.is_valid(email): raise InvalidEmailAddressError(email)
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 create(self, store, fqdn_listname): """See `IListManager`.""" fqdn_listname = fqdn_listname.lower() listname, at, hostname = fqdn_listname.partition('@') if len(hostname) == 0: raise InvalidEmailAddressError(fqdn_listname) list_id = '{}.{}'.format(listname, hostname) notify(ListCreatingEvent(fqdn_listname)) mlist = store.query(MailingList).filter_by(_list_id=list_id).first() if mlist: raise ListAlreadyExistsError(fqdn_listname) mlist = MailingList(fqdn_listname) mlist.created_at = now() store.add(mlist) notify(ListCreatedEvent(mlist)) return mlist
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, 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 or is the list posting address. :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) # Check for list posting address, but allow for nonmember. if (record.email.lower() == mlist.posting_address and role != MemberRole.nonmember): raise InvalidEmailAddressError('List posting address not allowed') # 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(): # pragma: no branch 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 # Check for and remove nonmember subscriptions of the user to this list. if role is MemberRole.member: for address in user.addresses: nonmember = mlist.nonmembers.get_member(address.email) if nonmember is not None: nonmember.unsubscribe() return member