launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #19341
[Merge] lp:~cjwatson/launchpad/message-for-header into lp:launchpad
Colin Watson has proposed merging lp:~cjwatson/launchpad/message-for-header into lp:launchpad.
Commit message:
Add an X-Launchpad-Message-For header with just the name of the person subscribed to the notification.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #1493844 in Launchpad itself: "Can't use gmail+new-verbose-footers to filter by group rationale"
https://bugs.launchpad.net/launchpad/+bug/1493844
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/message-for-header/+merge/270811
Add an X-Launchpad-Message-For header with just the name of the person subscribed to the notification.
There are several times more implementations of this than there ought to be, because not everything goes through BaseMailer yet; and the implementation for bug notifications is horrible because BugNotificationRecipient doesn't (I think) provide enough information.
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/message-for-header into lp:launchpad.
=== modified file 'lib/lp/answers/model/questionjob.py'
--- lib/lp/answers/model/questionjob.py 2015-08-25 16:24:06 +0000
+++ lib/lp/answers/model/questionjob.py 2015-09-11 12:44:20 +0000
@@ -236,6 +236,7 @@
for email in recipients.getEmails():
reason, header = recipients.getReason(email)
headers['X-Launchpad-Message-Rationale'] = header
+ headers['X-Launchpad-Message-For'] = reason.subscriber.name
formatted_body = self.buildBody(reason.getReason())
simple_sendmail(
self.from_address, email, self.subject, formatted_body,
=== modified file 'lib/lp/bugs/doc/bugnotification-email.txt'
--- lib/lp/bugs/doc/bugnotification-email.txt 2015-07-31 14:46:31 +0000
+++ lib/lp/bugs/doc/bugnotification-email.txt 2015-09-11 12:44:20 +0000
@@ -585,6 +585,12 @@
>>> print notification_email['X-Launchpad-Message-Rationale']
Because-I-said-so
+The X-Launchpad-Message-For header is set from the to_person (since this
+notification is not for a team).
+
+ >>> print notification_email['X-Launchpad-Message-For']
+ name16
+
The references parameter sets the References header of the email.
>>> print notification_email['References']
=== modified file 'lib/lp/bugs/doc/bugnotification-sending.txt'
--- lib/lp/bugs/doc/bugnotification-sending.txt 2015-07-13 16:14:46 +0000
+++ lib/lp/bugs/doc/bugnotification-sending.txt 2015-09-11 12:44:20 +0000
@@ -22,6 +22,7 @@
>>> def print_notification_headers(email_notification, extra_headers=[]):
... for header in ['To', 'From', 'Subject',
... 'X-Launchpad-Message-Rationale',
+ ... 'X-Launchpad-Message-For',
... 'X-Launchpad-Subscription'] + extra_headers:
... if email_notification[header]:
... print "%s: %s" % (header, email_notification[header])
@@ -73,6 +74,7 @@
From: Sample Person <1@xxxxxxxxxxxxxxxxxx>
Subject: [Bug 1] subject
X-Launchpad-Message-Rationale: Subscriber (mozilla-firefox in Ubuntu)
+ X-Launchpad-Message-For: name16
<BLANKLINE>
a comment.
<BLANKLINE>
@@ -82,6 +84,7 @@
From: Sample Person <1@xxxxxxxxxxxxxxxxxx>
Subject: [Bug 1] subject
X-Launchpad-Message-Rationale: Assignee
+ X-Launchpad-Message-For: mark
<BLANKLINE>
a comment.
<BLANKLINE>
@@ -91,6 +94,7 @@
From: Sample Person <1@xxxxxxxxxxxxxxxxxx>
Subject: [Bug 1] subject
X-Launchpad-Message-Rationale: Subscriber
+ X-Launchpad-Message-For: name12
<BLANKLINE>
a comment.
<BLANKLINE>
@@ -154,6 +158,7 @@
From: Sample Person <1@xxxxxxxxxxxxxxxxxx>
Subject: Re: [Bug 1] subject
X-Launchpad-Message-Rationale: Assignee
+ X-Launchpad-Message-For: mark
<BLANKLINE>
a new comment.
<BLANKLINE>
@@ -193,6 +198,7 @@
From: Sample Person <1@xxxxxxxxxxxxxxxxxx>
Subject: [Bug 1] Re: Firefox does not support SVG
X-Launchpad-Message-Rationale: Assignee
+ X-Launchpad-Message-For: mark
<BLANKLINE>
** Summary changed:
- Old summary
@@ -239,6 +245,7 @@
From: Sample Person <1@xxxxxxxxxxxxxxxxxx>
Subject: [Bug 1] Re: Firefox does not support SVG
X-Launchpad-Message-Rationale: Assignee
+ X-Launchpad-Message-For: mark
<BLANKLINE>
a new comment.
<BLANKLINE>
@@ -366,6 +373,7 @@
From: Sample Person <16@xxxxxxxxxxxxxxxxxx>
Subject: [Bug 16] [NEW] new bug
X-Launchpad-Message-Rationale: Subscriber
+ X-Launchpad-Message-For: name12
<BLANKLINE>
Public bug reported:
...
@@ -396,6 +404,7 @@
From: Sample Person <16@xxxxxxxxxxxxxxxxxx>
Subject: [Bug 16] subject
X-Launchpad-Message-Rationale: Subscriber
+ X-Launchpad-Message-For: name12
X-Launchpad-Bug-Duplicate: 1
<BLANKLINE>
*** This bug is a duplicate of bug 1 ***
@@ -432,6 +441,7 @@
From: Sample Person <...@bugs.launchpad.net>
Subject: [Bug ...] [NEW] Zero-day on Frobulator
X-Launchpad-Message-Rationale: Subscriber
+ X-Launchpad-Message-For: name12
<BLANKLINE>
*** This bug is a security vulnerability ***
<BLANKLINE>
@@ -456,6 +466,7 @@
From: Sample Person <...@bugs.launchpad.net>
Subject: [Bug ...] subject
X-Launchpad-Message-Rationale: Subscriber
+ X-Launchpad-Message-For: name12
<BLANKLINE>
a comment.
<BLANKLINE>
@@ -538,6 +549,7 @@
References: foo@xxxxxxxxxxx-332342--1231
...
X-Launchpad-Message-Rationale: Assignee
+ X-Launchpad-Message-For: name12
...
INFO Notifying foo.bar@xxxxxxxxxxxxx about bug 1.
...
@@ -548,6 +560,7 @@
References: sdsdfsfd
...
X-Launchpad-Message-Rationale: Subscriber (mozilla-firefox in Ubuntu)
+ X-Launchpad-Message-For: name16
...
INFO Notifying mark@xxxxxxxxxxx about bug 1.
...
@@ -564,6 +577,7 @@
References: sdsdfsfd
...
X-Launchpad-Message-Rationale: Subscriber (mozilla-firefox in Ubuntu)
+ X-Launchpad-Message-For: name16
Errors-To: bounces@xxxxxxxxxxxxx
Return-Path: bounces@xxxxxxxxxxxxx
Precedence: bulk
@@ -840,12 +854,14 @@
... "will be automatically wrapped by the BugNotification "
... "machinery. Ain't technology great?")
... verbose_person = factory.makePerson(
- ... displayname='Verbose Person', email='verbose@xxxxxxxxxxx',
+ ... name='verbose-person', displayname='Verbose Person',
+ ... email='verbose@xxxxxxxxxxx',
... selfgenerated_bugnotifications=True)
... verbose_person.verbose_bugnotifications = True
... ignored = bug.subscribe(verbose_person, verbose_person)
... concise_person = factory.makePerson(
- ... displayname='Concise Person', email='concise@xxxxxxxxxxx')
+ ... name='concise-person', displayname='Concise Person',
+ ... email='concise@xxxxxxxxxxx')
... concise_person.verbose_bugnotifications = False
... ignored = bug.subscribe(concise_person, concise_person)
@@ -858,7 +874,7 @@
... name='conciseteam', displayname='Concise Team')
... concise_team.verbose_bugnotifications = False
... concise_team_person = factory.makePerson(
- ... displayname='Concise Team Person',
+ ... name='conciseteam-person', displayname='Concise Team Person',
... email='conciseteam@xxxxxxxxxxx')
... concise_team_person.verbose_bugnotifications = True
... ignored = concise_team.addMember(
@@ -873,7 +889,7 @@
... name='verboseteam', displayname='Verbose Team')
... verbose_team.verbose_bugnotifications = True
... verbose_team_person = factory.makePerson(
- ... displayname='Verbose Team Person',
+ ... name='verboseteam-person', displayname='Verbose Team Person',
... email='verboseteam@xxxxxxxxxxx')
... verbose_team_person.verbose_bugnotifications = False
... ignored = verbose_team.addMember(
@@ -934,6 +950,7 @@
From: Verbose Person <verbose@xxxxxxxxxxx>
Subject: [Bug ...] subject
X-Launchpad-Message-Rationale: Subscriber
+ X-Launchpad-Message-For: concise-person
<BLANKLINE>
a really simple comment.
<BLANKLINE>
@@ -961,6 +978,7 @@
From: Verbose Person <verbose@xxxxxxxxxxx>
Subject: [Bug ...] subject
X-Launchpad-Message-Rationale: Subscriber @verboseteam
+ X-Launchpad-Message-For: verboseteam
<BLANKLINE>
a really simple comment.
<BLANKLINE>
@@ -980,6 +998,7 @@
From: Verbose Person <verbose@xxxxxxxxxxx>
Subject: [Bug ...] subject
X-Launchpad-Message-Rationale: Subscriber
+ X-Launchpad-Message-For: verbose-person
<BLANKLINE>
a really simple comment.
<BLANKLINE>
@@ -1010,6 +1029,7 @@
From: Verbose Person <verbose@xxxxxxxxxxx>
Subject: [Bug ...] subject
X-Launchpad-Message-Rationale: Subscriber @conciseteam
+ X-Launchpad-Message-For: conciseteam
<BLANKLINE>
a really simple comment.
<BLANKLINE>
@@ -1134,6 +1154,7 @@
From: Sample Person <...@bugs.launchpad.net>
Subject: [Bug 1] subject
X-Launchpad-Message-Rationale: Subscriber (Mozilla Firefox)
+ X-Launchpad-Message-For: no-priv
<BLANKLINE>
another comment.
<BLANKLINE>
@@ -1190,6 +1211,7 @@
From: Sample Person <...@bugs.launchpad.net>
Subject: [Bug 1] subject
X-Launchpad-Message-Rationale: Subscriber (Mozilla Firefox)
+ X-Launchpad-Message-For: no-priv
X-Launchpad-Subscription: Allow-comments filter
<BLANKLINE>
another comment.
@@ -1245,6 +1267,7 @@
From: Sample Person <...@bugs.launchpad.net>
Subject: [Bug 1] subject
X-Launchpad-Message-Rationale: Subscriber @addressless
+ X-Launchpad-Message-For: addressless
<BLANKLINE>
no comment for no-priv.
<BLANKLINE>
@@ -1291,6 +1314,7 @@
From: Sample Person <...@bugs.launchpad.net>
Subject: [Bug 1] subject
X-Launchpad-Message-Rationale: Subscriber (Mozilla Firefox)
+ X-Launchpad-Message-For: no-priv
X-Launchpad-Subscription: Allow-comments filter
<BLANKLINE>
no comment for no-priv.
@@ -1350,6 +1374,7 @@
From: Sample Person <...@bugs.launchpad.net>
Subject: [Bug 1] Re: Firefox does not support SVG
X-Launchpad-Message-Rationale: Subscriber @addressless
+ X-Launchpad-Message-For: addressless
<BLANKLINE>
** Summary changed:
- Whatever
@@ -1405,6 +1430,7 @@
From: Sample Person <...@bugs.launchpad.net>
Subject: [Bug 1] Re: Firefox does not support SVG
X-Launchpad-Message-Rationale: Subscriber (Mozilla Firefox)
+ X-Launchpad-Message-For: no-priv
<BLANKLINE>
** Summary changed:
- I'm losing my
=== modified file 'lib/lp/bugs/doc/initial-bug-contacts.txt'
--- lib/lp/bugs/doc/initial-bug-contacts.txt 2012-08-16 07:02:41 +0000
+++ lib/lp/bugs/doc/initial-bug-contacts.txt 2015-09-11 12:44:20 +0000
@@ -191,6 +191,8 @@
>>> msg['X-Launchpad-Message-Rationale']
'Subscriber (pmount in Ubuntu)'
+ >>> msg['X-Launchpad-Message-For']
+ 'daf'
>>> msg['Subject']
'[Bug 1] [NEW] Firefox does not support SVG'
=== modified file 'lib/lp/bugs/mail/bugnotificationbuilder.py'
--- lib/lp/bugs/mail/bugnotificationbuilder.py 2015-08-28 06:44:52 +0000
+++ lib/lp/bugs/mail/bugnotificationbuilder.py 2015-09-11 12:44:20 +0000
@@ -13,6 +13,7 @@
from email.mime.text import MIMEText
from email.utils import formatdate
+import re
import rfc822
from zope.component import getUtility
@@ -207,6 +208,16 @@
if rationale is not None:
headers.append(('X-Launchpad-Message-Rationale', rationale))
+ # XXX cjwatson 2015-09-11: The ridiculously complicated way that
+ # bug notifications are built means that we no longer have
+ # direct access to the subscriber name at this point. As a
+ # stopgap, parse it out of the rationale.
+ match = re.search(r'@([^ ]*)', rationale)
+ if match is not None:
+ message_for = match.group(1)
+ else:
+ message_for = removeSecurityProxy(to_person).name
+ headers.append(('X-Launchpad-Message-For', message_for))
if filters is not None:
for filter in filters:
=== modified file 'lib/lp/bugs/stories/bugs/bug-add-subscriber.txt'
--- lib/lp/bugs/stories/bugs/bug-add-subscriber.txt 2012-07-27 01:15:04 +0000
+++ lib/lp/bugs/stories/bugs/bug-add-subscriber.txt 2015-09-11 12:44:20 +0000
@@ -82,6 +82,7 @@
Reply-To: Bug ... <...@bugs.launchpad.net>
...
X-Launchpad-Message-Rationale: Subscriber
+ X-Launchpad-Message-For: ddaa
...
You have been subscribed to a public bug by No Privileges Person (no-priv):
...
=== modified file 'lib/lp/code/doc/branch-merge-proposal-notifications.txt'
--- lib/lp/code/doc/branch-merge-proposal-notifications.txt 2015-09-02 16:54:24 +0000
+++ lib/lp/code/doc/branch-merge-proposal-notifications.txt 2015-09-11 12:44:20 +0000
@@ -29,13 +29,15 @@
>>> previewdiff = factory.makePreviewDiff(merge_proposal=bmp)
>>> transaction.commit()
>>> source_subscriber = factory.makePerson(
- ... email='source@xxxxxxxxxxx', displayname='Source Subscriber')
+ ... email='source@xxxxxxxxxxx', name='source-subscriber',
+ ... displayname='Source Subscriber')
>>> _unused = bmp.source_branch.subscribe(source_subscriber,
... BranchSubscriptionNotificationLevel.NOEMAIL,
... BranchSubscriptionDiffSize.NODIFF,
... CodeReviewNotificationLevel.STATUS, source_subscriber)
>>> target_subscriber = factory.makePerson(
- ... email='target@xxxxxxxxxxx', displayname='Target Subscriber')
+ ... email='target@xxxxxxxxxxx', name='target-subscriber',
+ ... displayname='Target Subscriber')
>>> target_subscription = bmp.target_branch.subscribe(target_subscriber,
... BranchSubscriptionNotificationLevel.NOEMAIL,
... BranchSubscriptionDiffSize.NODIFF,
@@ -136,6 +138,8 @@
~person-name...
>>> print notification['X-Launchpad-Message-Rationale']
Subscriber
+ >>> print notification['X-Launchpad-Message-For']
+ source-subscriber
>>> print notification.get_payload(decode=True)
Eric has proposed merging
lp://dev/~person-name...into lp://dev/~person-name...
@@ -176,11 +180,12 @@
>>> for notification in notifications:
... print "%s, %s" % (
... notification['X-Envelope-To'],
- ... notification['X-Launchpad-Message-Rationale'])
- bob@xxxxxxxxxxx, Reviewer
- mary@xxxxxxxxxxx, Reviewer
- source@xxxxxxxxxxx, Subscriber
- target@xxxxxxxxxxx, Subscriber
+ ... notification['X-Launchpad-Message-Rationale'],
+ ... notification['X-Launchpad-Message-For'])
+ bob@xxxxxxxxxxx, Reviewer, bob
+ mary@xxxxxxxxxxx, Reviewer, mary
+ source@xxxxxxxxxxx, Subscriber, source-subscriber
+ target@xxxxxxxxxxx, Subscriber, target-subscriber
>>> notification = notifications[0]
>>> print notification.get_payload()[0].get_payload(decode=True)
Eric has proposed merging
=== modified file 'lib/lp/code/doc/branch-notifications.txt'
--- lib/lp/code/doc/branch-notifications.txt 2015-09-02 16:54:24 +0000
+++ lib/lp/code/doc/branch-notifications.txt 2015-09-11 12:44:20 +0000
@@ -60,6 +60,8 @@
~name12/firefox/main
>>> print branch_notification['X-Launchpad-Message-Rationale']
Subscriber
+ >>> print branch_notification['X-Launchpad-Message-For']
+ name12
>>> notification_body = branch_notification.get_payload(decode=True)
>>> print notification_body #doctest: -NORMALIZE_WHITESPACE
The contents.
=== modified file 'lib/lp/code/doc/codeimport.txt'
--- lib/lp/code/doc/codeimport.txt 2014-02-24 07:19:52 +0000
+++ lib/lp/code/doc/codeimport.txt 2015-09-11 12:44:20 +0000
@@ -100,6 +100,8 @@
New code import: widget/trunk-cvs
>>> print message['X-Launchpad-Message-Rationale']
Operator @vcs-imports
+ >>> print message['X-Launchpad-Message-For']
+ vcs-imports
>>> print message.get_payload(decode=True)
A new CVS code import has been requested by Code Import Person:
http://code.launchpad.dev/~import-person/widget/trunk-cvs
=== modified file 'lib/lp/code/mail/codeimport.py'
--- lib/lp/code/mail/codeimport.py 2014-02-24 07:19:52 +0000
+++ lib/lp/code/mail/codeimport.py 2015-09-11 12:44:20 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2015 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Email notifications related to code imports."""
@@ -65,6 +65,7 @@
headers = {'X-Launchpad-Branch': code_import.branch.unique_name,
'X-Launchpad-Message-Rationale':
'Operator @%s' % vcs_imports.name,
+ 'X-Launchpad-Message-For': vcs_imports.name,
'X-Launchpad-Notification-Type': 'code-import',
}
for address in get_contact_email_addresses(vcs_imports):
@@ -185,6 +186,7 @@
else:
template_params['rationale'] = rationale
template_params['unsubscribe'] = ''
+ for_person = vcs_imports
else:
if subscription.notification_level in interested_levels:
template_params['rationale'] = (
@@ -197,10 +199,12 @@
"%s/+edit-subscription." % canonical_url(branch))
else:
template_params['unsubscribe'] = ''
+ for_person = subscription.person
else:
# Don't send email to this subscriber.
continue
headers['X-Launchpad-Message-Rationale'] = rationale
+ headers['X-Launchpad-Message-For'] = for_person.name
body = email_template % template_params
simple_sendmail(from_address, email_address, subject, body, headers)
=== modified file 'lib/lp/code/mail/tests/test_branch.py'
--- lib/lp/code/mail/tests/test_branch.py 2015-09-02 16:54:24 +0000
+++ lib/lp/code/mail/tests/test_branch.py 2015-09-11 12:44:20 +0000
@@ -227,6 +227,7 @@
self.assertEqual(
{'X-Launchpad-Branch': branch.unique_name,
'X-Launchpad-Message-Rationale': 'Subscriber',
+ 'X-Launchpad-Message-For': bob.name,
'X-Launchpad-Notification-Type': 'branch-updated',
'X-Launchpad-Project': self.getBranchProjectName(branch),
'Message-Id': '<foobar-example-com>'},
@@ -247,6 +248,7 @@
self.assertEqual(
{'X-Launchpad-Branch': branch.unique_name,
'X-Launchpad-Message-Rationale': 'Subscriber',
+ 'X-Launchpad-Message-For': bob.name,
'X-Launchpad-Notification-Type': 'branch-revision',
'X-Launchpad-Branch-Revision-Number': '1',
'X-Launchpad-Project': self.getBranchProjectName(branch),
=== modified file 'lib/lp/code/mail/tests/test_branchmergeproposal.py'
--- lib/lp/code/mail/tests/test_branchmergeproposal.py 2015-09-02 16:54:24 +0000
+++ lib/lp/code/mail/tests/test_branchmergeproposal.py 2015-09-11 12:44:20 +0000
@@ -135,6 +135,7 @@
self.assertEqual(
{'X-Launchpad-Branch': bmp.source_branch.unique_name,
'X-Launchpad-Message-Rationale': 'Subscriber',
+ 'X-Launchpad-Message-For': subscriber.name,
'X-Launchpad-Notification-Type': 'code-review',
'X-Launchpad-Project': bmp.source_branch.product.name,
'Reply-To': bmp.address,
=== modified file 'lib/lp/code/mail/tests/test_codereviewcomment.py'
--- lib/lp/code/mail/tests/test_codereviewcomment.py 2015-09-08 11:56:33 +0000
+++ lib/lp/code/mail/tests/test_codereviewcomment.py 2015-09-11 12:44:20 +0000
@@ -164,6 +164,7 @@
rationale = mailer._recipients.getReason('subscriber@xxxxxxxxxxx')[1]
expected = {'X-Launchpad-Branch': source_branch.unique_name,
'X-Launchpad-Message-Rationale': rationale,
+ 'X-Launchpad-Message-For': subscriber.name,
'X-Launchpad-Notification-Type': 'code-review',
'X-Launchpad-Project': source_branch.product.name,
'Message-Id': message.rfc822msgid,
@@ -221,6 +222,7 @@
'You are subscribed to branch %s.' % source_branch.bzr_identity,
'',
'Launchpad-Message-Rationale: %s' % rationale,
+ 'Launchpad-Message-For: %s' % subscriber.name,
'Launchpad-Notification-Type: code-review',
'Launchpad-Branch: %s' % source_branch.unique_name,
'Launchpad-Project: %s' % source_branch.product.name,
=== modified file 'lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py'
--- lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py 2015-09-02 16:54:24 +0000
+++ lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py 2015-09-11 12:44:20 +0000
@@ -84,6 +84,8 @@
self.assertEqual(
'Requester', ctrl.headers['X-Launchpad-Message-Rationale'])
self.assertEqual(
+ build.requester.name, ctrl.headers['X-Launchpad-Message-For'])
+ self.assertEqual(
'recipe-build-status',
ctrl.headers['X-Launchpad-Notification-Type'])
self.assertEqual(
@@ -119,6 +121,8 @@
self.assertEqual(
'Requester', ctrl.headers['X-Launchpad-Message-Rationale'])
self.assertEqual(
+ build.requester.name, ctrl.headers['X-Launchpad-Message-For'])
+ self.assertEqual(
'recipe-build-status',
ctrl.headers['X-Launchpad-Notification-Type'])
self.assertEqual(
=== modified file 'lib/lp/registry/browser/person.py'
--- lib/lp/registry/browser/person.py 2015-08-06 16:48:48 +0000
+++ lib/lp/registry/browser/person.py 2015-09-11 12:44:20 +0000
@@ -4327,7 +4327,7 @@
return
try:
send_direct_contact_email(
- sender_email, self.recipients, subject, message)
+ sender_email, self.recipients, self.context, subject, message)
except QuotaReachedError as error:
fmt_date = DateTimeFormatterAPI(self.next_try)
self.request.response.addErrorNotification(
=== modified file 'lib/lp/registry/doc/teammembership-email-notification.txt'
--- lib/lp/registry/doc/teammembership-email-notification.txt 2015-09-02 02:46:18 +0000
+++ lib/lp/registry/doc/teammembership-email-notification.txt 2015-09-11 12:44:20 +0000
@@ -1067,10 +1067,11 @@
... name='team-two', email='team-two@xxxxxxxxxxx', owner=owner)
>>> ignored = team_one.addMember(team_two, owner, force_team_add=True)
>>> run_mail_jobs()
- >>> print_distinct_emails()
+ >>> print_distinct_emails(include_for=True)
From: Team One ...
To: Team Two <team-two...>
X-Launchpad-Message-Rationale: Member (team-one) @team-two
+ X-Launchpad-Message-For: team-two
X-Launchpad-Notification-Type: team-membership-new
Subject: team-two joined team-one
<BLANKLINE>
=== modified file 'lib/lp/registry/mail/notification.py'
--- lib/lp/registry/mail/notification.py 2015-09-02 02:46:18 +0000
+++ lib/lp/registry/mail/notification.py 2015-09-11 12:44:20 +0000
@@ -157,13 +157,15 @@
def send_direct_contact_email(
- sender_email, recipients_set, subject, body):
+ sender_email, recipients_set, person_or_team, subject, body):
"""Send a direct user-to-user email.
:param sender_email: The email address of the sender.
:type sender_email: string
:param recipients_set: The recipients.
- :type recipients_set:' A ContactViaWebNotificationSet
+ :type recipients_set: `ContactViaWebNotificationSet`
+ :param person_or_team: The party that is the context of the email.
+ :type person_or_team: `IPerson`
:param subject: The Subject header.
:type subject: unicode
:param body: The message body.
@@ -209,7 +211,7 @@
message = None
for recipient_email, recipient in recipients_set.getRecipientPersons():
recipient_name = str(encode(recipient.displayname))
- reason, rational_header = recipients_set.getReason(recipient_email)
+ reason, rationale_header = recipients_set.getReason(recipient_email)
reason = str(encode(reason)).replace('\n ', '\n')
formatted_body = mailwrapper.format(body, force_wrap=True)
formatted_body += additions % reason
@@ -219,7 +221,8 @@
message['To'] = formataddr((recipient_name, recipient_email))
message['Subject'] = subject_header
message['Message-ID'] = make_msgid('launchpad')
- message['X-Launchpad-Message-Rationale'] = rational_header
+ message['X-Launchpad-Message-Rationale'] = rationale_header
+ message['X-Launchpad-Message-For'] = person_or_team.name
# Send the message.
sendmail(message, bulk=False)
# Use the information from the last message sent to record the action
=== modified file 'lib/lp/registry/model/productjob.py'
--- lib/lp/registry/model/productjob.py 2015-07-09 20:06:17 +0000
+++ lib/lp/registry/model/productjob.py 2015-09-11 12:44:20 +0000
@@ -1,4 +1,4 @@
-# Copyright 2012 Canonical Ltd. This software is licensed under the
+# Copyright 2012-2015 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Jobs classes to update products and send notifications."""
@@ -321,6 +321,7 @@
'X-Launchpad-Project':
'%(product_displayname)s (%(product_name)s)' % message_data,
'X-Launchpad-Message-Rationale': rationale,
+ 'X-Launchpad-Message-For': self.product.owner.name,
}
if reply_to is not None:
headers['Reply-To'] = reply_to
=== modified file 'lib/lp/registry/tests/test_notification.py'
--- lib/lp/registry/tests/test_notification.py 2012-12-26 01:04:05 +0000
+++ lib/lp/registry/tests/test_notification.py 2015-09-11 12:44:20 +0000
@@ -1,4 +1,4 @@
-# Copyright 2012 Canonical Ltd. This software is licensed under the
+# Copyright 2012-2015 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Test notification classes and functions."""
@@ -28,7 +28,8 @@
recipients_set = NotificationRecipientSet()
recipients_set.add(user, 'test reason', 'test rationale')
pop_notifications()
- send_direct_contact_email('me@xxxxxx', recipients_set, subject, body)
+ send_direct_contact_email(
+ 'me@xxxxxx', recipients_set, user, subject, body)
notifications = pop_notifications()
notification = notifications[0]
self.assertEqual(1, len(notifications))
@@ -37,6 +38,7 @@
self.assertEqual(subject, notification['Subject'])
self.assertEqual(
'test rationale', notification['X-Launchpad-Message-Rationale'])
+ self.assertEqual(user.name, notification['X-Launchpad-Message-For'])
self.assertIs(None, notification['Precedence'])
self.assertTrue('launchpad' in notification['Message-ID'])
self.assertEqual(
@@ -61,7 +63,7 @@
authorization.record(old_message)
self.assertRaises(
QuotaReachedError, send_direct_contact_email,
- 'me@xxxxxx', recipients_set, 'subject', 'body')
+ 'me@xxxxxx', recipients_set, user, 'subject', 'body')
def test_empty_recipient_set(self):
# The recipient set can be empty. No messages are sent and the
@@ -75,7 +77,7 @@
authorization.record(old_message)
pop_notifications()
send_direct_contact_email(
- 'me@xxxxxx', recipients_set, 'subject', 'body')
+ 'me@xxxxxx', recipients_set, user, 'subject', 'body')
notifications = pop_notifications()
self.assertEqual(0, len(notifications))
self.assertTrue(authorization.is_allowed)
@@ -87,7 +89,8 @@
recipients_set.add(user, 'test reason', 'test rationale')
pop_notifications()
body = 'Can you help me? ' * 8
- send_direct_contact_email('me@xxxxxx', recipients_set, 'subject', body)
+ send_direct_contact_email(
+ 'me@xxxxxx', recipients_set, user, 'subject', body)
notifications = pop_notifications()
body, footer = notifications[0].get_payload().split('-- ')
self.assertEqual(
@@ -105,7 +108,8 @@
recipients_set = NotificationRecipientSet()
recipients_set.add(user, 'test reason', 'test rationale')
pop_notifications()
- send_direct_contact_email('me@xxxxxx', recipients_set, 'test', 'test')
+ send_direct_contact_email(
+ 'me@xxxxxx', recipients_set, user, 'test', 'test')
notifications = pop_notifications()
notification = notifications[0]
self.assertEqual(
=== modified file 'lib/lp/registry/tests/test_productjob.py'
--- lib/lp/registry/tests/test_productjob.py 2015-07-08 16:05:11 +0000
+++ lib/lp/registry/tests/test_productjob.py 2015-09-11 12:44:20 +0000
@@ -1,4 +1,4 @@
-# Copyright 2010-2012 Canonical Ltd. This software is licensed under the
+# Copyright 2010-2015 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Tests for ProductJobs."""
@@ -442,6 +442,7 @@
('X-Launchpad-Project', '%s (%s)' %
(product.displayname, product.name)),
('X-Launchpad-Message-Rationale', 'Maintainer'),
+ ('X-Launchpad-Message-For', product.owner.name),
('Reply-To', reply_to),
]
self.assertContentEqual(expected_headers, headers.items())
@@ -458,6 +459,7 @@
('X-Launchpad-Project', '%s (%s)' %
(product.displayname, product.name)),
('X-Launchpad-Message-Rationale', 'Maintainer'),
+ ('X-Launchpad-Message-For', product.owner.name),
]
self.assertContentEqual(expected_headers, headers.items())
=== modified file 'lib/lp/services/mail/basemailer.py'
--- lib/lp/services/mail/basemailer.py 2015-08-27 14:34:21 +0000
+++ lib/lp/services/mail/basemailer.py 2015-09-11 12:44:20 +0000
@@ -123,6 +123,8 @@
reason, rationale = self._recipients.getReason(email)
headers = OrderedDict()
headers['X-Launchpad-Message-Rationale'] = reason.mail_header
+ if reason.subscriber.name is not None:
+ headers['X-Launchpad-Message-For'] = reason.subscriber.name
if self.notification_type is not None:
headers['X-Launchpad-Notification-Type'] = self.notification_type
reply_to = self._getReplyToAddress(email, recipient)
=== modified file 'lib/lp/services/mail/notificationrecipientset.py'
--- lib/lp/services/mail/notificationrecipientset.py 2015-08-26 13:41:21 +0000
+++ lib/lp/services/mail/notificationrecipientset.py 2015-09-11 12:44:20 +0000
@@ -29,6 +29,7 @@
correspond to a real Person.
"""
+ name = None
displayname = None
is_team = False
expanded_notification_footers = False
=== modified file 'lib/lp/services/mail/tests/test_basemailer.py'
--- lib/lp/services/mail/tests/test_basemailer.py 2015-08-23 22:53:55 +0000
+++ lib/lp/services/mail/tests/test_basemailer.py 2015-09-11 12:44:20 +0000
@@ -168,7 +168,8 @@
def test_generateEmail_append_expanded_footer(self):
# Recipients with expanded_notification_footers receive an expanded
# footer on messages.
- fake_to = self.factory.makePerson(email='to@xxxxxxxxxxx')
+ fake_to = self.factory.makePerson(
+ name='to-person', email='to@xxxxxxxxxxx')
fake_to.expanded_notification_footers = True
recipients = {fake_to: FakeSubscription()}
mailer = BaseMailerSubclass(
@@ -179,6 +180,7 @@
ctrl.body, EndsWith(
'\n-- \n'
'Launchpad-Message-Rationale: pete\n'
+ 'Launchpad-Message-For: to-person\n'
'Launchpad-Notification-Type: test\n'))
def test_sendall_single_failure_doesnt_kill_all(self):
=== modified file 'lib/lp/snappy/tests/test_snapbuild.py'
--- lib/lp/snappy/tests/test_snapbuild.py 2015-08-03 13:20:45 +0000
+++ lib/lp/snappy/tests/test_snapbuild.py 2015-09-11 12:44:20 +0000
@@ -255,6 +255,7 @@
"unstable" % build.id, subject)
self.assertEqual(
"Requester", notification["X-Launchpad-Message-Rationale"])
+ self.assertEqual(person.name, notification["X-Launchpad-Message-For"])
self.assertEqual(
"snap-build-status",
notification["X-Launchpad-Notification-Type"])
=== modified file 'lib/lp/soyuz/mail/tests/test_packageupload.py'
--- lib/lp/soyuz/mail/tests/test_packageupload.py 2015-08-25 23:27:09 +0000
+++ lib/lp/soyuz/mail/tests/test_packageupload.py 2015-09-11 12:44:20 +0000
@@ -132,6 +132,7 @@
"X-Launchpad-Message-Rationale": Equals("Announcement"),
"X-Launchpad-Notification-Type": Equals("package-upload"),
}))
+ self.assertNotIn("X-Launchpad-Message-For", dict(notifications[1]))
def test_forAction_announce_from_person_override_with_unicode_names(self):
# PackageUploadMailer.forAction() takes an optional
@@ -164,6 +165,7 @@
"X-Launchpad-Message-Rationale": Equals("Announcement"),
"X-Launchpad-Notification-Type": Equals("package-upload"),
}))
+ self.assertNotIn("X-Launchpad-Message-For", dict(notifications[1]))
def test_forAction_bcc_to_derivatives_list(self):
# PackageUploadMailer.forAction() will BCC the announcement email to
@@ -186,6 +188,7 @@
"X-Launchpad-Message-Rationale": Equals("Announcement"),
"X-Launchpad-Notification-Type": Equals("package-upload"),
}))
+ self.assertNotIn("X-Launchpad-Message-For", dict(notifications[1]))
def test_fetch_information_spr_multiple_changelogs(self):
# If previous_version is passed the "changelog" entry in the
@@ -454,15 +457,17 @@
"accepted", blamer, spr, [], [], archive, distroseries,
PackagePublishingPocket.RELEASE, changes=changes)
recipients = dict(mailer._recipients.getRecipientPersons())
- for email, rationale in (
- (blamer.preferredemail.email, "Requester"),
- ("maintainer@xxxxxxxxxxx", "Maintainer"),
- ("changer@xxxxxxxxxxx", "Changed-By")):
+ for person, rationale in (
+ (blamer, "Requester"),
+ (maintainer, "Maintainer"),
+ (changer, "Changed-By")):
+ email = person.preferredemail.email
headers = mailer._getHeaders(email, recipients[email])
self.assertThat(
headers,
ContainsDict({
"X-Launchpad-Message-Rationale": Equals(rationale),
+ "X-Launchpad-Message-For": Equals(person.name),
"X-Launchpad-Notification-Type": Equals("package-upload"),
"X-Katie": Equals("Launchpad actually"),
"X-Launchpad-Archive": Equals(archive.reference),
@@ -497,14 +502,16 @@
"accepted", blamer, spr, [], [], archive, distroseries,
PackagePublishingPocket.RELEASE, changes=changes)
recipients = dict(mailer._recipients.getRecipientPersons())
- for email, rationale in (
- (blamer.preferredemail.email, "Requester"),
- (uploader.preferredemail.email, "PPA Uploader")):
+ for person, rationale in (
+ (blamer, "Requester"),
+ (uploader, "PPA Uploader")):
+ email = person.preferredemail.email
headers = mailer._getHeaders(email, recipients[email])
self.assertThat(
headers,
ContainsDict({
"X-Launchpad-Message-Rationale": Equals(rationale),
+ "X-Launchpad-Message-For": Equals(person.name),
"X-Launchpad-Notification-Type": Equals("package-upload"),
"X-Katie": Equals("Launchpad actually"),
"X-Launchpad-Archive": Equals(archive.reference),
=== modified file 'lib/lp/soyuz/tests/test_build_notify.py'
--- lib/lp/soyuz/tests/test_build_notify.py 2015-09-04 12:19:07 +0000
+++ lib/lp/soyuz/tests/test_build_notify.py 2015-09-11 12:44:20 +0000
@@ -105,10 +105,13 @@
format_address_for_person(recipient), notification['To'])
if reason == "buildd-admin":
rationale = "Buildd-Admin @launchpad-buildd-admins"
+ expected_for = "launchpad-buildd-admins"
else:
rationale = reason.title()
+ expected_for = recipient.name
self.assertEqual(
rationale, notification['X-Launchpad-Message-Rationale'])
+ self.assertEqual(expected_for, notification['X-Launchpad-Message-For'])
self.assertEqual(
'package-build-status',
notification['X-Launchpad-Notification-Type'])
=== modified file 'lib/lp/soyuz/tests/test_livefsbuild.py'
--- lib/lp/soyuz/tests/test_livefsbuild.py 2015-08-03 12:59:18 +0000
+++ lib/lp/soyuz/tests/test_livefsbuild.py 2015-09-11 12:44:20 +0000
@@ -1,4 +1,4 @@
-# Copyright 2014 Canonical Ltd. This software is licensed under the
+# Copyright 2014-2015 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Test live filesystem build features."""
@@ -257,6 +257,7 @@
"unstable" % build.id, subject)
self.assertEqual(
"Requester", notification["X-Launchpad-Message-Rationale"])
+ self.assertEqual(person.name, notification["X-Launchpad-Message-For"])
self.assertEqual(
"livefs-build-status",
notification["X-Launchpad-Notification-Type"])
=== modified file 'lib/lp/testing/mail_helpers.py'
--- lib/lp/testing/mail_helpers.py 2015-09-02 02:46:18 +0000
+++ lib/lp/testing/mail_helpers.py 2015-09-11 12:44:20 +0000
@@ -60,8 +60,8 @@
def print_emails(include_reply_to=False, group_similar=False,
- include_rationale=False, notifications=None,
- include_notification_type=False):
+ include_rationale=False, include_for=False,
+ notifications=None, include_notification_type=False):
"""Pop all messages from stub.test_emails and print them with
their recipients.
@@ -76,6 +76,7 @@
:param group_similar: Group messages sent to multiple recipients if True.
:param include_rationale: Include the X-Launchpad-Message-Rationale
header.
+ :param include_for: Include the X-Launchpad-Message-For header.
:param notifications: Use the provided list of notifications instead of
the stack.
:param include_notification_type: Include the
@@ -106,8 +107,10 @@
print 'Reply-To:', message['Reply-To']
rationale_header = 'X-Launchpad-Message-Rationale'
if include_rationale and rationale_header in message:
- print (
- '%s: %s' % (rationale_header, message[rationale_header]))
+ print '%s: %s' % (rationale_header, message[rationale_header])
+ for_header = 'X-Launchpad-Message-For'
+ if include_for and for_header in message:
+ print '%s: %s' % (for_header, message[for_header])
notification_type_header = 'X-Launchpad-Notification-Type'
if include_notification_type and notification_type_header in message:
print '%s: %s' % (
@@ -118,11 +121,12 @@
def print_distinct_emails(include_reply_to=False, include_rationale=True,
- include_notification_type=True):
+ include_for=False, include_notification_type=True):
"""A convenient shortcut for `print_emails`(group_similar=True)."""
return print_emails(group_similar=True,
include_reply_to=include_reply_to,
include_rationale=include_rationale,
+ include_for=include_for,
include_notification_type=include_notification_type)
Follow ups