示例#1
0
 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
示例#2
0
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
示例#3
0
 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
示例#4
0
 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
示例#6
0
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