Skip to content

Commit 83570e7

Browse files
committed
issue2550535 Fix keep_quoted_text=yes setting.
In some cases even when keep_quoted_text=yes is configured we would strip quoted sections. This hit the python bug-tracker especially for python interpreter examples with leading '>>>' strings. The fix is slightly different compared to the proposal as this broke keep_quoted_text=no in certain cases. We also fix a bug where keep_quoted_text=no would drop the last line of a non-quoted section if there wasn't an empty line between the next quotes.
1 parent ea29de3 commit 83570e7

File tree

3 files changed

+180
-22
lines changed

3 files changed

+180
-22
lines changed

CHANGES.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ Fixed:
5959
thanks to Thomas Arendsen Hein for reporting and patch.
6060
- issue2550711 Fix XSS vulnerability in @action parameter,
6161
thanks to "om" for reporting.
62+
- issue2550535 In some cases even when keep_quoted_text=yes is
63+
configured we would strip quoted sections. This hit the python
64+
bug-tracker especially for python interpreter examples with leading
65+
'>>>' strings. The fix is slightly different compared to the proposal
66+
as this broke keep_quoted_text=no in certain cases. We also fix a bug
67+
where keep_quoted_text=no would drop the last line of a non-quoted
68+
section if there wasn't an empty line between the next quotes.
6269

6370

6471
2011-07-15: 1.4.19

roundup/mailgw.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,16 +1778,24 @@ def parseContent(content, keep_citations=None, keep_body=None, config=None):
17781778
# extract out the summary from the message
17791779
summary = ''
17801780
l = []
1781-
for section in sections:
1781+
# find last non-empty section for signature matching
1782+
last_nonempty = len(sections) -1
1783+
while last_nonempty and not sections[last_nonempty]:
1784+
last_nonempty -= 1
1785+
for ns, section in enumerate(sections):
17821786
#section = section.strip()
17831787
if not section:
17841788
continue
17851789
lines = eol.split(section)
1786-
if (lines[0] and lines[0][0] in '>|') or (len(lines) > 1 and
1787-
lines[1] and lines[1][0] in '>|'):
1790+
quote_1st = lines[0] and lines[0][0] in '>|'
1791+
quote_2nd = len(lines) > 1 and lines[1] and lines[1][0] in '>|'
1792+
if quote_1st or quote_2nd:
1793+
# don't drop non-quoted first line of intermediate section:
1794+
if ns and not quote_1st and lines[0] and not keep_citations:
1795+
l.append(lines[0])
17881796
# see if there's a response somewhere inside this section (ie.
17891797
# no blank line between quoted message and response)
1790-
for line in lines[1:]:
1798+
for n, line in enumerate(lines[1:]):
17911799
if line and line[0] not in '>|':
17921800
break
17931801
else:
@@ -1796,17 +1804,19 @@ def parseContent(content, keep_citations=None, keep_body=None, config=None):
17961804
l.append(section)
17971805
continue
17981806
# keep this section - it has reponse stuff in it
1799-
lines = lines[lines.index(line):]
1807+
if not keep_citations:
1808+
lines = lines[n+1:]
18001809
section = '\n'.join(lines)
1801-
# and while we're at it, use the first non-quoted bit as
1802-
# our summary
1803-
summary = section
18041810

1811+
is_last = ns == last_nonempty
1812+
# and while we're at it, use the first non-quoted bit as
1813+
# our summary
18051814
if not summary:
18061815
# if we don't have our summary yet use the first line of this
18071816
# section
18081817
summary = section
1809-
elif signature.match(lines[0]) and 2 <= len(lines) <= 10:
1818+
# match signature only in last section
1819+
elif is_last and signature.match(lines[0]) and 2 <= len(lines) <= 10:
18101820
# lose any signature
18111821
break
18121822
elif original_msg.match(lines[0]):

test/test_mailgw.py

Lines changed: 154 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@
3737
#import db_test_base
3838
import memorydb
3939

