2014-10-28 16:10:44 +00:00
|
|
|
import logging
|
2015-01-15 22:11:05 +00:00
|
|
|
import json
|
2016-08-08 20:29:47 +00:00
|
|
|
import features
|
2014-10-28 16:10:44 +00:00
|
|
|
|
2013-09-27 23:29:01 +00:00
|
|
|
from flask.ext.mail import Message
|
|
|
|
|
2014-07-29 17:47:54 +00:00
|
|
|
from app import mail, app, get_app_url
|
2014-10-22 23:01:56 +00:00
|
|
|
from util.jinjautil import get_template_env
|
2014-09-05 23:57:33 +00:00
|
|
|
|
2014-10-28 16:10:44 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
2014-10-22 23:01:56 +00:00
|
|
|
template_env = get_template_env("emails")
|
2014-09-05 23:57:33 +00:00
|
|
|
|
2014-10-28 16:10:44 +00:00
|
|
|
class CannotSendEmailException(Exception):
|
|
|
|
pass
|
|
|
|
|
2015-01-15 22:11:05 +00:00
|
|
|
class GmailAction(object):
|
|
|
|
""" Represents an action that can be taken in Gmail in response to the email. """
|
|
|
|
def __init__(self, metadata):
|
|
|
|
self.metadata = metadata
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def confirm(name, url, description):
|
|
|
|
return GmailAction({
|
|
|
|
"@context": "http://schema.org",
|
|
|
|
"@type": "EmailMessage",
|
|
|
|
"action": {
|
|
|
|
"@type": 'ConfirmAction',
|
|
|
|
"name": name,
|
|
|
|
"handler": {
|
|
|
|
"@type": "HttpActionHandler",
|
|
|
|
"url": get_app_url() + '/' + url
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"description": description
|
|
|
|
})
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def view(name, url, description):
|
|
|
|
return GmailAction({
|
|
|
|
"@context": "http://schema.org",
|
|
|
|
"@type": "EmailMessage",
|
|
|
|
"action": {
|
|
|
|
"@type": 'ViewAction',
|
|
|
|
"name": name,
|
|
|
|
"url": get_app_url() + '/' + url
|
|
|
|
},
|
|
|
|
"description": description
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
def send_email(recipient, subject, template_file, parameters, action=None):
|
2014-09-05 23:57:33 +00:00
|
|
|
app_title = app.config['REGISTRY_TITLE_SHORT']
|
|
|
|
app_url = get_app_url()
|
|
|
|
|
2016-08-02 23:10:04 +00:00
|
|
|
def app_link_handler(url=None):
|
2016-08-08 20:29:47 +00:00
|
|
|
return app_url + '/' + url if url else app_url
|
2014-09-05 23:57:33 +00:00
|
|
|
|
2016-08-09 16:18:35 +00:00
|
|
|
app_logo = app.config.get('ENTERPRISE_LOGO_URL', 'https://quay.io/static/img/quay-logo.png')
|
|
|
|
|
2014-11-24 21:07:38 +00:00
|
|
|
parameters.update({
|
2014-09-05 23:57:33 +00:00
|
|
|
'subject': subject,
|
2016-08-09 16:18:35 +00:00
|
|
|
'app_logo': app_logo,
|
2014-09-05 23:57:33 +00:00
|
|
|
'app_url': app_url,
|
|
|
|
'app_title': app_title,
|
2016-08-08 20:29:47 +00:00
|
|
|
'hosted': features.BILLING,
|
2015-01-15 22:11:05 +00:00
|
|
|
'app_link': app_link_handler,
|
|
|
|
'action_metadata': json.dumps(action.metadata) if action else None
|
2014-09-05 23:57:33 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
rendered_html = template_env.get_template(template_file + '.html').render(parameters)
|
|
|
|
|
2014-10-10 17:14:33 +00:00
|
|
|
msg = Message('[%s] %s' % (app_title, subject), recipients=[recipient])
|
2014-09-05 23:57:33 +00:00
|
|
|
msg.html = rendered_html
|
2013-09-27 23:29:01 +00:00
|
|
|
|
2014-10-28 16:10:44 +00:00
|
|
|
try:
|
|
|
|
mail.send(msg)
|
|
|
|
except Exception as ex:
|
2014-11-03 22:16:36 +00:00
|
|
|
logger.exception('Error while trying to send email to %s', recipient)
|
2014-10-28 16:10:44 +00:00
|
|
|
raise CannotSendEmailException(ex.message)
|
2013-09-27 23:29:01 +00:00
|
|
|
|
2014-09-05 23:57:33 +00:00
|
|
|
def send_password_changed(username, email):
|
|
|
|
send_email(email, 'Account password changed', 'passwordchanged', {
|
|
|
|
'username': username
|
|
|
|
})
|
2014-04-17 20:18:37 +00:00
|
|
|
|
2014-09-05 23:57:33 +00:00
|
|
|
def send_email_changed(username, old_email, new_email):
|
|
|
|
send_email(old_email, 'Account e-mail address changed', 'emailchanged', {
|
|
|
|
'username': username,
|
|
|
|
'new_email': new_email
|
2014-11-24 21:07:38 +00:00
|
|
|
})
|
2014-04-15 21:00:32 +00:00
|
|
|
|
2014-01-17 22:04:05 +00:00
|
|
|
def send_change_email(username, email, token):
|
2014-09-05 23:57:33 +00:00
|
|
|
send_email(email, 'E-mail address change requested', 'changeemail', {
|
|
|
|
'username': username,
|
|
|
|
'token': token
|
|
|
|
})
|
2014-01-17 22:04:05 +00:00
|
|
|
|
2013-09-27 23:29:01 +00:00
|
|
|
def send_confirmation_email(username, email, token):
|
2015-01-15 22:11:05 +00:00
|
|
|
action = GmailAction.confirm('Confirm E-mail', 'confirm?code=' + token,
|
|
|
|
'Verification of e-mail address')
|
|
|
|
|
2014-09-05 23:57:33 +00:00
|
|
|
send_email(email, 'Please confirm your e-mail address', 'confirmemail', {
|
|
|
|
'username': username,
|
|
|
|
'token': token
|
2015-01-15 22:11:05 +00:00
|
|
|
}, action=action)
|
2013-10-14 21:50:07 +00:00
|
|
|
|
2014-07-28 18:58:12 +00:00
|
|
|
def send_repo_authorization_email(namespace, repository, email, token):
|
2015-01-15 22:11:05 +00:00
|
|
|
action = GmailAction.confirm('Verify E-mail', 'authrepoemail?code=' + token,
|
|
|
|
'Verification of e-mail address')
|
|
|
|
|
2014-09-05 23:57:33 +00:00
|
|
|
subject = 'Please verify your e-mail address for repository %s/%s' % (namespace, repository)
|
|
|
|
send_email(email, subject, 'repoauthorizeemail', {
|
|
|
|
'namespace': namespace,
|
|
|
|
'repository': repository,
|
|
|
|
'token': token
|
2015-01-15 22:11:05 +00:00
|
|
|
}, action=action)
|
2014-07-28 18:58:12 +00:00
|
|
|
|
2015-12-28 20:25:31 +00:00
|
|
|
|
|
|
|
def send_org_recovery_email(org, admin_users):
|
|
|
|
subject = 'Organization %s recovery' % (org.username)
|
|
|
|
send_email(org.email, subject, 'orgrecovery', {
|
|
|
|
'organization': org.username,
|
|
|
|
'admin_usernames': [user.username for user in admin_users],
|
|
|
|
})
|
|
|
|
|
|
|
|
|
2013-10-14 21:50:07 +00:00
|
|
|
def send_recovery_email(email, token):
|
2015-01-15 22:11:05 +00:00
|
|
|
action = GmailAction.view('Recover Account', 'recovery?code=' + token,
|
2015-01-16 19:57:09 +00:00
|
|
|
'Recovery of an account')
|
2015-01-15 22:11:05 +00:00
|
|
|
|
2014-09-05 23:57:33 +00:00
|
|
|
subject = 'Account recovery'
|
|
|
|
send_email(email, subject, 'recovery', {
|
|
|
|
'email': email,
|
|
|
|
'token': token
|
2015-01-16 19:57:09 +00:00
|
|
|
}, action=action)
|
2014-09-05 23:57:33 +00:00
|
|
|
|
|
|
|
def send_payment_failed(email, username):
|
|
|
|
send_email(email, 'Subscription Payment Failure', 'paymentfailure', {
|
|
|
|
'username': username
|
|
|
|
})
|
2013-11-15 19:42:31 +00:00
|
|
|
|
2014-09-18 17:20:32 +00:00
|
|
|
def send_org_invite_email(member_name, member_email, orgname, team, adder, code):
|
2015-01-16 19:57:09 +00:00
|
|
|
action = GmailAction.view('Join %s' % team, 'confirminvite?code=' + code,
|
2015-01-15 22:11:05 +00:00
|
|
|
'Invitation to join a team')
|
|
|
|
|
2014-09-18 17:20:32 +00:00
|
|
|
send_email(member_email, 'Invitation to join team', 'teaminvite', {
|
|
|
|
'inviter': adder,
|
|
|
|
'token': code,
|
|
|
|
'organization': orgname,
|
|
|
|
'teamname': team
|
2015-01-15 22:11:05 +00:00
|
|
|
}, action=action)
|
2013-11-15 19:42:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
def send_invoice_email(email, contents):
|
2014-09-05 23:57:33 +00:00
|
|
|
# Note: This completely generates the contents of the email, so we don't use the
|
|
|
|
# normal template here.
|
2015-11-02 19:16:04 +00:00
|
|
|
msg = Message('Quay payment received - Thank you!', recipients=[email])
|
2013-11-15 19:42:31 +00:00
|
|
|
msg.html = contents
|
|
|
|
mail.send(msg)
|
2014-04-15 21:00:32 +00:00
|
|
|
|
|
|
|
|
2014-09-05 23:57:33 +00:00
|
|
|
# INTERNAL EMAILS BELOW
|
|
|
|
|
2014-04-17 20:18:37 +00:00
|
|
|
def send_subscription_change(change_description, customer_id, customer_email, quay_username):
|
2014-09-05 23:57:33 +00:00
|
|
|
SUBSCRIPTION_CHANGE_TITLE = 'Subscription Change - {0} {1}'
|
2014-09-23 20:28:06 +00:00
|
|
|
SUBSCRIPTION_CHANGE = """
|
|
|
|
Change: {0}<br>
|
|
|
|
Customer id: <a href="https://manage.stripe.com/customers/{1}">{1}</a><br>
|
|
|
|
Customer email: <a href="mailto:{2}">{2}</a><br>
|
|
|
|
Quay user or org name: {3}<br>
|
|
|
|
"""
|
2014-11-24 21:07:38 +00:00
|
|
|
|
2014-04-17 20:18:37 +00:00
|
|
|
title = SUBSCRIPTION_CHANGE_TITLE.format(quay_username, change_description)
|
2014-10-10 17:14:33 +00:00
|
|
|
msg = Message(title, recipients=['stripe@quay.io'])
|
2014-04-17 20:18:37 +00:00
|
|
|
msg.html = SUBSCRIPTION_CHANGE.format(change_description, customer_id, customer_email,
|
|
|
|
quay_username)
|
2014-04-15 21:00:32 +00:00
|
|
|
mail.send(msg)
|
2014-04-22 17:56:34 +00:00
|
|
|
|
|
|
|
|