Example #1
0
def process(mlist, msg, msgdata):
    ## VirginRunner sets _fasttrack for internally crafted messages.
    if msgdata.get('isdigest') or msgdata.get('_fasttrack'):
        return

    ## Same process is done by CookHeaders.py if subject_prefix is enabled
    if mlist.subject_prefix.strip():
        return

    old_style_save = mm_cfg.OLD_STYLE_PREFIXING
    mm_cfg.OLD_STYLE_PREFIXING = 0
    mlist.subject_prefix = DUMMY_PREFIX

    try:
        prefix_subject(mlist, msg, msgdata)
        subject = msg.get('subject')
        if subject:
            subject = str(subject)[len(DUMMY_PREFIX):]
            change_header('Subject', subject, mlist, msg, msgdata)
    except (UnicodeError, ValueError):
        ## Sometimes subject header is not MIME encoded for 8bit
        ## simply abort fixing.
        pass

    mm_cfg.OLD_STYLE_PREFIXING = old_style_save
    mlist.subject_prefix = ''
Example #2
0
def process(mlist, msg, msgdata):
    try:
	confs_by_list = mm_cfg.REWRITE_FROM
    except AttributeError:
	return

    if mlist.internal_name() in confs_by_list:
	conf = confs_by_list[mlist.internal_name()]
    elif '*' in confs_by_list:
	conf = confs_by_list['*']
    else:
	return

    from_name_fmt = conf.get('from_name', '%(from_name)s')
    from_address_fmt = conf.get('from_address', '%(from_address)s')
    save_original = conf.get('save_original')

    d = SafeDict({'list_real_name':	mlist.real_name,
                  'list_name':		mlist.internal_name(),
		  'list_address':	mlist.GetListEmail(),
                  'list_domain':	mlist.host_name,
                  'list_desc':		mlist.description,
                  'list_info':		mlist.info,
                  })

    lcset = Utils.GetCharSet(mlist.preferred_language)

    from_name, from_address = parseaddr(msg.get('From'))
    d['from_address'] = from_address
    try:
	d['from_local'], d['from_domain'] = re.split('@', from_address, 1)
    except ValueError:
	d['from_local'] = from_address
	d['from_domain'] = ''

    if from_name != '':
	d['from_name'] = Utils.oneline(from_name, lcset)
    else:
	d['from_name'] = d['from_local']

    try:
	membername = mlist.getMemberName(from_address) or None
	try:
	    d['from_membername'] = membername.encode(lcset)
	except (AttributeError, UnicodeError):
	    d['from_membername'] = d['from_name']
    except Errors.NotAMemberError:
	d['from_membername'] = d['from_name']

    from_name = from_name_fmt % d
    from_address = from_address_fmt % d

    if save_original:
        change_header(save_original, msg['From'], mlist, msg, msgdata, delete=False)

    change_header('From', formataddr((from_name, from_address)), mlist, msg, msgdata)
Example #3
0
def process(mlist, msg, msgdata):
    ## VirginRunner sets _fasttrack for internally crafted messages.
    if msgdata.get('isdigest') or msgdata.get('_fasttrack'):
        return

    subject = msg.get('subject')
    if not subject:
        return

    subject = MIME_RE.sub('\\1\n ', str(subject))
    change_header('Subject', subject, mlist, msg, msgdata)
Example #4
0
def process(mlist, msg, msgdata):
    try:
	confs_by_list = mm_cfg.ADD_HEADERS
    except AttributeError:
	return

    if mlist.internal_name() in confs_by_list:
	conf = confs_by_list[mlist.internal_name()]
    elif '*' in confs_by_list:
	conf = confs_by_list['*']
    else:
	return

    d = SafeDict({'list_real_name':	mlist.real_name,
                  'list_name':		mlist.internal_name(),
		  'list_address':	mlist.GetListEmail(),
                  'list_domain':	mlist.host_name,
                  'list_desc':		mlist.description,
                  'list_info':		mlist.info,
                  'post_id':		mlist.post_id,
                  })

    lcset = Utils.GetCharSet(mlist.preferred_language)
    d['from_header'] = msg.get('From')
    from_name, from_address = parseaddr(d['from_header'])
    d['from_address'] = from_address
    try:
	d['from_local'], d['from_domain'] = re.split('@', from_address, 1)
    except ValueError:
	d['from_local'] = from_address
	d['from_domain'] = ''
    if from_name != '':
	d['from_name'] = Utils.oneline(from_name, lcset)
    else:
	d['from_name'] = d['from_local']
    try:
	membername = mlist.getMemberName(from_address) or None
	try:
	    d['from_membername'] = membername.encode(lcset)
	except (AttributeError, UnicodeError):
	    d['from_membername'] = d['from_name']
    except Errors.NotAMemberError:
	d['from_membername'] = d['from_name']

    for name, value_fmt in conf.items():
        value = value_fmt % d
        change_header(name, value, mlist, msg, msgdata, delete=False)
