Skip to content
This repository has been archived by the owner on Feb 8, 2018. It is now read-only.

Send confirmation email #4335

Merged
merged 23 commits into from Apr 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
617eca2
Improvements to fake_data.make_package
chadwhitacre Mar 22, 2017
3c86a13
Factor out a method to clarify logic in add_email
chadwhitacre Mar 22, 2017
7ebd268
Add packages parameter to start_email_verification
chadwhitacre Mar 23, 2017
3d06713
Rename start_email_verification to get_*_link
chadwhitacre Mar 27, 2017
8cc556e
Rename add_email to start_email_verification
chadwhitacre Mar 27, 2017
46792fd
Fix subtle bug in test_adds_events
chadwhitacre Mar 27, 2017
85e4378
Refactor email verification methods
chadwhitacre Mar 27, 2017
9e5cd99
Make some guesses at what recursion is about
chadwhitacre Mar 27, 2017
64017dd
Clean up a few little things
chadwhitacre Mar 27, 2017
0c91a13
Beef up test suite around start_email_verification
chadwhitacre Mar 27, 2017
ca9a6b6
Move cursor creation up a level
chadwhitacre Mar 27, 2017
a694122
Add *packages param to start_email_verification
chadwhitacre Mar 27, 2017
e66262f
Clear out old claims on resend
chadwhitacre Mar 27, 2017
437f4a7
Remove claims when emails removed
chadwhitacre Mar 27, 2017
86ccce4
LazyResponse -> LocalizedErrorResponse
chadwhitacre Mar 27, 2017
2e979de
Clean up error handling
chadwhitacre Mar 28, 2017
8799c69
Expose packages arg in the modify.json endpoint
chadwhitacre Mar 29, 2017
8eba761
Update ttw tests
chadwhitacre Mar 29, 2017
53b7fb9
Start standardizing on dash in email template name
chadwhitacre Mar 29, 2017
01c837f
Extend verification template for package claiming
chadwhitacre Mar 30, 2017
136591a
Give more details about Aspen workaround
chadwhitacre Apr 13, 2017
2c2a3a5
Make somewhat clever function a little clearer
chadwhitacre Apr 13, 2017
9926985
Fix regression in start_package_claims
chadwhitacre Apr 13, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
72 changes: 72 additions & 0 deletions emails/verification-notice.spt
@@ -0,0 +1,72 @@
{{ _("New activity on your account") }}

[---] text/html
{% 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=('<b>{}</b>'|safe).format(package_name)
, username=('<b><a href="https://gratipay.com/{0}/">{0}</a></b>'|safe).format(username)
, email_address=('<b>{}</b>'|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=('<b>{}</b>'|safe).format(package_name)
, username=('<b><a href="https://gratipay.com/{0}/">{0}</a></b>'|safe).format(username)
, email_address=('<b>{}</b>'|safe).format(new_email)
, email_address_2=('<b>{}</b>'|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=('<b><a href="https://gratipay.com/{0}/">{0}</a></b>'|safe).format(username)
, email_address=('<b>{}</b>'|safe).format(new_email)
, email_address_2=('<b>{}</b>'|safe).format(email)
) }}
{% endif %}
[---] text/plain
{% 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 %}
57 changes: 52 additions & 5 deletions 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?",
('<b>%s</b>'|safe) % email,
('<b><a href="https://gratipay.com/~{0}/">{0}</a></b>'|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?"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if it doesn't sound familiar?

What if it does, for that matter? I don't really know what I would do if I received an email like this.

Am I supposed to click the package name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Down on line 32 there's a "Yes, proceed!" button. Here's what it looks like:

screen shot 2017-04-13 at 8 41 55 am

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, woops - didn't see that! Thanks!

, "We've received a request to connect {n} npm packages to the {username} account "
"on Gratipay. Sound familiar?"
, n=npackages
, package_name=('<b>{}</b>'|safe).format(package_name)
, username=('<b><a href="https://gratipay.com/~{0}/">{0}</a></b>'|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=('<b>{}</b>'|safe).format(package_name)
, email_address=('<b>{}</b>'|safe).format(new_email)
, username=('<b><a href="https://gratipay.com/~{0}/">{0}</a></b>'|safe).format(username)
) }}
{% else %}
{{ _( "We've received a request to connect {email_address} to the {username} account on Gratipay. "
"Sound familiar?"
, email_address=('<b>{}</b>'|safe).format(new_email)
, username=('<b><a href="https://gratipay.com/~{0}/">{0}</a></b>'|safe).format(username)
) }}
{% endif %}
<br>
<br>
<a href="{{ link }}" style="{{ button_style }}">{{ _("Yes, proceed!") }}</a>

