Example #1
0
def do_include(mlist, msg, msgdata, recips):
    # regular_include_lists are the other mailing lists on this mailman
    # installation whose members are included in the regular (non-digest)
    # delivery if those list addresses don't appear in To: or Cc: headers.
    if not mlist.regular_include_lists:
        return recips
    recips = set(recips)
    destinations = email.Utils.getaddresses(msg.get_all('to', []) +
                                            msg.get_all('cc', []))
    destinations = [y.lower() for x,y in destinations]
    for listname in mlist.regular_include_lists:
        listname = listname.lower()
        if listname in destinations:
            continue
        listlhs, hostname = listname.split('@')
        if listlhs == mlist.internal_name():
            syslog('error', 'Include list %s is a self reference.',
                    listname)
            continue
        try:
            slist = MailList(listlhs, lock=False)
        except MMUnknownListError:
            syslog('error', 'Include list %s not found.', listname)
            continue
        if not mm_cfg.ALLOW_CROSS_DOMAIN_SIBLING \
           and slist.host_name != hostname:
            syslog('error', 'Include list %s is not in the same domain.',
                    listname)
            continue
        srecips = set([slist.getMemberCPAddress(m)
                   for m in slist.getRegularMemberKeys()
                   if slist.getDeliveryStatus(m) == ENABLED])
        recips |= srecips
    return list(recips)
Example #2
0
    def _update_list_subscriptions(self, list_name, subscription_info):
        """Update the subscription information for a single mailing list.

        :param list_name: The name of the mailing list to update.
        :type list_name: string
        :param subscription_info: The mailing list's new subscription
            information.
        :type subscription_info: a list of 4-tuples containing the address,
            real name, flags, and status of each person in the list's
            subscribers.
        """
        ## syslog('xmlrpc', '%s subinfo: %s', list_name, subscription_info)
        # Start with an unlocked list.
        mlist = MailList(list_name, lock=False)
        # Create a mapping of email address to the member's real name,
        # flags, and status.  Note that flags is currently unused.
        member_map = dict(
            (address, (realname, flags, status))
            for address, realname, flags, status in subscription_info)
        # In Mailman parlance, the 'member key' is the lower-cased
        # address.  We need a mapping from the member key to
        # case-preserved address for all future members of the list.
        key_to_case_preserved = dict(
            (address.lower(), address) for address in member_map)
        # The following modifications to membership may be made:
        # - Current members whose address is changing case
        # - New members who need to be added to the mailing list
        # - Old members who need to be removed from the mailing list
        # - Current members whose settings are being changed
        #
        # Start by getting the case-folded membership sets of all current
        # and future members.
        current_members = set(mlist.getMembers())
        future_members = set(key_to_case_preserved)
        # Additions are all those addresses in future_members who are not
        # in current_members.
        additions = future_members - current_members
        # Deletions are all those addresses in current_members who are not
        # in future_members.
        deletions = current_members - future_members
        # Any address in both current and future members is either
        # changing case, updating settings, or both.
        updates = current_members & future_members
        # If there's nothing to do, just skip this list.
        if not additions and not deletions and not updates:
            # Why did we get here?  This list should not have shown up in
            # getMembershipInformation().
            syslog('xmlrpc', 'Strange subscription information for list: %s',
                   list_name)
            return
        # Lock the list and make the modifications.  Don't worry if the list
        # couldn't be locked, we'll just log that and try again the next time
        # through the loop.  Eventually any existing lock will expire anyway.
        try:
            mlist.Lock(2)
        except TimeOutError:
            syslog('xmlrpc',
                   'Could not lock the list to update subscriptions: %s',
                   list_name)
            return
        try:
            # Handle additions first.
            if len(additions) > 0:
                syslog('xmlrpc', 'Adding to %s: %s', list_name, additions)
            for address in additions:
                # When adding the new member, be sure to use the
                # case-preserved email address.
                original_address = key_to_case_preserved[address]
                realname, flags, status = member_map[original_address]
                mlist.addNewMember(original_address, realname=realname)
                mlist.setDeliveryStatus(original_address, status)
            # Handle deletions next.
            if len(deletions) > 0:
                syslog('xmlrpc', 'Removing from %s: %s', list_name, deletions)
            for address in deletions:
                mlist.removeMember(address)
            # Updates can be either a settings update, a change in the
            # case of the subscribed address, or both.
            found_updates = []
            for address in updates:
                # See if the case is changing.
                current_address = mlist.getMemberCPAddress(address)
                future_address = key_to_case_preserved[address]
                if current_address != future_address:
                    mlist.changeMemberAddress(address, future_address)
                    found_updates.append('%s -> %s' %
                                         (address, future_address))
                # flags are ignored for now.
                realname, flags, status = member_map[future_address]
                if realname != mlist.getMemberName(address):
                    mlist.setMemberName(address, realname)
                    found_updates.append('%s new name: %s' %
                                         (address, realname))
                if status != mlist.getDeliveryStatus(address):
                    mlist.setDeliveryStatus(address, status)
                    found_updates.append('%s new status: %s' %
                                         (address, status))
            if len(found_updates) > 0:
                syslog('xmlrpc', 'Membership updates for %s: %s', list_name,
                       found_updates)
            # We're done, so flush the changes for this mailing list.
            mlist.Save()
        finally:
            mlist.Unlock()
