diff --git a/emails/verification-notice.spt b/emails/verification-notice.spt
index b48abd72ca..d6675cb568 100644
--- a/emails/verification-notice.spt
+++ b/emails/verification-notice.spt
@@ -1,13 +1,72 @@
-{{ _("Connecting {0} to {1} on Gratipay.", new_email, username) }}
+{{ _("New activity on your account") }}
[---] text/html
-{{ _("We are connecting {0} to the {1} account on Gratipay. This is a notification "
- "sent to {2} because that is the primary email address we have on file.",
- ('%s'|safe) % new_email,
- ('{0}'|safe).format(username),
- ('%s'|safe) % email) }}
-
+{% if new_email_verified %}
+{{ ngettext( "We are connecting the {package_name} npm package to the {username} account on "
+ "Gratipay. This is a notification sent to {email_address} because that is the "
+ "primary email address we have on file."
+ , "We are connecting {n} npm packages to the {username} account on Gratipay. This is "
+ "a notification sent to {email_address} because that is the primary email address "
+ "we have on file."
+ , n=npackages
+ , package_name=('{}'|safe).format(package_name)
+ , username=('{0}'|safe).format(username)
+ , email_address=('{}'|safe).format(email)
+ ) }}
+{% elif npackages > 0 %}
+{{ ngettext( "We are connecting {email_address} and the {package_name} npm package to the "
+ "{username} account on Gratipay. This is a notification sent to {email_address_2} "
+ "because that is the primary email address we have on file."
+ , "We are connecting {email_address} and {n} npm packages to the {username} account on "
+ "Gratipay. This is a notification sent to {email_address_2} because that is the "
+ "primary email address we have on file."
+ , n=npackages
+ , package_name=('{}'|safe).format(package_name)
+ , username=('{0}'|safe).format(username)
+ , email_address=('{}'|safe).format(new_email)
+ , email_address_2=('{}'|safe).format(email)
+ ) }}
+{% else %}
+{{ _( "We are connecting {email_address} to the {username} account on Gratipay. This is a "
+ "notification sent to {email_address_2} because that is the primary email address we have "
+ "on file."
+ , username=('{0}'|safe).format(username)
+ , email_address=('{}'|safe).format(new_email)
+ , email_address_2=('{}'|safe).format(email)
+ ) }}
+ {% endif %}
[---] text/plain
-{{ _("We are connecting {0} to the {1} account on Gratipay. This is a notification "
- "sent to {2} because that is the primary email address we have on file.",
- new_email, username, email) }}
+{% if new_email_verified %}
+{{ ngettext( "We are connecting the {package_name} npm package to the {username} account on "
+ "Gratipay. This is a notification sent to {email_address} because that is the "
+ "primary email address we have on file."
+ , "We are connecting {n} npm packages to the {username} account on Gratipay. This is "
+ "a notification sent to {email_address} because that is the primary email address "
+ "we have on file."
+ , n=npackages
+ , package_name=package_name
+ , username=username
+ , email_address=email
+ ) }}
+{% elif npackages > 0 %}
+{{ ngettext( "We are connecting {email_address} and the {package_name} npm package to the "
+ "{username} account on Gratipay. This is a notification sent to {email_address_2} "
+ "because that is the primary email address we have on file."
+ , "We are connecting {email_address} and {n} npm packages to the {username} account on "
+ "Gratipay. This is a notification sent to {email_address_2} because that is the "
+ "primary email address we have on file."
+ , n=npackages
+ , package_name=package_name
+ , username=username
+ , email_address=new_email
+ , email_address_2=email
+ ) }}
+{% else %}
+{{ _( "We are connecting {email_address} to the {username} account on Gratipay. This is a "
+ "notification sent to {email_address_2} because that is the primary email address we have "
+ "on file."
+ , username=username
+ , email_address=new_email
+ , email_address_2=email
+ ) }}
+ {% endif %}
diff --git a/emails/verification.spt b/emails/verification.spt
index 906c24a505..006d850527 100644
--- a/emails/verification.spt
+++ b/emails/verification.spt
@@ -1,16 +1,63 @@
{{ _("Connect to {0} on Gratipay?", username) }}
[---] text/html
-{{ _("We've received a request to connect {0} to the {1} account on Gratipay. Sound familiar?",
- ('%s'|safe) % email,
- ('{0}'|safe).format(username)) }}
+{% if new_email_verified %}
+{{ ngettext( "We've received a request to connect the {package_name} npm package to the "
+ "{username} account on Gratipay. Sound familiar?"
+ , "We've received a request to connect {n} npm packages to the {username} account "
+ "on Gratipay. Sound familiar?"
+ , n=npackages
+ , package_name=('{}'|safe).format(package_name)
+ , username=('{0}'|safe).format(username)
+ ) }}
+{% elif npackages > 0 %}
+{{ ngettext( "We've received a request to connect {email_address} and the {package_name} npm "
+ "package to the {username} account on Gratipay. Sound familiar?"
+ , "We've received a request to connect {email_address} and {n} npm packages to the "
+ "{username} account on Gratipay. Sound familiar?"
+ , n=npackages
+ , package_name=('{}'|safe).format(package_name)
+ , email_address=('{}'|safe).format(new_email)
+ , username=('{0}'|safe).format(username)
+ ) }}
+{% else %}
+{{ _( "We've received a request to connect {email_address} to the {username} account on Gratipay. "
+ "Sound familiar?"
+ , email_address=('{}'|safe).format(new_email)
+ , username=('{0}'|safe).format(username)
+ ) }}
+{% endif %}
{{ _("Yes, proceed!") }}
[---] text/plain
-{{ _("We've received a request to connect {0} to the {1} account on Gratipay. Sound familiar?",
- email, username) }}
+{% if new_email_verified %}
+{{ ngettext( "We've received a request to connect the {package_name} npm package to the "
+ "{username} account on Gratipay. Sound familiar?"
+ , "We've received a request to connect {n} npm packages to the {username} account "
+ "on Gratipay. Sound familiar?"
+ , n=npackages
+ , package_name=package_name
+ , username=username
+ ) }}
+{% elif npackages > 0 %}
+{{ ngettext( "We've received a request to connect {email_address} and the {package_name} npm "
+ "package to the {username} account on Gratipay. Sound familiar?"
+ , "We've received a request to connect {email_address} and {n} npm packages to the "
+ "{username} account on Gratipay. Sound familiar?"
+ , n=npackages
+ , package_name=package_name
+ , email_address=new_email
+ , username=username
+ ) }}
+{% else %}
+{{ _( "We've received a request to connect {email_address} to the {username} account on Gratipay. "
+ "Sound familiar?"
+ , email_address=new_email
+ , username=username
+ ) }}
+{% endif %}
{{ _("Follow this link to finish connecting your email:") }}
diff --git a/gratipay/models/participant/email.py b/gratipay/models/participant/email.py
index ae4fcb62f2..4581f7133c 100644
--- a/gratipay/models/participant/email.py
+++ b/gratipay/models/participant/email.py
@@ -65,21 +65,24 @@ def start_email_verification(self, email, *packages):
self.validate_email_verification_request(c, email, *packages)
link = self.get_email_verification_link(c, email, *packages)
- self.app.email_queue.put( self
- , 'verification'
- , email=email
- , link=link
- , include_unsubscribe=False
- )
- if self.email_address:
+ verified_emails = self.get_verified_email_addresses()
+ kwargs = dict( npackages=len(packages)
+ , package_name=packages[0].name if packages else ''
+ , new_email=email
+ , new_email_verified=email in verified_emails
+ , link=link
+ , include_unsubscribe=False
+ )
+ self.app.email_queue.put(self, 'verification', email=email, **kwargs)
+ if self.email_address and self.email_address != email:
self.app.email_queue.put( self
, 'verification-notice'
- , new_email=email
- , include_unsubscribe=False
# Don't count this one against their sending quota.
# It's going to their own verified address, anyway.
, _user_initiated=False
+
+ , **kwargs
)
diff --git a/tests/py/test_email.py b/tests/py/test_email.py
index 48ef5a44ad..07ce43148a 100644
--- a/tests/py/test_email.py
+++ b/tests/py/test_email.py
@@ -307,51 +307,55 @@ def test_html_escaping(self):
assert 'foo'bar' in last_email['body_html']
assert ''' not in last_email['body_text']
+ def test_npm_package_name_is_handled_safely(self):
+ foo = self.make_package(name='