[---] 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:") }}

Expand Down
13 changes: 0 additions & 13 deletions emails/verification_notice.spt

This file was deleted.

5 changes: 2 additions & 3 deletions error.spt
Expand Up @@ -2,8 +2,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera

from aspen.http import status_strings

from gratipay.utils import LazyResponse
from gratipay.utils.i18n import HTTP_ERRORS
from gratipay.utils.i18n import HTTP_ERRORS, LocalizedErrorResponse

[----------------------------------------]

Expand All @@ -19,7 +18,7 @@ try:
except Exception as e:
website.tell_sentry(e, state)

if isinstance(response, LazyResponse):
if isinstance(response, LocalizedErrorResponse):
response.render_body(state)
err = response.body
if code == 500 and not err:
Expand Down
6 changes: 3 additions & 3 deletions gratipay/elsewhere/__init__.py
Expand Up @@ -17,7 +17,7 @@
from requests_oauthlib import OAuth1Session, OAuth2Session

from gratipay.elsewhere._extractors import not_available
from gratipay.utils import LazyResponse
from gratipay.utils.i18n import LocalizedErrorResponse


ACTIONS = {'opt-in', 'connect'}
Expand Down Expand Up @@ -137,13 +137,13 @@ def msg(_, to_age):
return _("You've consumed your quota of requests, you can try again in {0}.", to_age(reset))
else:
return _("You're making requests too fast, please try again later.")
raise LazyResponse(status, msg)
raise LocalizedErrorResponse(status, msg)
if status != 200:
log('{} api responded with {}:\n{}'.format(self.name, status, response.text)
, level=logging.ERROR)
msg = lambda _: _("{0} returned an error, please try again later.",
self.display_name)
raise LazyResponse(502, msg)
raise LocalizedErrorResponse(502, msg)

return response

Expand Down
32 changes: 21 additions & 11 deletions gratipay/exceptions.py
Expand Up @@ -4,7 +4,7 @@

from __future__ import print_function, unicode_literals

from aspen import Response
from gratipay.utils.i18n import LocalizedErrorResponse


class ProblemChangingUsername(Exception):
Expand All @@ -27,28 +27,37 @@ class UsernameAlreadyTaken(ProblemChangingUsername):
msg = "The username '{}' is already taken."


class ProblemChangingEmail(Response):
def __init__(self, *args):
Response.__init__(self, 400, self.msg.format(*args))
class ProblemChangingEmail(LocalizedErrorResponse):
pass

class EmailAlreadyVerified(ProblemChangingEmail):
msg = "{} is already verified for this Gratipay account."
def lazy_body(self, _):
return _("You have already added and verified that address.")

class EmailTaken(ProblemChangingEmail):
msg = "{} is already connected to a different Gratipay account."
def lazy_body(self, _):
return _("That address is already linked to a different Gratipay account.")

class CannotRemovePrimaryEmail(ProblemChangingEmail):
msg = "You cannot remove your primary email address."
def lazy_body(self, _):
return _("You cannot remove your primary email address.")

class EmailNotOnFile(ProblemChangingEmail):
def lazy_body(self, _):
return _("That email address is not on file for this package.")

class EmailNotVerified(ProblemChangingEmail):
msg = "The email address '{}' is not verified."
def lazy_body(self, _):
return _("That email address is not verified.")

class TooManyEmailAddresses(ProblemChangingEmail):
msg = "You've reached the maximum number of email addresses we allow."
def lazy_body(self, _):
return _("You've reached the maximum number of email addresses we allow.")


class Throttled(Exception):
msg = "You've initiated too many emails too quickly. Please try again in a minute or two."
class Throttled(LocalizedErrorResponse):
def lazy_body(self, _):
return _("You've initiated too many emails too quickly. Please try again in a minute or two.")


class ProblemChangingNumber(Exception):
Expand Down Expand Up @@ -78,3 +87,4 @@ def __str__(self):
return "Negative balance not allowed in this context."

class NotWhitelisted(Exception): pass
class NoPackages(Exception): pass
7 changes: 0 additions & 7 deletions gratipay/models/package/__init__.py
Expand Up @@ -40,10 +40,3 @@ def from_names(cls, package_manager, name):
"""
return cls.db.one("SELECT packages.*::packages FROM packages "
"WHERE package_manager=%s and name=%s", (package_manager, name))


# Emails
# ======

def send_confirmation_email(self, address):
pass