40+
def expectedFailure(method):
41+
""" For marking a failing test.
42+
This will *not* run the test and return success instead.
43+
"""
44+
return lambda x: 0
45+
4046
class Message(rfc822.Message):
4147
"""String-based Message class with equivalence test."""
4248
def __init__(self, s):
@@ -2280,48 +2286,183 @@ def testFollowupStupidQuoting(self):
22802286
_______________________________________________________________________
22812287
''')
22822288

2289+
firstquotingtest = '''Content-Type: text/plain;
2290+
charset="iso-8859-1"
2291+
From: richard <[email protected]>
2292+
2293+
Message-Id: <followup_dummy_id>
2294+
In-Reply-To: <dummy_test_message_id>
2295+
Subject: Re: [issue1] Testing...
2296+
2297+
Blah blah wrote:
2298+
> Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
2299+
> skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
2300+
>
2301+
2302+
This is a followup
2303+
'''
2304+
22832305
def testEmailQuoting(self):
22842306
self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no'
2285-
self.innerTestQuoting('''This is a followup
2286-
''')
2307+
self.innerTestQuoting(self.firstquotingtest, '''This is a followup
2308+
''', 'This is a followup')
22872309

22882310
def testEmailQuotingRemove(self):
22892311
self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
2290-
self.innerTestQuoting('''Blah blah wrote:
2312+
self.innerTestQuoting(self.firstquotingtest, '''Blah blah wrote:
22912313
> Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
22922314
> skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
22932315
>
22942316
22952317
This is a followup
2296-
''')
2318+
''', 'This is a followup')
22972319

2298-
def innerTestQuoting(self, expect):
2299-
nodeid = self.doNewIssue()
2320+
secondquotingtest = '''Content-Type: text/plain;
2321+
charset="iso-8859-1"
2322+
From: richard <[email protected]>
2323+
2324+
Message-Id: <followup_dummy_id>
2325+
In-Reply-To: <dummy_test_message_id>
2326+
Subject: Re: [issue1] Testing...
23002327
2301-
messages = self.db.issue.get(nodeid, 'messages')
2328+
On Tue, Feb 23, 2010 at 8:46 AM, Someone <[email protected]> wrote:
2329+
> aa
2330+
> aa
23022331
2303-
self._handle_mail('''Content-Type: text/plain;
2332+
AA:
2333+
2334+
AA
2335+
2336+
AA
2337+
2338+
AA
2339+
2340+
TEXT BEFORE QUOTE
2341+
> bb
2342+
> bb
2343+
>
2344+
2345+
BB
2346+
BB
2347+
BB
2348+
BB
2349+
2350+
> cc
2351+
>
2352+
> cc
2353+
>
2354+
>
2355+
> cc
2356+
>
2357+
> cc
2358+
>
2359+
> cc
2360+
>
2361+
CC
2362+
2363+
--
2364+
added signature
2365+
'''
2366+
def testEmailQuoting2(self):
2367+
self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no'
2368+
self.innerTestQuoting(self.secondquotingtest, '''AA:
2369+
2370+
AA
2371+
2372+
AA
2373+
2374+
AA
2375+
2376+
TEXT BEFORE QUOTE
2377+
2378+
BB
2379+
BB
2380+
BB
2381+
BB
2382+
2383+
CC
2384+
''', 'AA:')
2385+
2386+
def testEmailQuotingRemove2(self):
2387+
self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
2388+
self.innerTestQuoting(self.secondquotingtest,
2389+
'\n'.join(self.secondquotingtest.split('\n')[8:-3]), 'AA:')
2390+
2391+
thirdquotingtest = '''Content-Type: text/plain;
23042392
charset="iso-8859-1"
23052393
From: richard <[email protected]>
23062394
23072395
Message-Id: <followup_dummy_id>
23082396
In-Reply-To: <dummy_test_message_id>
23092397
Subject: Re: [issue1] Testing...
23102398
2311-
Blah blah wrote:
2312-
> Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
2313-
> skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
2399+
On Mon, Jan 02, 2012 at 06:14:27PM +0000, Someone wrote:
23142400
>
2401+
> aa
2402+
>
2403+
> aa
2404+
> aa
2405+
> aa
2406+
AA0
2407+
AA
2408+
2409+
> bb
2410+
> bb
2411+
> bb
2412+
BB
2413+
2414+
> cc
2415+
> cc
2416+
> cc
2417+
> cc
2418+
> cc
2419+
> cc
2420+
2421+
CC
2422+
CC
2423+
CC
2424+
2425+
CC
2426+
CC
2427+
2428+
CC
2429+
CC
2430+
CC
2431+
CC
2432+
2433+
CC
2434+
2435+
NAME
2436+
--
2437+
sig
2438+
sig
2439+
sig
2440+
sig
2441+
'''
23152442

2316-
This is a followup
2317-
''')
2443+
# This fails because the sig isn't removed (we currently remove the
2444+
# sig only if the delimiter is the first line in a section)
2445+
@expectedFailure
2446+
def testEmailQuotingRemove3(self):
2447+
self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
2448+
self.innerTestQuoting(self.thirdquotingtest,
2449+
'\n'.join(self.thirdquotingtest.split('\n')[8:-6]), 'AA0')
2450+
2451+
def innerTestQuoting(self, msgtext, expect, summary=None):
2452+
nodeid = self.doNewIssue()
2453+
2454+
messages = self.db.issue.get(nodeid, 'messages')
2455+
2456+
self._handle_mail(msgtext)
23182457
# figure the new message id
23192458
newmessages = self.db.issue.get(nodeid, 'messages')
23202459
for msg in messages:
23212460
newmessages.remove(msg)
23222461
messageid = newmessages[0]
23232462

23242463
self.compareMessages(self.db.msg.get(messageid, 'content'), expect)
2464+
if summary:
2465+
self.assertEqual (summary, self.db.msg.get(messageid, 'summary'))
23252466

23262467
def testUserLookup(self):
23272468
i = self.db.user.create(username='user1', address='[email protected]')

0 commit comments

Comments
 (0)