Example #5
0
def process(mlist, msg, msgdata):
    if not mlist.topics_enabled:
        return
    # Helper function.  Return RFC 2047 decoded header as a string in the
    # charset of the list's preferred language.
    def _decode(h):
        if not h:
            return h
        return Utils.oneline(h, Utils.GetCharSet(mlist.preferred_language))

    # Extract the Subject:, Keywords:, and possibly body text
    matchlines = []
    matchlines.append(_decode(msg.get('subject', None)))
    matchlines.append(_decode(msg.get('keywords', None)))
    if mlist.topics_bodylines_limit == 0:
        # Don't scan any body lines
        pass
    elif mlist.topics_bodylines_limit < 0:
        # Scan all body lines
        matchlines.extend(scanbody(msg))
    else:
        # Scan just some of the body lines
        matchlines.extend(scanbody(msg, mlist.topics_bodylines_limit))
    matchlines = filter(None, matchlines)
    # For each regular expression in the topics list, see if any of the lines
    # of interest from the message match the regexp.  If so, the message gets
    # added to the specific topics bucket.
    hits = {}
    for name, pattern, desc, emptyflag in mlist.topics:
        pattern = OR.join(pattern.splitlines())
        cre = re.compile(pattern, re.IGNORECASE)
        for line in matchlines:
            if cre.search(line):
                hits[name] = 1
                break
    if hits:
        msgdata['topichits'] = hits.keys()
        change_header('X-Topics',
                      NLTAB.join(hits.keys()),
                      mlist,
                      msg,
                      msgdata,
                      delete=False)
Example #6
0
def process(mlist, msg, msgdata):
    if not mlist.topics_enabled:
        return
    # Helper function.  Return RFC 2047 decoded header as a string in the
    # charset of the list's preferred language.
    def _decode(h):
        if not h:
            return h
        return Utils.oneline(h, Utils.GetCharSet(mlist.preferred_language))
    # Extract the Subject:, Keywords:, and possibly body text
    matchlines = []
    matchlines.append(_decode(msg.get('subject', None)))
    matchlines.append(_decode(msg.get('keywords', None)))
    if mlist.topics_bodylines_limit == 0:
        # Don't scan any body lines
        pass
    elif mlist.topics_bodylines_limit < 0:
        # Scan all body lines
        matchlines.extend(scanbody(msg))
    else:
        # Scan just some of the body lines
        matchlines.extend(scanbody(msg, mlist.topics_bodylines_limit))
    matchlines = filter(None, matchlines)
    # For each regular expression in the topics list, see if any of the lines
    # of interest from the message match the regexp.  If so, the message gets
    # added to the specific topics bucket.
    hits = {}
    for name, pattern, desc, emptyflag in mlist.topics:
        pattern = OR.join(pattern.splitlines())
        cre = re.compile(pattern, re.IGNORECASE)
        for line in matchlines:
            if cre.search(line):
                hits[name] = 1
                break
    if hits:
        msgdata['topichits'] = hits.keys()
        change_header('X-Topics', NLTAB.join(hits.keys()),
                      mlist, msg, msgdata, delete=False)
