Skip to content

Commit a4a6ad6

Browse files
committed
update
1 parent c5846bb commit a4a6ad6

1 file changed

Lines changed: 48 additions & 109 deletions

File tree

Mailman/Handlers/CookHeaders.py

Lines changed: 48 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -205,119 +205,58 @@ def munge_from_header(mlist, msg, msgdata):
205205
change_header('From', new_from, mlist, msg, msgdata)
206206

207207
def prefix_subject(mlist, msg, msgdata):
208-
# Add the subject prefix unless the message is a digest or is being fast
209-
# tracked (e.g. internally crafted, delivered to a single user such as the
210-
# list admin).
208+
"""Add the list's subject prefix to the message's Subject: header."""
209+
# Get the subject and charset
210+
subject = msg.get('subject', '')
211+
if not subject:
212+
return
213+
214+
# Get the list's charset
215+
cset = mlist.preferred_language
216+
217+
# Get the prefix
211218
prefix = mlist.subject_prefix.strip()
212219
if not prefix:
213220
return
214-
subject = msg.get('subject', '')
215-
# Try to figure out what the continuation_ws is for the header
216-
if isinstance(subject, Header):
217-
lines = str(subject).splitlines()
218-
else:
219-
lines = subject.splitlines()
220-
ws = ' '
221-
if len(lines) > 1 and lines[1] and lines[1][0] in ' \t':
222-
ws = lines[1][0]
223-
msgdata['origsubj'] = subject
224-
# The subject may be multilingual but we take the first charset as major
225-
# one and try to decode. If it is decodable, returned subject is in one
226-
# line and cset is properly set. If fail, subject is mime-encoded and
227-
# cset is set as us-ascii. See detail for ch_oneline() (CookHeaders one
228-
# line function).
229-
subject, cset = ch_oneline(subject)
230-
# TK: Python interpreter has evolved to be strict on ascii charset code
231-
# range. It is safe to use unicode string when manupilating header
232-
# contents with re module. It would be best to return unicode in
233-
# ch_oneline() but here is temporary solution.
234-
subject = str(subject, cset)
235-
# If the subject_prefix contains '%d', it is replaced with the
236-
# mailing list sequential number. Sequential number format allows
237-
# '%d' or '%05d' like pattern.
238-
prefix_pattern = re.escape(prefix)
239-
# unescape '%' :-<
240-
prefix_pattern = '%'.join(prefix_pattern.split(r'\%'))
241-
p = re.compile(r'%\d*d')
242-
if p.search(prefix, 1):
243-
# prefix have number, so we should search prefix w/number in subject.
244-
# Also, force new style.
245-
prefix_pattern = p.sub(r'\s*\d+\s*', prefix_pattern)
246-
old_style = False
247-
else:
248-
old_style = mm_cfg.OLD_STYLE_PREFIXING
249-
subject = re.sub(prefix_pattern, '', subject)
250-
# Previously the following re didn't have the first \s*. It would fail
251-
# if the incoming Subject: was like '[prefix] Re: Re: Re:' because of the
252-
# leading space after stripping the prefix. It is not known what MUA would
253-
# create such a Subject:, but the issue was reported.
254-
rematch = re.match(
255-
r'(\s*(RE|AW|SV|VS)\s*(\[\d+\])?\s*:\s*)+',
256-
subject, re.I)
257-
if rematch:
258-
subject = subject[rematch.end():]
259-
recolon = 'Re:'
260-
else:
261-
recolon = ''
262-
# Strip leading and trailing whitespace from subject.
263-
subject = subject.strip()
264-
# At this point, subject may become null if someone post mail with
265-
# Subject: [subject prefix]
266-
if subject == '':
267-
# We want the i18n context to be the list's preferred_language. It
268-
# could be the poster's.
269-
otrans = i18n.get_translation()
270-
i18n.set_language(mlist.preferred_language)
271-
subject = _('(no subject)')
272-
i18n.set_translation(otrans)
273-
cset = Utils.GetCharSet(mlist.preferred_language)
274-
subject = str(subject, cset)
275-
# and substitute %d in prefix with post_id
221+
222+
# Handle the subject encoding
276223
try:
277-
prefix = prefix % mlist.post_id
278-
except TypeError:
279-
pass
280-
# If charset is 'us-ascii', try to concatnate as string because there
281-
# is some weirdness in Header module (TK)
282-
if cset == 'us-ascii':
283-
try:
284-
if old_style:
285-
h = u' '.join([recolon, prefix, subject])
286-
else:
287-
if recolon:
288-
h = u' '.join([prefix, recolon, subject])
289-
else:
290-
h = u' '.join([prefix, subject])
291-
h = h.encode('us-ascii')
292-
h = uheader(mlist, h, 'Subject', continuation_ws=ws)
293-
change_header('Subject', h, mlist, msg, msgdata)
294-
ss = u' '.join([recolon, subject])
295-
ss = ss.encode('us-ascii')
296-
ss = uheader(mlist, ss, 'Subject', continuation_ws=ws)
297-
msgdata['stripped_subject'] = ss
298-
return
299-
except UnicodeError:
300-
pass
301-
# Get the header as a Header instance, with proper unicode conversion
302-
# Because of rfc2047 encoding, spaces between encoded words can be
303-
# insignificant, so we need to append spaces to our encoded stuff.
304-
prefix += ' '
305-
if recolon:
306-
recolon += ' '
307-
if old_style:
308-
h = uheader(mlist, recolon, 'Subject', continuation_ws=ws)
309-
h.append(prefix)
310-
else:
311-
h = uheader(mlist, prefix, 'Subject', continuation_ws=ws)
312-
h.append(recolon)
313-
# TK: Subject is concatenated and unicode string.
314-
subject = subject.encode(cset, 'replace')
315-
h.append(subject, cset)
316-
change_header('Subject', h, mlist, msg, msgdata)
317-
ss = uheader(mlist, recolon, 'Subject', continuation_ws=ws)
318-
ss.append(subject, cset)
319-
msgdata['stripped_subject'] = ss
320-
224+
# If subject is already a string, use it directly
225+
if isinstance(subject, str):
226+
subject_str = subject
227+
else:
228+
# Try to decode the subject
229+
try:
230+
subject_str = str(subject, cset)
231+
except (UnicodeError, LookupError):
232+
# If that fails, try utf-8
233+
subject_str = str(subject, 'utf-8', 'replace')
234+
except Exception as e:
235+
mailman_log('error', 'Error decoding subject: %s', str(e))
236+
return
237+
238+
# Add the prefix if it's not already there
239+
if not subject_str.startswith(prefix):
240+
msg['Subject'] = prefix + ' ' + subject_str
241+
242+
# Mark message as processed
243+
mailman_log('debug', 'CookHeaders: Adding X-BeenThere header for message %s', msgid)
244+
change_header('X-BeenThere', mlist.GetListEmail(),
245+
mlist, msg, msgdata, delete=False)
246+
247+
# Add standard headers
248+
mailman_log('debug', 'CookHeaders: Adding standard headers for message %s', msgid)
249+
change_header('X-Mailman-Version', mm_cfg.VERSION,
250+
mlist, msg, msgdata, repl=False)
251+
change_header('Precedence', 'list',
252+
mlist, msg, msgdata, repl=False)
253+
254+
# Handle From: header munging if needed
255+
if (msgdata.get('from_is_list') or mlist.from_is_list) and not msgdata.get('_fasttrack'):
256+
mailman_log('debug', 'CookHeaders: Munging From header for message %s', msgid)
257+
munge_from_header(mlist, msg, msgdata)
258+
259+
mailman_log('debug', 'CookHeaders: Finished processing message %s', msgid)
321260

322261
def ch_oneline(headerstr):
323262
# Decode header string in one line and convert into single charset

0 commit comments

Comments
 (0)