Example #3
0
    def _update_list_subscriptions(self, list_name, subscription_info):
        """Update the subscription information for a single mailing list.

        :param list_name: The name of the mailing list to update.
        :type list_name: string
        :param subscription_info: The mailing list's new subscription
            information.
        :type subscription_info: a list of 4-tuples containing the address,
            real name, flags, and status of each person in the list's
            subscribers.
        """
        ## syslog('xmlrpc', '%s subinfo: %s', list_name, subscription_info)
        # Start with an unlocked list.
        mlist = MailList(list_name, lock=False)
        # Create a mapping of email address to the member's real name,
        # flags, and status.  Note that flags is currently unused.
        member_map = dict(
            (address, (realname, flags, status)) for address, realname, flags, status in subscription_info
        )
        # In Mailman parlance, the 'member key' is the lower-cased
        # address.  We need a mapping from the member key to
        # case-preserved address for all future members of the list.
        key_to_case_preserved = dict((address.lower(), address) for address in member_map)
        # The following modifications to membership may be made:
        # - Current members whose address is changing case
        # - New members who need to be added to the mailing list
        # - Old members who need to be removed from the mailing list
        # - Current members whose settings are being changed
        #
        # Start by getting the case-folded membership sets of all current
        # and future members.
        current_members = set(mlist.getMembers())
        future_members = set(key_to_case_preserved)
        # Additions are all those addresses in future_members who are not
        # in current_members.
        additions = future_members - current_members
        # Deletions are all those addresses in current_members who are not
        # in future_members.
        deletions = current_members - future_members
        # Any address in both current and future members is either
        # changing case, updating settings, or both.
        updates = current_members & future_members
        # If there's nothing to do, just skip this list.
        if not additions and not deletions and not updates:
            # Why did we get here?  This list should not have shown up in
            # getMembershipInformation().
            syslog("xmlrpc", "Strange subscription information for list: %s", list_name)
            return
        # Lock the list and make the modifications.  Don't worry if the list
        # couldn't be locked, we'll just log that and try again the next time
        # through the loop.  Eventually any existing lock will expire anyway.
        try:
            mlist.Lock(2)
        except TimeOutError:
            syslog("xmlrpc", "Could not lock the list to update subscriptions: %s", list_name)
            return
        try:
            # Handle additions first.
            if len(additions) > 0:
                syslog("xmlrpc", "Adding to %s: %s", list_name, additions)
            for address in additions:
                # When adding the new member, be sure to use the
                # case-preserved email address.
                original_address = key_to_case_preserved[address]
                realname, flags, status = member_map[original_address]
                mlist.addNewMember(original_address, realname=realname)
                mlist.setDeliveryStatus(original_address, status)
            # Handle deletions next.
            if len(deletions) > 0:
                syslog("xmlrpc", "Removing from %s: %s", list_name, deletions)
            for address in deletions:
                mlist.removeMember(address)
            # Updates can be either a settings update, a change in the
            # case of the subscribed address, or both.
            found_updates = []
            for address in updates:
                # See if the case is changing.
                current_address = mlist.getMemberCPAddress(address)
                future_address = key_to_case_preserved[address]
                if current_address != future_address:
                    mlist.changeMemberAddress(address, future_address)
                    found_updates.append("%s -> %s" % (address, future_address))
                # flags are ignored for now.
                realname, flags, status = member_map[future_address]
                if realname != mlist.getMemberName(address):
                    mlist.setMemberName(address, realname)
                    found_updates.append("%s new name: %s" % (address, realname))
                if status != mlist.getDeliveryStatus(address):
                    mlist.setDeliveryStatus(address, status)
                    found_updates.append("%s new status: %s" % (address, status))
            if len(found_updates) > 0:
                syslog("xmlrpc", "Membership updates for %s: %s", list_name, found_updates)
            # We're done, so flush the changes for this mailing list.
            mlist.Save()
        finally:
            mlist.Unlock()