def process(mlist, msg, msgdata):
    if not mlist.topics_enabled:
        return
    # Extract the Subject:, Keywords:, and possibly body text
    matchlines = []
    matchlines.append(msg.get('subject', None))
    matchlines.append(msg.get('keywords', None))
    if mlist.topics_bodylines_limit == 0:
        # Don't scan any body lines
        pass
    elif mlist.topics_bodylines_limit < 0:
        # Scan all body lines
        matchlines.extend(scanbody(msg))
    else:
        # Scan just some of the body lines
        matchlines.extend(scanbody(msg, mlist.topics_bodylines_limit))
    matchlines = [_f for _f in matchlines if _f]
    # For each regular expression in the topics list, see if any of the lines
    # of interest from the message match the regexp.  If so, the message gets
    # added to the specific topics bucket.
    hits = {}
    for name, pattern, desc, emptyflag in mlist.topics:
        pattern = OR.join(pattern.splitlines())
        cre = re.compile(pattern, re.IGNORECASE)
        for line in matchlines:
            if cre.search(line):
                hits[name] = 1
                break
    if hits:
        msgdata['topichits'] = list(hits.keys())
        change_header('X-Topics',
                      NLTAB.join(list(hits.keys())),
                      mlist,
                      msg,
                      msgdata,
                      delete=False)
Example #8
0
def process(mlist, msg, msgdata):
    recips = msgdata['recips']
    # Short circuit
    if not recips:
        return
    # There is an issue with addresses in To: or Cc: that differ in
    # case from the MemberCPAddresses in recips.  We can't just
    # lower-case everything because we still want CP addresses in
    # the final recips list, so we lower case the keys.
    # Seed this set with addresses we don't care about dup avoiding
    explicit_recips = {}
    listaddrs = [mlist.GetListEmail(), mlist.GetBouncesEmail(),
                 mlist.GetOwnerEmail(), mlist.GetRequestEmail()]
    for addr in listaddrs:
        explicit_recips[addr.lower()] = True
    # Figure out the set of explicit recipients
    ccaddrs = {}
    for header in ('to', 'cc', 'resent-to', 'resent-cc'):
        addrs = getaddresses(msg.get_all(header, []))
        if header == 'cc':
            for name, addr in addrs:
                ccaddrs[addr.lower()] = name, addr
        for name, addr in addrs:
            if not addr:
                continue
            # Ignore the list addresses for purposes of dup avoidance
            explicit_recips[addr.lower()] = True
    # Now strip out the list addresses
    for addr in listaddrs:
        del explicit_recips[addr.lower()]
    if not explicit_recips:
        # No one was explicitly addressed, so we can't do any dup collapsing
        return
    newrecips = []
    for r in recips:
        # If this recipient is explicitly addressed...
        if explicit_recips.has_key(r.lower()):
            send_duplicate = True
            # If the member wants to receive duplicates, or if the recipient
            # is not a member at all, just flag the X-Mailman-Duplicate: yes
            # header.
            if mlist.isMember(r) and \
                   mlist.getMemberOption(r, mm_cfg.DontReceiveDuplicates):
                send_duplicate = False
            # We'll send a duplicate unless the user doesn't wish it.  If
            # personalization is enabled, the add-dupe-header flag will add a
            # X-Mailman-Duplicate: yes header for this user's message.
            if send_duplicate:
                msgdata.setdefault('add-dup-header', {})[r] = True
                newrecips.append(r)
            elif ccaddrs.has_key(r.lower()):
                del ccaddrs[r.lower()]
        else:
            # Otherwise, this is the first time they've been in the recips
            # list.  Add them to the newrecips list and flag them as having
            # received this message.
            newrecips.append(r)
    # Set the new list of recipients
    msgdata['recips'] = newrecips
    # RFC 2822 specifies zero or one CC header
    if ccaddrs:
        change_header('Cc',
        COMMASPACE.join([formataddr(i) for i in ccaddrs.values()]),
        mlist, msg, msgdata)
    else:
        del msg['cc']
