Skip to content

Commit a170cdb

Browse files
committed
Fix issue934009: Have New Issues Submitted By Email *Not* Change Body!
The mailgw config options: keep_quoted_text and leave_body_unchanged can now have a new values: new. If set to new, keep_quoted_text acts like yes if the message is starting a new issue. Otherise it strips quoted text. This allows somebody to start a new issue by forwarding a threaded email (with multiple quoted parts) into roundup and keeping all the quoted parts. If leave_body_unchanged is set to new, even the signature on the email that starts a new issue will be preserved.
1 parent d4e7763 commit a170cdb

File tree

4 files changed

+125
-10
lines changed

4 files changed

+125
-10
lines changed

CHANGES.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,16 @@ Features:
111111
describe the purpose of the directory. It also says the detectors
112112
are provided on an as-is basis and may not work. Detector by W.
113113
Trevor King (wking), rest by John Rouillard.
114-
114+
- issue934009: Have New Issues Submitted By Email *Not* Change Body!
115+
The mailgw config options: keep_quoted_text and leave_body_unchanged
116+
can now have a new values: new. If set to new, keep_quoted_text acts
117+
like yes if the message is starting a new issue. Otherise it strips
118+
quoted text. This allows somebody to start a new issue by forwarding
119+
a threaded email (with multiple quoted parts) into roundup and
120+
keeping all the quoted parts. If leave_body_unchanged is set to
121+
new, even the signature on the email that starts a new issue will be
122+
preserved.
123+
115124
Fixed:
116125

117126
- issue1615201: Optionally restore the original (version 0.6) mailgw

roundup/configuration.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,19 @@ def str2value(self, value):
293293
else:
294294
raise OptionValueError(self, value, self.class_description)
295295

296+
class EmailBodyOption(Option):
297+
298+
"""When to replace message body or strip quoting: always, never or for new items only"""
299+
300+
class_description = "Allowed values: yes, no, new"
301+
302+
def str2value(self, value):
303+
_val = value.lower()
304+
if _val in ("yes", "no", "new"):
305+
return _val
306+
else:
307+
raise OptionValueError(self, value, self.class_description)
308+
296309
class IsolationOption(Option):
297310
"""Database isolation levels"""
298311

