Updated Branches:
refs/heads/master 9e35b6f85 -> 5da3d1f30
[#6328] ticket:448 Set Message-ID for first ticket notification
When ticket is created set Message-ID: in corresponding notification to
ticket.message_id(). Thus later we can use this value in top-level
comments notifications as In-Reply-To: and References: to group emails
in one thread.
Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/0b5ceda0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/0b5ceda0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/0b5ceda0
Branch: refs/heads/master
Commit: 0b5ceda03e77c34b9c860d66fb95a46f7a402fce
Parents: 734bf8a
Author: Igor Bondarenko <jetmind2@gmail.com>
Authored: Wed Oct 23 08:36:22 2013 +0000
Committer: Cory Johns <cjohns@slashdotmedia.com>
Committed: Thu Oct 24 18:59:28 2013 +0000
----------------------------------------------------------------------
Allura/allura/lib/mail_util.py | 1 +
Allura/allura/model/notification.py | 3 +-
ForgeTracker/forgetracker/model/ticket.py | 9 ++-
.../forgetracker/tests/functional/test_root.py | 62 +++++++++++++++++++-
4 files changed, 70 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/0b5ceda0/Allura/allura/lib/mail_util.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/mail_util.py b/Allura/allura/lib/mail_util.py
index db7ddb3..3a67e10 100644
--- a/Allura/allura/lib/mail_util.py
+++ b/Allura/allura/lib/mail_util.py
@@ -195,6 +195,7 @@ class SMTPClient(object):
if not isinstance(in_reply_to, basestring):
raise TypeError('Only strings are supported now, not lists')
message['In-Reply-To'] = Header(u'<%s>' % in_reply_to)
+ message['References'] = message['In-Reply-To']
content = message.as_string()
smtp_addrs = map(_parse_smtp_addr, addrs)
smtp_addrs = [ a for a in smtp_addrs if isvalid(a) ]
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/0b5ceda0/Allura/allura/model/notification.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/notification.py b/Allura/allura/model/notification.py
index 95b51ba..718a60f 100644
--- a/Allura/allura/model/notification.py
+++ b/Allura/allura/model/notification.py
@@ -184,13 +184,14 @@ class Notification(MappedClass):
h.get_first(idx, 'title'),
getattr(artifact, 'email_address', u'noreply@in.sf.net'))
d = dict(
- message_id=artifact.message_id(),
from_address=reply_to,
reply_to_address=reply_to,
subject=subject_prefix + subject,
text=kwargs.pop('text', subject),
author_id=c.user._id,
pubdate=datetime.utcnow())
+ if kwargs.get('message_id'):
+ d['_id'] = kwargs['message_id']
if c.user.get_pref('email_address'):
d['from_address'] = '"%s" <%s>' % (
c.user.get_pref('display_name'),
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/0b5ceda0/ForgeTracker/forgetracker/model/ticket.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index d580c43..5bd7788 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -799,7 +799,14 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
subject = self.email_subject
Thread.new(discussion_id=self.app_config.discussion_id,
ref_id=self.index_id())
- n = Notification.post(artifact=self, topic='metadata', text=description, subject=subject)
+ # First ticket notification. Use persistend Message-ID (self.message_id()).
+ # Thus we can group notification emails in one thread later.
+ n = Notification.post(
+ message_id=self.message_id(),
+ artifact=self,
+ topic='metadata',
+ text=description,
+ subject=subject)
if monitoring_email and n and (not self.private or
self.app.config.options.get('TicketMonitoringType') in (
'NewTicketsOnly', 'AllTicketChanges')):
http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/0b5ceda0/ForgeTracker/forgetracker/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index cfd2a61..d524563 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -2684,10 +2684,10 @@ class TestStats(TrackerTestController):
assert_in('# tickets: 0', r.body)
-class TestNotifications(TrackerTestController):
+class TestNotificationEmailGrouping(TrackerTestController):
- def test_notification_email_grouping(self):
- ticket_view = self.new_ticket(summary='Test Ticket')
+ def test_new_ticket_message_id(self):
+ self.new_ticket(summary='Test Ticket')
ThreadLocalORMSession.flush_all()
M.MonQTask.run_ready()
ThreadLocalORMSession.flush_all()
@@ -2695,3 +2695,59 @@ class TestNotifications(TrackerTestController):
ticket = tm.Ticket.query.get(ticket_num=1)
assert_equal(email.kwargs.message_id, ticket.message_id())
assert_equal(email.kwargs.in_reply_to, None)
+
+ def test_comments(self):
+ ticket_view = self.new_ticket(summary='Test Ticket').follow()
+ ThreadLocalORMSession.flush_all()
+ M.MonQTask.query.remove()
+ ThreadLocalORMSession.flush_all()
+ # Messy code to add a comment
+ for f in ticket_view.html.findAll('form'):
+ if f.get('action', '').endswith('/post'):
+ break
+ post_content = 'top-level comment'
+ params = dict()
+ inputs = f.findAll('input')
+ for field in inputs:
+ if field.has_key('name'):
+ params[field['name']] = field.has_key('value') and field['value'] or ''
+ params[f.find('textarea')['name']] = post_content
+ r = self.app.post(f['action'].encode('utf-8'), params=params,
+ headers={'Referer': '/bugs/1/'.encode("utf-8")})
+ ThreadLocalORMSession.flush_all()
+ M.MonQTask.run_ready()
+ ThreadLocalORMSession.flush_all()
+ # Check that comment notification refers ticket's message id
+ email = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendmail')).first()
+ ticket = tm.Ticket.query.get(ticket_num=1)
+ top_level_comment = ticket.discussion_thread.posts[0]
+ top_level_comment_msg_id = ticket.url() + top_level_comment._id
+ assert_equal(email.kwargs.message_id, top_level_comment_msg_id)
+ assert_equal(email.kwargs.in_reply_to, ticket.message_id())
+
+ ThreadLocalORMSession.flush_all()
+ M.MonQTask.query.remove()
+ ThreadLocalORMSession.flush_all()
+ # Messy code to add reply
+ r = self.app.get('/bugs/1/')
+ post_link = str(r.html.find('div', {'class': 'edit_post_form reply'}).find('form')['action'])
+ post_form = r.html.find('form', {'action': post_link + 'reply'})
+ params = dict()
+ inputs = post_form.findAll('input')
+ for field in inputs:
+ if field.has_key('name'):
+ params[field['name']] = field.has_key('value') and field['value'] or ''
+ reply_text = 'Reply to top-level-comment'
+ params[post_form.find('textarea')['name']] = reply_text
+ r = self.app.post(post_link + 'reply',
+ params=params,
+ headers={'Referer':post_link.encode("utf-8")})
+ ThreadLocalORMSession.flush_all()
+ M.MonQTask.run_ready()
+ ThreadLocalORMSession.flush_all()
+ # Check that reply notification refers top-level comment's message id
+ email = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendmail')).first()
+ ticket = tm.Ticket.query.get(ticket_num=1)
+ reply = [post for post in ticket.discussion_thread.posts if post.text == reply_text][0]
+ assert_equal(email.kwargs.message_id, ticket.url() + reply._id)
+ assert_equal(email.kwargs.in_reply_to, top_level_comment_msg_id)
|