def process(mlist, msg, msgdata):
    recips = msgdata['recips']
    # Short circuit
    if not recips:
        return
    # There is an issue with addresses in To: or Cc: that differ in
    # case from the MemberCPAddresses in recips.  We can't just
    # lower-case everything because we still want CP addresses in
    # the final recips list, so we lower case the keys.
    # Seed this set with addresses we don't care about dup avoiding
    explicit_recips = {}
    listaddrs = [
        mlist.GetListEmail(),
        mlist.GetBouncesEmail(),
        mlist.GetOwnerEmail(),
        mlist.GetRequestEmail()
    ]
    for addr in listaddrs:
        explicit_recips[addr.lower()] = True
    # Figure out the set of explicit recipients
    ccaddrs = {}
    for header in ('to', 'cc', 'resent-to', 'resent-cc'):
        addrs = getaddresses(msg.get_all(header, []))
        if header == 'cc':
            for name, addr in addrs:
                ccaddrs[addr.lower()] = name, addr
        for name, addr in addrs:
            if not addr:
                continue
            # Ignore the list addresses for purposes of dup avoidance
            explicit_recips[addr.lower()] = True
    # Now strip out the list addresses
    for addr in listaddrs:
        del explicit_recips[addr.lower()]
    if not explicit_recips:
        # No one was explicitly addressed, so we can't do any dup collapsing
        return
    newrecips = []
    for r in recips:
        # If this recipient is explicitly addressed...
        if r.lower() in explicit_recips:
            send_duplicate = True
            # If the member wants to receive duplicates, or if the recipient
            # is not a member at all, just flag the X-Mailman-Duplicate: yes
            # header.
            if mlist.isMember(r) and \
                   mlist.getMemberOption(r, mm_cfg.DontReceiveDuplicates):
                send_duplicate = False
            # We'll send a duplicate unless the user doesn't wish it.  If
            # personalization is enabled, the add-dupe-header flag will add a
            # X-Mailman-Duplicate: yes header for this user's message.
            if send_duplicate:
                msgdata.setdefault('add-dup-header', {})[r] = True
                newrecips.append(r)
            elif r.lower() in ccaddrs:
                del ccaddrs[r.lower()]
        else:
            # Otherwise, this is the first time they've been in the recips
            # list.  Add them to the newrecips list and flag them as having
            # received this message.
            newrecips.append(r)
    # Set the new list of recipients
    msgdata['recips'] = newrecips
    # RFC 2822 specifies zero or one CC header
    if ccaddrs:
        change_header(
            'Cc',
            COMMASPACE.join([formataddr(i) for i in list(ccaddrs.values())]),
            mlist, msg, msgdata)
    else:
        del msg['cc']
Example #10
0
def process(mlist, msg, msgdata):
    ## Check reply_goes_to_list value:
    ## 0 - Reply-To: not munged
    ## 1 - Reply-To: set back to the list
    ## 2 - Reply-To: set to an explicit value (reply_to_address)
    if mlist.reply_goes_to_list == 0:
    	if msg.has_key('Reply-To'):
	    return
    elif mlist.reply_goes_to_list == 1:
    	return
    elif mlist.reply_goes_to_list == 2:
    	return

    try:
	confs = mm_cfg.ADJUST_REPLYTO
	if not mlist.internal_name() in confs:
	    return
    except AttributeError:
	pass

    def domatch(addrpatterns, addr):
	for addrpattern in addrpatterns:
	    if not addrpattern:
		## Ignore blank or empty lines
		continue
	    try:
		if re.match(addrpattern, addr, re.IGNORECASE):
		    return True
	    except re.error:
		## The pattern is a malformed regexp -- try matching safely,
		## with all non-alphanumerics backslashed:
		if re.match(re.escape(addrpattern), addr, re.IGNORECASE):
		    return True
	return False

    ## Set 'Reply-To' header to the list's posting address and
    ## the address(es) taken from 'From', 'To', 'Cc' and 'Reply-To' headers.
    listaddrs = [mlist.GetListEmail()]
    listaddrs += [alias.strip() for alias in mlist.acceptable_aliases.splitlines()]
    listaddr_set = False
    addrs_set = set()
    reply_to = []
    for hfname in ('From', 'To', 'Cc', 'Reply-To'):
	for name, addr in email.Utils.getaddresses(msg.get_all(hfname, [])):
	    if addr in addrs_set:
		continue
	    if addr == '':
	    	continue
	    if mlist.isMember(addr) and \
	       mlist.getDeliveryStatus(addr) == MemberAdaptor.ENABLED:
	    	continue
	    if domatch(listaddrs, addr):
		if listaddr_set:
		    ## List address has already been set
		    continue
		listaddr_set = True
            reply_to.append(addr)
	    addrs_set.add(addr)

    if not listaddr_set:
	## Prepend the list address if it has NOT been set
        reply_to[0:0] = [mlist.reply_to_address or mlist.GetListEmail()]

    change_header('Reply-To', COMMASPACE.join(reply_to), mlist, msg, msgdata)