@@ -760,15 +773,18 @@ def str2value(self, value):
760773
"actor from being exposed at mail archives, etc."),
761774
), "Outgoing email options.\nUsed for nozy messages and approval requests"),
762775
("mailgw", (
763-
(BooleanOption, "keep_quoted_text", "yes",
776+
(EmailBodyOption, "keep_quoted_text", "yes",
764777
"Keep email citations when accepting messages.\n"
765-
"Setting this to \"no\" strips out \"quoted\" text"
766-
" from the message.\n"
778+
"Setting this to \"no\" strips out \"quoted\" text\n"
779+
"from the message. Setting this to \"new\" keeps quoted\n"
780+
"text only if a new issue is being created.\n"
767781
"Signatures are also stripped.",
768782
["EMAIL_KEEP_QUOTED_TEXT"]),
769-
(BooleanOption, "leave_body_unchanged", "no",
770-
"Preserve the email body as is - that is,\n"
771-
"keep the citations _and_ signatures.",
783+
(EmailBodyOption, "leave_body_unchanged", "no",
784+
"Setting this to \"yes\" preserves the email body\n"
785+
"as is - that is, keep the citations _and_ signatures.\n"
786+
"Setting this to \"new\" keeps the body only if we are\n"
787+
"creating a new issue.",
772788
["EMAIL_LEAVE_BODY_UNCHANGED"]),
773789
(Option, "default_class", "issue",
774790
"Default class to use in the mailgw\n"

roundup/mailgw.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,9 +1138,8 @@ def create_msg(self):
11381138
Roundup requires the submission to be plain text. The message parser could
11391139
not find a text/plain part to use.
11401140
""")
1141-
11421141
# parse the body of the message, stripping out bits as appropriate
1143-
summary, content = parseContent(self.content, config=self.config)
1142+
summary, content = parseContent(self.content, config=self.config, is_new_issue = not bool(self.nodeid))
11441143
content = content.strip()
11451144

11461145
if content:
@@ -1782,7 +1781,7 @@ def uidFromAddress(db, address, create=1, **user_props):
17821781
else:
17831782
return 0
17841783

1785-
def parseContent(content, keep_citations=None, keep_body=None, config=None):
1784+
def parseContent(content, keep_citations=None, keep_body=None, config=None, is_new_issue=False):
17861785
"""Parse mail message; return message summary and stripped content
17871786
17881787
The message body is divided into sections by blank lines.
@@ -1806,8 +1805,30 @@ def parseContent(content, keep_citations=None, keep_body=None, config=None):
18061805
config = configuration.CoreConfig()
18071806
if keep_citations is None:
18081807
keep_citations = config["MAILGW_KEEP_QUOTED_TEXT"]
1808+
if keep_citations == "new":
1809+
# don't strip citations if we are a new issue
1810+
if is_new_issue:
1811+
keep_citations = True
1812+
else:
1813+
keep_citations = False
1814+
elif keep_citations == "yes":
1815+
keep_citations = True
1816+
else:
1817+
keep_citations = False
1818+
18091819
if keep_body is None:
18101820
keep_body = config["MAILGW_LEAVE_BODY_UNCHANGED"]
1821+
if keep_body == "new":
1822+
# don't strip citations if we are a new issue
1823+
if is_new_issue:
1824+
keep_body = True
1825+
else:
1826+
keep_body = False
1827+
elif keep_body == "yes":
1828+
keep_body = True
1829+
else:
1830+
keep_body = False
1831+
18111832
eol = config["MAILGW_EOL_RE"]
18121833
signature = config["MAILGW_SIGN_RE"]
18131834
original_msg = config["MAILGW_ORIGMSG_RE"]

test/test_mailgw.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2547,6 +2547,75 @@ def testEmailQuoting(self):
25472547
self.innerTestQuoting(self.firstquotingtest, '''This is a followup
25482548
''', 'This is a followup')
25492549

2550+
def testEmailQuotingNewIsNew(self):
2551+
self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'new'
2552+
# create the message, remove the prefix from subject
2553+
testmessage=self.firstquotingtest.replace(" Re: [issue1]", "")
2554+
nodeid = self._handle_mail(testmessage)
2555+
2556+
msgs = self.db.issue.get(nodeid, 'messages')
2557+
# validate content and summary
2558+
content = self.db.msg.get(msgs[0], 'content')
2559+
self.assertEqual(content, '''Blah blah wrote:
2560+
> Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
2561+
> skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
2562+
>
2563+
2564+
This is a followup''')
2565+
2566+
summary = self.db.msg.get(msgs[0], 'summary')
2567+
self.assertEqual(summary, '''This is a followup''')
2568+
2569+
def testEmailQuotingNewIsFollowup(self):
2570+
self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'new'
2571+
# create issue1 that we can followup on
2572+
self.doNewIssue()
2573+
# add the second message to the issue
2574+
nodeid = self._handle_mail(self.firstquotingtest)
2575+
msgs = self.db.issue.get(nodeid, 'messages')
2576+
# check second message for accuracy
2577+
content = self.db.msg.get(msgs[1], 'content')
2578+
summary = self.db.msg.get(msgs[1], 'summary')
2579+
self.assertEqual(content, '''This is a followup''')
2580+
self.assertEqual(summary, '''This is a followup''')
2581+
2582+
def testEmailReplaceBodyNewIsNew(self):
2583+
mysig = "--\nmy sig\n\n"
2584+
self.instance.config.EMAIL_LEAVE_BODY_UNCHANGED = 'new'
2585+
# create the message, remove the prefix from subject
2586+
testmessage=self.firstquotingtest.replace(" Re: [issue1]", "") + mysig
2587+
nodeid = self._handle_mail(testmessage)
2588+
2589+
msgs = self.db.issue.get(nodeid, 'messages')
2590+
# validate content and summary
2591+
content = self.db.msg.get(msgs[0], 'content')
2592+
self.assertEqual(content, '''Blah blah wrote:
2593+
> Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
2594+
> skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
2595+
>
2596+
2597+
This is a followup\n''' + mysig[:-2])
2598+
# the :-2 requrement to strip the trailing newlines is probably a bug
2599+
# somewhere mailgw has right content maybe trailing \n are stripped by
2600+
# msg or something.
2601+
2602+
summary = self.db.msg.get(msgs[0], 'summary')
2603+
self.assertEqual(summary, '''This is a followup''')
2604+
2605+
def testEmailReplaceBodyNewIsFollowup(self):
2606+
mysig = "\n--\nmy sig\n"
2607+
self.instance.config.EMAIL_LEAVE_BODY_UNCHANGED = 'new'
2608+
# create issue1 that we can followup on
2609+
self.doNewIssue()
2610+
# add the second message to the issue
2611+
nodeid = self._handle_mail(self.firstquotingtest + mysig)
2612+
msgs = self.db.issue.get(nodeid, 'messages')
2613+
# check second message for accuracy
2614+
content = self.db.msg.get(msgs[1], 'content')
2615+
summary = self.db.msg.get(msgs[1], 'summary')
2616+
self.assertEqual(content, '''Blah blah wrote:\n> Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf\n> skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj\n>\n\nThis is a followup''')
2617+
self.assertEqual(summary, '''This is a followup''')
2618+
25502619
def testEmailQuotingRemove(self):
25512620
self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
25522621
self.innerTestQuoting(self.firstquotingtest, '''Blah blah wrote:

0 commit comments

Comments
 (0)