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 = ''
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)
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)
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)
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)
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']
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)