From 240210d43e990d90828e905968f68e6eabf4e656 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Sun, 18 Mar 2018 20:15:48 +0100 Subject: [PATCH 1/9] first use of email templates --- rowers/tasks.py | 37 ++++++++++++++++++++++------------ rowers/templates/csvemail.html | 14 +++++++++++++ rowers/templates/csvemail.txt | 5 +++++ rowers/utils.py | 1 + 4 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 rowers/templates/csvemail.html create mode 100644 rowers/templates/csvemail.txt diff --git a/rowers/tasks.py b/rowers/tasks.py index 42568a6e..98e3c3d5 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -6,6 +6,7 @@ import gzip import shutil import numpy as np + from scipy import optimize import rowingdata @@ -40,7 +41,13 @@ from rowers.dataprepnodjango import ( create_c2_stroke_data_db ) -from django.core.mail import send_mail, EmailMessage + +from django.core.mail import ( + send_mail, + EmailMessage,EmailMultiAlternatives, + ) +from django.template.loader import get_template +from django.template import Context from django.db.utils import OperationalError import datautils @@ -51,7 +58,7 @@ import arrow # testing task - +from django.contrib.staticfiles import finders @app.task def add(x, y): @@ -625,24 +632,28 @@ def handle_sendemailcsv(first_name, last_name, email, csvfile,**kwargs): # send email with attachment fullemail = first_name + " " + last_name + " " + "<" + email + ">" subject = "File from Rowsandall.com" - message = "Dear " + first_name + ",\n\n" - message += "Please find attached the requested file for your workout.\n\n" - message += "Best Regards, the Rowsandall Team" - - - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) + plaintext = get_template('csvemail.txt') + htmly = get_template('csvemail.html') + + d = {'first_name':first_name} + + from_email = 'Rowsandall ' + + text_content = plaintext.render(d) + html_content = htmly.render(d) + + msg = EmailMultiAlternatives(subject, text_content, from_email, [fullemail]) + msg.attach_alternative(html_content, "text/html") if os.path.isfile(csvfile): - email.attach_file(csvfile) + msg.attach_file(csvfile) else: csvfile2 = csvfile with gzip.open(csvfile + '.gz', 'rb') as f_in, open(csvfile2, 'wb') as f_out: shutil.copyfileobj(f_in, f_out) - email.attach_file(csvfile2) + msg.attach_file(csvfile2) os.remove(csvfile2) @@ -652,7 +663,7 @@ def handle_sendemailcsv(first_name, last_name, email, csvfile,**kwargs): emailbounced = False if not emailbounced: - res = email.send() + res = msg.send() return 1 diff --git a/rowers/templates/csvemail.html b/rowers/templates/csvemail.html new file mode 100644 index 00000000..95d44006 --- /dev/null +++ b/rowers/templates/csvemail.html @@ -0,0 +1,14 @@ + + + +

Dear {{ first_name }},

+ +

+ Please find attached the requested file for your workout. +

+ +

+ Best Regards, the Rowsandall Team +

+ + diff --git a/rowers/templates/csvemail.txt b/rowers/templates/csvemail.txt new file mode 100644 index 00000000..33071ef7 --- /dev/null +++ b/rowers/templates/csvemail.txt @@ -0,0 +1,5 @@ +Dear {{ first_name }}, + +Please find attached the requested file for your workout. + +Best Regards, the Rowsandall Team diff --git a/rowers/utils.py b/rowers/utils.py index e1588ffe..fa159aba 100644 --- a/rowers/utils.py +++ b/rowers/utils.py @@ -7,6 +7,7 @@ from django.conf import settings import uuid import datetime + lbstoN = 4.44822 landingpages = ( From 073533f1a924d7bcc5f1c9821e7a3e3f449a4dc1 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 19 Mar 2018 10:23:39 +0100 Subject: [PATCH 2/9] fixed nan values in updatefitnessmetric --- rowers/dataprepnodjango.py | 16 +++++++--------- rowers/views.py | 3 ++- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/rowers/dataprepnodjango.py b/rowers/dataprepnodjango.py index e9e3cd10..49a3e6dc 100644 --- a/rowers/dataprepnodjango.py +++ b/rowers/dataprepnodjango.py @@ -677,14 +677,11 @@ def getsmallrowdata_db(columns,ids=[],debug=False): def fitnessmetric_to_sql(m,table='powertimefitnessmetric',debug=False, doclean=False): # test if nan among values - if np.nan in m.values() or np.inf in m.values(): - for key in m.keys(): - if np.isnan([m[key]]): - m[key] = -1 - if m[key] == np.inf: - m[key] = -1 - if -m[key] == np.inf: - m[key] = -1 + for key in m.keys(): + if str(m[key]) == 'nan': + m[key] = -1 + if 'inf' in str(m[key]): + m[key] = -1 if debug: engine = create_engine(database_url_debug, echo=False) @@ -702,9 +699,10 @@ def fitnessmetric_to_sql(m,table='powertimefitnessmetric',debug=False, values = tuple(m[key] for key in m.keys()) with engine.connect() as conn, conn.begin(): - result = conn.execute(query,values) if doclean: result2 = conn.execute(query2) + result = conn.execute(query,values) + conn.close() engine.dispose() diff --git a/rowers/views.py b/rowers/views.py index fb69cd79..9a5588a5 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -13031,7 +13031,8 @@ def plannedsession_view(request,id=0,rowerid=0, { 'psdict': psdict, 'attrs':[ - 'name','startdate','enddate','sessiontype', + 'name','startdate','enddate','preferreddate', + 'sessiontype', 'sessionmode','criterium', 'sessionvalue','sessionunit','comment', ], From 5afb2477cf16b6a442ed15cc6d62033a0b649850 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 19 Mar 2018 12:44:41 +0100 Subject: [PATCH 3/9] cleaning up email templates --- rowers/tasks.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/rowers/tasks.py b/rowers/tasks.py index 98e3c3d5..3f5be55a 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -5,7 +5,7 @@ import gc import gzip import shutil import numpy as np - +import re from scipy import optimize @@ -30,6 +30,13 @@ import pandas as pd from django_rq import job from django.utils import timezone +from django.utils.html import strip_tags + +def textify(html): + # Remove html tags and continuous whitespaces + text_only = re.sub('[ \t]+', ' ', strip_tags(html)) + # Strip single spaces in the beginning of each line + return text_only.replace('\n ', '\n').strip() from utils import deserialize_list @@ -640,9 +647,9 @@ def handle_sendemailcsv(first_name, last_name, email, csvfile,**kwargs): from_email = 'Rowsandall ' - text_content = plaintext.render(d) html_content = htmly.render(d) - + text_content = textify(html_content) + msg = EmailMultiAlternatives(subject, text_content, from_email, [fullemail]) msg.attach_alternative(html_content, "text/html") From b744eff7f692a58a1c209749e2fbff39ee0b443c Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 19 Mar 2018 14:47:40 +0100 Subject: [PATCH 4/9] added breakthrough notification --- rowers/tasks.py | 66 ++++++++++------------- rowers/templates/breakthroughemail.html | 70 +++++++++++++++++++++++++ rowers/templates/csvemail.html | 2 +- 3 files changed, 98 insertions(+), 40 deletions(-) create mode 100644 rowers/templates/breakthroughemail.html diff --git a/rowers/tasks.py b/rowers/tasks.py index 3f5be55a..2349eade 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -311,55 +311,43 @@ def handle_sendemail_breakthrough(workoutid, useremail, btvalues=pd.DataFrame().to_json(), **kwargs): + if 'debug' in kwargs: + debug = kwargs['debug'] + else: + debug = False + siteurl = SITE_URL if debug: siteurl = SITE_URL_DEV - # send email with attachment - subject = "A breakthrough workout on rowsandall.com" - message = "Dear " + userfirstname + ",\n" - message += "Congratulations! Your recent workout has been analyzed" - message += " by Rowsandall.com and it appears your fitness," - message += " as measured by Critical Power, has improved!" - message += " Critical Power (CP) is the power that you can " - message += "sustain for a given duration. For more, see this " - message += " article in the analytics blog:\n\n" - message += " http://analytics.rowsandall.com/2017/06/17/how-do-we-calculate-critical-power/ \n\n" - message += "Link to the workout "+siteurl+"/rowers/workout/" - message += str(workoutid) - message += "/edit\n\n" - message += "To add the workout to your Ranking workouts and see the updated CP plot, click the following link:\n" - message += siteurl+"/rowers/workout/" - message += str(workoutid) - message += "/updatecp\n\n" - btvalues = pd.read_json(btvalues) btvalues.sort_values('delta', axis=0, inplace=True) - if not btvalues.empty: - message += "These were the breakthrough values:\n" - for t in btvalues.itertuples(): - delta = t.delta - cpvalue = t.cpvalues - pwr = t.pwr + tablevalues = [ + {'delta': t.delta, + 'cpvalue': t.cpvalues, + 'pwr': t.pwr + } for t in btvalues.itertuples() + ] - message += "Time: {delta} seconds\n".format( - delta=delta - ) - message += "New: {cpvalue:.0f} Watt\n".format( - cpvalue=cpvalue - ) - message += "Old: {pwr:.0f} Watt\n\n".format( - pwr=pwr - ) + # send email with attachment + subject = "A breakthrough workout on rowsandall.com" + from_email = 'Rowsandall ' - message += "To opt out of these email notifications, deselect the checkbox on your Profile page under Account Information.\n\n" + htmly = get_template('breakthroughemail.html') - message += "Best Regards, the Rowsandall Team" + d = { + 'first_name':userfirstname, + 'siteurl':siteurl, + 'workoutid':workoutid, + 'btvalues':tablevalues, + } - email = EmailMessage(subject, message, - 'Rowsandall ', - [useremail]) + html_content = htmly.render(d) + text_content = textify(html_content) + + msg = EmailMultiAlternatives(subject, text_content, from_email, [useremail]) + msg.attach_alternative(html_content, "text/html") if 'emailbounced' in kwargs: emailbounced = kwargs['emailbounced'] @@ -367,7 +355,7 @@ def handle_sendemail_breakthrough(workoutid, useremail, emailbounced = False if not emailbounced: - res = email.send() + res = msg.send() diff --git a/rowers/templates/breakthroughemail.html b/rowers/templates/breakthroughemail.html new file mode 100644 index 00000000..0c59145c --- /dev/null +++ b/rowers/templates/breakthroughemail.html @@ -0,0 +1,70 @@ + + +{% load staticfiles %} +{% load rowerfilters %} + + + +

Dear {{ first_name }},

+ +

+ Congratulations! Your recent workout has been analyzed + by Rowsandall.com and it appears your fitness, + as measured by Critical Power, has improved! + Critical Power (CP) is the power that you can + sustain for a given duration. For more, see this + article in the analytics blog: +

+ +

+ + http://analytics.rowsandall.com/2017/06/17/how-do-we-calculate-critical-power/ +

+ +

+ Link to the workout: + {{ siteurl }}/rowers/workout/{{ workoutid }} +

+ +

+ To add the workout to your Ranking workouts and see the updated CP plot, + click the following link: +

+ +

+ + {{ siteurl }}/rowers/workout/{{ workoutid }}/updatecp +

+ +{% if btvalues %} +

+ These were the breakthrough values: +

+ +

+ + + + + {% for set in btvalues %} + + + + + + {% endfor %} +
Time (sec)New Power (W)Old Power
{{ set|lookup:"delta" }}{{ set|lookup:"cpvalue" }}{{ set|lookup:"pwr" }}
+

+{% endif %} + + +

+ To opt out of these email notifications, deselect the checkbox on your Profile + page under Account Information. +

+ +

+ Best Regards, the Rowsandall Team +

+ + diff --git a/rowers/templates/csvemail.html b/rowers/templates/csvemail.html index 95d44006..89b9b267 100644 --- a/rowers/templates/csvemail.html +++ b/rowers/templates/csvemail.html @@ -1,6 +1,6 @@ - +

Dear {{ first_name }},

From e7e2ced5f516af7a68fe8fa4a124f64cb6ed8295 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 19 Mar 2018 15:49:57 +0100 Subject: [PATCH 5/9] a few new email templates --- rowers/tasks.py | 158 +++++++++++++----------- rowers/templates/breakthroughemail.html | 10 +- rowers/templates/csvemail.html | 11 +- rowers/templates/csvemail.txt | 5 - rowers/templates/emailbase.html | 16 +++ rowers/templates/gpxemail.html | 15 +++ rowers/templates/hardemail.html | 36 ++++++ rowers/templates/otwpoweremail.html | 35 ++++++ rowers/templates/summarymail.html | 15 +++ rowers/templates/tcxemail.html | 15 +++ rowers/templates/unrecognizedemail.html | 26 ++++ 11 files changed, 254 insertions(+), 88 deletions(-) delete mode 100644 rowers/templates/csvemail.txt create mode 100644 rowers/templates/emailbase.html create mode 100644 rowers/templates/gpxemail.html create mode 100644 rowers/templates/hardemail.html create mode 100644 rowers/templates/otwpoweremail.html create mode 100644 rowers/templates/summarymail.html create mode 100644 rowers/templates/tcxemail.html create mode 100644 rowers/templates/unrecognizedemail.html diff --git a/rowers/tasks.py b/rowers/tasks.py index 2349eade..6b0d06a9 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -371,31 +371,34 @@ def handle_sendemail_hard(workoutid, useremail, btvalues=pd.DataFrame().to_json(), debug=False,**kwargs): + if 'debug' in kwargs: + debug = kwargs['debug'] + else: + debug = False + siteurl = SITE_URL if debug: siteurl = SITE_URL_DEV # send email with attachment subject = "That was a pretty hard workout on rowsandall.com" - message = "Dear " + userfirstname + ",\n" - message += "Congratulations! Your recent workout has been analyzed" - message += " by Rowsandall.com and it appears that it was pretty hard work." - message += " You were working pretty close to your Critical Power\n\n" - message += " Critical Power (CP) is the power that you can " - message += "sustain for a given duration. For more, see this " - message += " article in the analytics blog:\n\n" - message += " http://analytics.rowsandall.com/2017/06/17/how-do-we-calculate-critical-power/ \n\n" - message += "Link to the workout: "+siteurl+"/rowers/workout/" - message += str(workoutid) - message += "/edit\n\n" + from_email = 'Rowsandall ' - message += "To opt out of these email notifications, deselect the checkbox on your Profile page under Account Information.\n\n" + htmly = get_template('hardemail.html') - message += "Best Regards, the Rowsandall Team" + d = { + 'first_name':userfirstname, + 'siteurl':siteurl, + 'workoutid':workoutid, + 'btvalues':tablevalues, + } + + html_content = htmly.render(d) + text_content = textify(html_content) + + msg = EmailMultiAlternatives(subject, text_content, from_email, [useremail]) + msg.attach_alternative(html_content, "text/html") - email = EmailMessage(subject, message, - 'Rowsandall ', - [useremail]) if 'emailbounced' in kwargs: emailbounced = kwargs['emailbounced'] @@ -403,7 +406,7 @@ def handle_sendemail_hard(workoutid, useremail, emailbounced = False if not emailbounced: - res = email.send() + res = msg.send() @@ -484,24 +487,19 @@ def handle_sendemail_unrecognizedowner(useremail, userfirstname, # send email with attachment fullemail = useremail subject = "Unrecognized file from Rowsandall.com" - message = "Dear " + userfirstname + ",\n\n" - message += """ - The file you tried to send to rowsandall.com was not recognized by - our email processing system. You may have sent a file in a format - that is not supported. Sometimes, rowing apps make file format changes. - When that happens, it takes some time for rowsandall.comm to make - the necessary changes on our side and support the app again. - The file has been sent to the developer at rowsandall.com for evaluation. + plaintext = get_template('csvemail.txt') + htmly = get_template('csvemail.html') + d = {'first_name':first_name} - """ + from_email = 'Rowsandall ' - message += "Best Regards, the Rowsandall Team" + html_content = htmly.render(d) + text_content = textify(html_content) - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) + msg = EmailMultiAlternatives(subject, text_content, from_email, [fullemail]) + msg.attach_alternative(html_content, "text/html") if 'emailbounced' in kwargs: emailbounced = kwargs['emailbounced'] @@ -509,7 +507,7 @@ def handle_sendemail_unrecognizedowner(useremail, userfirstname, emailbounced = False if not emailbounced: - res = email.send() + res = msg.send() return 1 @@ -522,15 +520,20 @@ def handle_sendemailtcx(first_name, last_name, email, tcxfile,**kwargs): # send email with attachment fullemail = first_name + " " + last_name + " " + "<" + email + ">" subject = "File from Rowsandall.com" - message = "Dear " + first_name + ",\n\n" - message += "Please find attached the requested file for your workout.\n\n" - message += "Best Regards, the Rowsandall Team" - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) + htmly = get_template('tcxemail.html') - email.attach_file(tcxfile) + d = {'first_name':first_name} + + from_email = 'Rowsandall ' + + html_content = htmly.render(d) + text_content = textify(html_content) + + msg = EmailMultiAlternatives(subject, text_content, from_email, [fullemail]) + msg.attach_alternative(html_content, "text/html") + + msg.attach_file(tcxfile) if 'emailbounced' in kwargs: emailbounced = kwargs['emailbounced'] @@ -538,7 +541,7 @@ def handle_sendemailtcx(first_name, last_name, email, tcxfile,**kwargs): emailbounced = False if not emailbounced: - res = email.send() + res = msg.send() # remove tcx file @@ -564,13 +567,8 @@ def handle_zip_file(emailfrom, subject, file,**kwargs): if debug: print "attaching" - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False - if not emailbounced: - res = email.send() + res = email.send() if debug: @@ -582,25 +580,30 @@ def handle_zip_file(emailfrom, subject, file,**kwargs): @app.task def handle_sendemailsummary(first_name, last_name, email, csvfile, **kwargs): - # send email with attachment fullemail = first_name + " " + last_name + " " + "<" + email + ">" subject = "File from Rowsandall.com" - message = "Dear " + first_name + ",\n\n" - message += "Please find attached the requested summary file.\n\n" - message += "Best Regards, the Rowsandall Team" - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) + htmly = get_template('summarymail.html') + + d = {'first_name':first_name} + + from_email = 'Rowsandall ' + + html_content = htmly.render(d) + text_content = textify(html_content) + + msg = EmailMultiAlternatives(subject, text_content, from_email, [fullemail]) + msg.attach_alternative(html_content, "text/html") + if os.path.isfile(csvfile): - email.attach_file(csvfile) + msg.attach_file(csvfile) else: csvfile2 = csvfile with gzip.open(csvfile + '.gz', 'rb') as f_in, open(csvfile2, 'wb') as f_out: shutil.copyfileobj(f_in, f_out) - email.attach_file(csvfile2) + msg.attach_file(csvfile2) os.remove(csvfile2) if 'emailbounced' in kwargs: @@ -609,7 +612,7 @@ def handle_sendemailsummary(first_name, last_name, email, csvfile, **kwargs): emailbounced = False if not emailbounced: - res = email.send() + res = msg.send() try: os.remove(csvfile) @@ -781,24 +784,35 @@ def handle_otwsetpower(self,f1, boattype, weightvalue, first_name, last_name, btvalues=btvalues.to_json()) - # send email - fullemail = first_name + " " + last_name + " " + "<" + email + ">" - subject = "Your Rowsandall OTW calculations are ready" - message = "Dear " + first_name + ",\n\n" - message += "Your Rowsandall OTW calculations are ready.\n" - message += "Thank you for using rowsandall.com.\n\n" - message += "Rowsandall OTW calculations have not been fully implemented yet.\n" - message += "We are now running an experimental version for debugging purposes. \n" - message += "Your wind/stream corrected plot is available here: " - message += siteurl+"/rowers/workout/" - message += str(workoutid) - message += "/interactiveotwplot\n\n" - message += "Please report any bugs/inconsistencies/unexpected results at rowsandall.slack.com or by reply to this email.\n\n" - message += "Best Regards, The Rowsandall Physics Department." - send_mail(subject, message, - 'Rowsandall Physics Department ', - [fullemail]) + subject = "Your OTW Physics Calculations are ready" + from_email = 'Rowsandall ' + fullemail = first_name + " " + last_name + " " + "<" + email + ">" + + htmly = get_template('otwpoweremail.html') + + d = { + 'first_name':first_name, + 'siteurl':siteurl, + 'workoutid':workoutid, + } + + html_content = htmly.render(d) + text_content = textify(html_content) + + msg = EmailMultiAlternatives(subject, text_content, from_email, [fullemail]) + msg.attach_alternative(html_content, "text/html") + + + if 'emailbounced' in kwargs: + emailbounced = kwargs['emailbounced'] + else: + emailbounced = False + + if not emailbounced: + res = msg.send() + + return 1 diff --git a/rowers/templates/breakthroughemail.html b/rowers/templates/breakthroughemail.html index 0c59145c..bd1107ab 100644 --- a/rowers/templates/breakthroughemail.html +++ b/rowers/templates/breakthroughemail.html @@ -1,10 +1,8 @@ - - +{% extends "emailbase.html" %} {% load staticfiles %} {% load rowerfilters %} - - +{% block body %}

Dear {{ first_name }},

@@ -66,5 +64,5 @@

Best Regards, the Rowsandall Team

- - +{% endblock %} + diff --git a/rowers/templates/csvemail.html b/rowers/templates/csvemail.html index 89b9b267..edb5ec7e 100644 --- a/rowers/templates/csvemail.html +++ b/rowers/templates/csvemail.html @@ -1,6 +1,8 @@ - - - +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %}

Dear {{ first_name }},

@@ -10,5 +12,4 @@

Best Regards, the Rowsandall Team

- - +{% endblock %} diff --git a/rowers/templates/csvemail.txt b/rowers/templates/csvemail.txt deleted file mode 100644 index 33071ef7..00000000 --- a/rowers/templates/csvemail.txt +++ /dev/null @@ -1,5 +0,0 @@ -Dear {{ first_name }}, - -Please find attached the requested file for your workout. - -Best Regards, the Rowsandall Team diff --git a/rowers/templates/emailbase.html b/rowers/templates/emailbase.html new file mode 100644 index 00000000..58c339eb --- /dev/null +++ b/rowers/templates/emailbase.html @@ -0,0 +1,16 @@ + + + +{% load staticfiles %} +{% load rowerfilters %} + + + + + {% block body %} + + {% endblock %} + + + + diff --git a/rowers/templates/gpxemail.html b/rowers/templates/gpxemail.html new file mode 100644 index 00000000..edb5ec7e --- /dev/null +++ b/rowers/templates/gpxemail.html @@ -0,0 +1,15 @@ +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %} +

Dear {{ first_name }},

+ +

+ Please find attached the requested file for your workout. +

+ +

+ Best Regards, the Rowsandall Team +

+{% endblock %} diff --git a/rowers/templates/hardemail.html b/rowers/templates/hardemail.html new file mode 100644 index 00000000..0ca5cf10 --- /dev/null +++ b/rowers/templates/hardemail.html @@ -0,0 +1,36 @@ +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %} +

Dear {{ first_name }},

+ +

+ Congratulations! Your recent workout has been analyzed + by Rowsandall.com and it appears it was pretty hard work. + You were working pretty close to your Critical Power. + Critical Power (CP) is the power that you can + sustain for a given duration. For more, see this + article in the analytics blog: +

+ +

+ + http://analytics.rowsandall.com/2017/06/17/how-do-we-calculate-critical-power/ +

+ +

+ Link to the workout: + {{ siteurl }}/rowers/workout/{{ workoutid }} +

+ + +

+ To opt out of these email notifications, deselect the checkbox on your Profile + page under Account Information. +

+ +

+ Best Regards, the Rowsandall Team +

+{% endblock %} diff --git a/rowers/templates/otwpoweremail.html b/rowers/templates/otwpoweremail.html new file mode 100644 index 00000000..8b90a830 --- /dev/null +++ b/rowers/templates/otwpoweremail.html @@ -0,0 +1,35 @@ +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %} +

Dear {{ first_name }},

+ +

+ Your Rowsandall OTW calculations are ready. +

+

+ Thank you for using rowsandall.com. +

+

+ Rowsandall OTW calculations have not been fully implemented yet. +

+

+ We are now running an experimental version for debugging purposes. +

+

+ Your wind/stream corrected plot is available here: + + {{ siteurl }}/rowers/workout/{{ workoutid }}/interactiveotwplot +

+

+ Please report any bugs/inconsistencies/unexpected results + by reply to this email. +

+ + + +

+ Best Regards, the Rowsandall Physics Department +

+{% endblock %} diff --git a/rowers/templates/summarymail.html b/rowers/templates/summarymail.html new file mode 100644 index 00000000..918f8443 --- /dev/null +++ b/rowers/templates/summarymail.html @@ -0,0 +1,15 @@ +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %} +

Dear {{ first_name }},

+ +

+ Please find attached the requested summary file. +

+ +

+ Best Regards, the Rowsandall Team +

+{% endblock %} diff --git a/rowers/templates/tcxemail.html b/rowers/templates/tcxemail.html new file mode 100644 index 00000000..edb5ec7e --- /dev/null +++ b/rowers/templates/tcxemail.html @@ -0,0 +1,15 @@ +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %} +

Dear {{ first_name }},

+ +

+ Please find attached the requested file for your workout. +

+ +

+ Best Regards, the Rowsandall Team +

+{% endblock %} diff --git a/rowers/templates/unrecognizedemail.html b/rowers/templates/unrecognizedemail.html new file mode 100644 index 00000000..bc6706ab --- /dev/null +++ b/rowers/templates/unrecognizedemail.html @@ -0,0 +1,26 @@ +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %} +

Dear {{ first_name }},

+ +

+ The file you tried to send to rowsandall.com was not recognized by + our email processing system. You may have sent a file in a format + that is not supported. Sometimes, rowing apps make file format changes. + When that happens, it takes some time for rowsandall.comm to make + the necessary changes on our side and support the app again. +

+ +

+ The file has been sent to the developer at rowsandall.com for evaluation. +

+ + + + +

+ Best Regards, the Rowsandall Team +

+{% endblock %} From 0dadcf32a62ffc00cc98dde6c82f0efd51e48315 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 19 Mar 2018 17:48:47 +0100 Subject: [PATCH 6/9] a few more templates --- rowers/tasks.py | 90 ++++++++++++------------- rowers/templates/teaminviteemail.html | 58 ++++++++++++++++ rowers/templates/teamresponseemail.html | 26 +++++++ 3 files changed, 128 insertions(+), 46 deletions(-) create mode 100644 rowers/templates/teaminviteemail.html create mode 100644 rowers/templates/teamresponseemail.html diff --git a/rowers/tasks.py b/rowers/tasks.py index 6b0d06a9..6e882bcd 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -631,7 +631,6 @@ def handle_sendemailcsv(first_name, last_name, email, csvfile,**kwargs): fullemail = first_name + " " + last_name + " " + "<" + email + ">" subject = "File from Rowsandall.com" - plaintext = get_template('csvemail.txt') htmly = get_template('csvemail.html') d = {'first_name':first_name} @@ -1035,34 +1034,25 @@ def handle_sendemail_invite(email, name, code, teamname, manager, debug=False,**kwargs): fullemail = name + ' <' + email + '>' subject = 'Invitation to join team ' + teamname - message = 'Dear ' + name + ',\n\n' - message += manager + ' is inviting you to join his team ' + teamname - message += ' on rowsandall.com\n\n' - message += 'By accepting the invite, you will have access to your' - message += " team's workouts on rowsandall.com and your workouts will " - message += " be visible to " - message += "the members of the team.\n\n" - message += "By accepting the invite, you are agreeing with the sharing " - message += "of personal data according to our privacy policy.\n\n" - message += 'If you already have an account on rowsandall.com, you can login to the site and you will find the invitation here on the Teams page:\n' - message += ' https://rowsandall.com/rowers/me/teams \n\n' - message += 'You can also click the direct link: \n' - message += 'https://rowsandall.com/rowers/me/invitation/' + code + ' \n\n' - message += 'If you are not yet registered to rowsandall.com, ' - message += 'you can register for free at https://rowsandall.com/rowers/register\n' - message += 'After you set up your account, you can use the direct link: ' - message += 'https://rowsandall.com/rowers/me/invitation/' + code + ' \n\n' - message += 'You can also manually accept your team membership with the code.\n' - message += 'You will need to do this if you registered under a different email address than this one.\n' - message += 'Code: ' + code + '\n' - message += 'Link to manually accept your team membership: ' - message += 'https://rowsandall.com/rowers/me/invitation\n\n' - message += "Best Regards, the Rowsandall Team" + siteurl = SITE_URL + if debug: + siteurl = SITE_URL_DEV - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) + htmly = get_template('teaminviteemail.html') + + d = { + 'name':name, + 'manage':manager, + 'code':code, + 'teamname':teamname, + } + + html_content = htmly.render(d) + text_content = textify(html_content) + + msg = EmailMultiAlternatives(subject, text_content, from_email, [fullemail]) + msg.attach_alternative(html_content, "text/html") if 'emailbounced' in kwargs: emailbounced = kwargs['emailbounced'] @@ -1070,7 +1060,7 @@ def handle_sendemail_invite(email, name, code, teamname, manager, emailbounced = False if not emailbounced: - res = email.send() + res = msg.send() return 1 @@ -1085,25 +1075,33 @@ def handle_sendemailnewresponse(first_name, last_name, workoutname, workoutid, commentid, debug=False,**kwargs): fullemail = first_name + ' ' + last_name + ' <' + email + '>' + from_email = 'Rowsandall ' subject = 'New comment on workout ' + workoutname - message = 'Dear ' + first_name + ',\n\n' - message += commenter_first_name + ' ' + commenter_last_name - message += ' has written a new comment on the workout ' - message += workoutname + '\n\n' - message += comment - message += '\n\n' - message += 'You can read the comment here:\n' - message += 'https://rowsandall.com/rowers/workout/' + \ - str(workoutid) + '/comment' - message += '\n\n' - message += 'You are receiving this email because you are subscribed ' - message += 'to comments on this workout. To unsubscribe, follow this link:\n' - message += 'https://rowsandall.com/rowers/workout/' + \ - str(workoutid) + '/unsubscribe' - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) + siteurl = SITE_URL + if debug: + siteurl = SITE_URL_DEV + + + htmly = get_template('teamresponseemail.html') + + d = { + 'first_name':first_name, + 'commenter_first_name':commenter_first_name, + 'commenter_last_name':commenter_last_name, + 'comment':comment, + 'workoutname':workoutname, + 'siteurl':siteurl, + 'workoutid':workoutid, + 'commentid':commentid + } + + html_content = htmly.render(d) + text_content = textify(html_content) + + msg = EmailMultiAlternatives(subject, text_content, from_email, [fullemail]) + msg.attach_alternative(html_content, "text/html") + if 'emailbounced' in kwargs: emailbounced = kwargs['emailbounced'] @@ -1111,7 +1109,7 @@ def handle_sendemailnewresponse(first_name, last_name, emailbounced = False if not emailbounced: - res = email.send() + res = msg.send() return 1 diff --git a/rowers/templates/teaminviteemail.html b/rowers/templates/teaminviteemail.html new file mode 100644 index 00000000..f0895252 --- /dev/null +++ b/rowers/templates/teaminviteemail.html @@ -0,0 +1,58 @@ +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %} +

Dear {{ name }},

+ +

+ {{ manager }} is inviting you to join his team {{ teamname }} + on rowsandall.com +

+

+ By accepting the invite, you will have access to your + team's workouts on rowsandall.com and your workouts will + be visible to + the members of the team. +

+

+ By accepting the invite, you are agreeing with the sharing + of personal data according to our privacy policy. +

+

+ If you already have an account on rowsandall.com, you can login to the + site and you will find the invitation here on the Teams page: + {{ siteurl }}/rowers/me/teams +

+

+ You can also click the direct link: + + {{ siteurl }}/rowers/me/invitation/{{ code }} +

+

+ If you are not yet registered to rowsandall.com, + you can register for free at + {{ siteurl }}/rowers/register +

+

+ After you set up your account, you can use the direct link: + + {{ siteurl }}/rowers/me/invitation/{{ code }} +

+

+ You can also manually accept your team membership with the code. + You will need to do this if you registered under a different email address than this one. +

+

+ Code: {{ code }} +

+

+ Link to manually accept your team membership: + + {{ siteurl }}/rowers/me/invitation +

+ +

+ Best Regards, the Rowsandall Team +

+{% endblock %} diff --git a/rowers/templates/teamresponseemail.html b/rowers/templates/teamresponseemail.html new file mode 100644 index 00000000..3bb04e19 --- /dev/null +++ b/rowers/templates/teamresponseemail.html @@ -0,0 +1,26 @@ +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %} +

Dear {{ name }},

+ +

+ {{ commenter_first_name }} {{ commenter_last_name }} has written + a new comment on your workout {{ workoutname }} +

+

+ {{ comment }} +

+

+ You can read the comment here: +

+

+ + {{ siteurl }}/rowers/workout/{{ workoutid }}/comment +

+ +

+ Best Regards, the Rowsandall Team +

+{% endblock %} From ffed5c694b09905b64b1822a4a6c68a882207e55 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 19 Mar 2018 18:05:30 +0100 Subject: [PATCH 7/9] bug fix in email templates --- rowers/tasks.py | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/rowers/tasks.py b/rowers/tasks.py index 6e882bcd..b3fed727 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -38,6 +38,29 @@ def textify(html): # Strip single spaces in the beginning of each line return text_only.replace('\n ', '\n').strip() +def send_template_email(from_email,to_email,subject,template,context,*args,**kwargs): + + htmly = get_template(template) + + html_content = htmly.render(context) + text_content = textify(html_content) + + msg = EmailMultiAlternatives(subject, text_content, from_email, to_email) + msg.attach_alternative(html_content, "text/html") + + + if 'emailbounced' in kwargs: + emailbounced = kwargs['emailbounced'] + else: + emailbounced = False + + if not emailbounced: + res = msg.send() + else: + return 0 + + return res + from utils import deserialize_list from rowers.dataprepnodjango import ( @@ -1096,21 +1119,7 @@ def handle_sendemailnewresponse(first_name, last_name, 'commentid':commentid } - html_content = htmly.render(d) - text_content = textify(html_content) - - msg = EmailMultiAlternatives(subject, text_content, from_email, [fullemail]) - msg.attach_alternative(html_content, "text/html") - - - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False - - if not emailbounced: - res = msg.send() - + res = send_template_email(from_email,[fullemail],subject,'teamresponseemail.html',d,**kwargs) return 1 From ea30428f6ea4186f0db88e77ea37428f4b86df0f Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 19 Mar 2018 21:08:45 +0100 Subject: [PATCH 8/9] a few more templates --- rowers/tasks.py | 511 ++++++++------------ rowers/teams.py | 1 + rowers/templates/teamdropemail.html | 16 + rowers/templates/teaminviteacceptemail.html | 16 + rowers/templates/teaminviterejectemail.html | 17 + rowers/templates/teamrejectemail.html | 16 + rowers/templates/teamremoveemail.html | 19 + rowers/templates/teamrequestemail.html | 29 ++ rowers/templates/teamresponseemail.html | 2 +- rowers/templates/teamwelcomeemail.html | 15 + temp.txt | 5 - 11 files changed, 321 insertions(+), 326 deletions(-) create mode 100644 rowers/templates/teamdropemail.html create mode 100644 rowers/templates/teaminviteacceptemail.html create mode 100644 rowers/templates/teaminviterejectemail.html create mode 100644 rowers/templates/teamrejectemail.html create mode 100644 rowers/templates/teamremoveemail.html create mode 100644 rowers/templates/teamrequestemail.html create mode 100644 rowers/templates/teamwelcomeemail.html delete mode 100644 temp.txt diff --git a/rowers/tasks.py b/rowers/tasks.py index b3fed727..d802a565 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -32,35 +32,6 @@ from django_rq import job from django.utils import timezone from django.utils.html import strip_tags -def textify(html): - # Remove html tags and continuous whitespaces - text_only = re.sub('[ \t]+', ' ', strip_tags(html)) - # Strip single spaces in the beginning of each line - return text_only.replace('\n ', '\n').strip() - -def send_template_email(from_email,to_email,subject,template,context,*args,**kwargs): - - htmly = get_template(template) - - html_content = htmly.render(context) - text_content = textify(html_content) - - msg = EmailMultiAlternatives(subject, text_content, from_email, to_email) - msg.attach_alternative(html_content, "text/html") - - - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False - - if not emailbounced: - res = msg.send() - else: - return 0 - - return res - from utils import deserialize_list from rowers.dataprepnodjango import ( @@ -90,6 +61,51 @@ import arrow from django.contrib.staticfiles import finders +def textify(html): + # Remove html tags and continuous whitespaces + text_only = re.sub('[ \t]+', ' ', strip_tags(html)) + # Strip single spaces in the beginning of each line + return text_only.replace('\n ', '\n').strip() + +def send_template_email(from_email,to_email,subject, + template,context, + *args,**kwargs): + + htmly = get_template(template) + + html_content = htmly.render(context) + text_content = textify(html_content) + + msg = EmailMultiAlternatives(subject, text_content, from_email, to_email) + msg.attach_alternative(html_content, "text/html") + + if 'attach_file' in kwargs: + fileobj = kwargs['attach_file'] + if os.path.isfile(fileobj): + msg.attach_file(fileobj) + else: + try: + fileobj2 = fileobj + with gzip.open(fileobj+'.gz','rb') as f_in, open(fileobj2,'wb') as f_out: + shutil.copyfileobj(f_in,f_out) + msg.attach_file(fileobj2) + os.remove(fileobj2) + except IOError: + pass + + if 'emailbounced' in kwargs: + emailbounced = kwargs['emailbounced'] + else: + emailbounced = False + + if not emailbounced: + res = msg.send() + else: + return 0 + + return res + + @app.task def add(x, y): return x + y @@ -357,8 +373,6 @@ def handle_sendemail_breakthrough(workoutid, useremail, subject = "A breakthrough workout on rowsandall.com" from_email = 'Rowsandall ' - htmly = get_template('breakthroughemail.html') - d = { 'first_name':userfirstname, 'siteurl':siteurl, @@ -366,23 +380,13 @@ def handle_sendemail_breakthrough(workoutid, useremail, 'btvalues':tablevalues, } - html_content = htmly.render(d) - text_content = textify(html_content) - - msg = EmailMultiAlternatives(subject, text_content, from_email, [useremail]) - msg.attach_alternative(html_content, "text/html") - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False - if not emailbounced: - res = msg.send() + res = send_template_email(from_email,[useremail], + subject,'breakthroughemail.html', + d,**kwargs) - - # remove tcx file return 1 # send email when a breakthrough workout is uploaded @@ -403,12 +407,20 @@ def handle_sendemail_hard(workoutid, useremail, if debug: siteurl = SITE_URL_DEV + btvalues = pd.read_json(btvalues) + btvalues.sort_values('delta', axis=0, inplace=True) + + tablevalues = [ + {'delta': t.delta, + 'cpvalue': t.cpvalues, + 'pwr': t.pwr + } for t in btvalues.itertuples() + ] + # send email with attachment subject = "That was a pretty hard workout on rowsandall.com" from_email = 'Rowsandall ' - htmly = get_template('hardemail.html') - d = { 'first_name':userfirstname, 'siteurl':siteurl, @@ -416,24 +428,10 @@ def handle_sendemail_hard(workoutid, useremail, 'btvalues':tablevalues, } - html_content = htmly.render(d) - text_content = textify(html_content) - - msg = EmailMultiAlternatives(subject, text_content, from_email, [useremail]) - msg.attach_alternative(html_content, "text/html") + res = send_template_email(from_email,[useremail], + subject,'hardemail.html',d,**kwargs) - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False - - if not emailbounced: - res = msg.send() - - - - # remove tcx file return 1 @@ -511,27 +509,15 @@ def handle_sendemail_unrecognizedowner(useremail, userfirstname, fullemail = useremail subject = "Unrecognized file from Rowsandall.com" - plaintext = get_template('csvemail.txt') - htmly = get_template('csvemail.html') + htmly = get_template('unrecognizedemail.html') - d = {'first_name':first_name} + d = {'first_name':userfirstname} from_email = 'Rowsandall ' - html_content = htmly.render(d) - text_content = textify(html_content) - - msg = EmailMultiAlternatives(subject, text_content, from_email, [fullemail]) - msg.attach_alternative(html_content, "text/html") - - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False - - if not emailbounced: - res = msg.send() - + res = send_template_email(from_email,[fullemail], + subject,'csvemail.html',d, + **kwargs) return 1 @@ -550,24 +536,11 @@ def handle_sendemailtcx(first_name, last_name, email, tcxfile,**kwargs): from_email = 'Rowsandall ' - html_content = htmly.render(d) - text_content = textify(html_content) - msg = EmailMultiAlternatives(subject, text_content, from_email, [fullemail]) - msg.attach_alternative(html_content, "text/html") + res = send_template_email(from_email,[fullemail], + subject,'tcxemail.html',d, + attach_file=tcxfile,**kwargs) - msg.attach_file(tcxfile) - - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False - - if not emailbounced: - res = msg.send() - - - # remove tcx file os.remove(tcxfile) return 1 @@ -612,31 +585,11 @@ def handle_sendemailsummary(first_name, last_name, email, csvfile, **kwargs): from_email = 'Rowsandall ' - html_content = htmly.render(d) - text_content = textify(html_content) - - msg = EmailMultiAlternatives(subject, text_content, from_email, [fullemail]) - msg.attach_alternative(html_content, "text/html") - - - if os.path.isfile(csvfile): - msg.attach_file(csvfile) - else: - csvfile2 = csvfile - with gzip.open(csvfile + '.gz', 'rb') as f_in, open(csvfile2, 'wb') as f_out: - shutil.copyfileobj(f_in, f_out) - - msg.attach_file(csvfile2) - os.remove(csvfile2) - - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False - - if not emailbounced: - res = msg.send() - + res = send_template_email(from_email,[fullemail], + subject,'summarymail.html',d, + attach_file=csvfile, + **kwargs) + try: os.remove(csvfile) except: @@ -654,37 +607,15 @@ def handle_sendemailcsv(first_name, last_name, email, csvfile,**kwargs): fullemail = first_name + " " + last_name + " " + "<" + email + ">" subject = "File from Rowsandall.com" - htmly = get_template('csvemail.html') - d = {'first_name':first_name} from_email = 'Rowsandall ' - html_content = htmly.render(d) - text_content = textify(html_content) - msg = EmailMultiAlternatives(subject, text_content, from_email, [fullemail]) - msg.attach_alternative(html_content, "text/html") - - if os.path.isfile(csvfile): - msg.attach_file(csvfile) - else: - csvfile2 = csvfile - with gzip.open(csvfile + '.gz', 'rb') as f_in, open(csvfile2, 'wb') as f_out: - shutil.copyfileobj(f_in, f_out) - - msg.attach_file(csvfile2) - os.remove(csvfile2) - - - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False - - if not emailbounced: - res = msg.send() - + res = send_template_email(from_email,[fullemail], + subject,'csvemail.html',d, + attach_file=csvfile,**kwargs) + return 1 @@ -819,22 +750,9 @@ def handle_otwsetpower(self,f1, boattype, weightvalue, 'workoutid':workoutid, } - html_content = htmly.render(d) - text_content = textify(html_content) - - msg = EmailMultiAlternatives(subject, text_content, from_email, [fullemail]) - msg.attach_alternative(html_content, "text/html") - - - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False - - if not emailbounced: - res = msg.send() - - + res = handle_template_email(from_email,[fullemail], + subject,'otwpoweremail.html',d, + **kwargs) return 1 @@ -1062,30 +980,20 @@ def handle_sendemail_invite(email, name, code, teamname, manager, if debug: siteurl = SITE_URL_DEV - htmly = get_template('teaminviteemail.html') - d = { 'name':name, - 'manage':manager, + 'manager':manager, 'code':code, 'teamname':teamname, + 'siteurl':siteurl } - html_content = htmly.render(d) - text_content = textify(html_content) + from_email = 'Rowsandall ' + + res = send_template_email(from_email,[fullemail], + subject,'teaminviteemail.html',d, + **kwargs) - msg = EmailMultiAlternatives(subject, text_content, from_email, [fullemail]) - msg.attach_alternative(html_content, "text/html") - - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False - - if not emailbounced: - res = msg.send() - - return 1 @@ -1106,8 +1014,6 @@ def handle_sendemailnewresponse(first_name, last_name, siteurl = SITE_URL_DEV - htmly = get_template('teamresponseemail.html') - d = { 'first_name':first_name, 'commenter_first_name':commenter_first_name, @@ -1133,30 +1039,32 @@ def handle_sendemailnewcomment(first_name, comment, workoutname, workoutid, debug=False,**kwargs): + + + fullemail = first_name + ' ' + last_name + ' <' + email + '>' + from_email = 'Rowsandall ' subject = 'New comment on workout ' + workoutname - message = 'Dear ' + first_name + ',\n\n' - message += commenter_first_name + ' ' + commenter_last_name - message += ' has written a new comment on your workout ' - message += workoutname + '\n\n' - message += comment - message += '\n\n' - message += 'You can read the comment here:\n' - message += 'https://rowsandall.com/rowers/workout/' + \ - str(workoutid) + '/comment' - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) + siteurl = SITE_URL + if debug: + siteurl = SITE_URL_DEV - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False + + d = { + 'first_name':first_name, + 'commenter_first_name':commenter_first_name, + 'commenter_last_name':commenter_last_name, + 'comment':comment, + 'workoutname':workoutname, + 'siteurl':siteurl, + 'workoutid':workoutid, + 'commentid':commentid + } - if not emailbounced: - res = email.send() - + res = send_template_email(from_email,[fullemail],subject, + 'teamresponseemail.html',d,**kwargs) + return 1 @@ -1166,29 +1074,23 @@ def handle_sendemail_request(email, name, code, teamname, requestor, id, debug=False,**kwargs): fullemail = name + ' <' + email + '>' subject = 'Request to join team ' + teamname - message = 'Dear ' + name + ',\n\n' - message += requestor + ' is requesting admission to your team ' + teamname - message += ' on rowsandall.com\n\n' - message += 'Click the direct link to accept: \n' - message += 'https://rowsandall.com/rowers/me/request/' + code + ' \n\n' - message += 'Click the following link to reject the request: \n' - message += 'https://rowsandall.com/rowers/me/request/' + str(id) + ' \n\n' - message += 'You can find all pending requests on your team management page:\n' - message += 'https://rowsandall.com/rowers/me/teams\n\n' - message += "Best Regards, the Rowsandall Team" + from_email = 'Rowsandall ' - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) + siteurl = SITE_URL + if debug: + siteurl = SITE_URL_DEV - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False + d = { + 'requestor':requestor, + 'teamname':teamname, + 'siteurl':siteurl, + 'id':id, + 'first_name':name, + } + + res = send_template_email(from_email,[fullemail],subject, + 'teamrequestemail.html',d,**kwargs) - if not emailbounced: - res = email.send() - return 1 @@ -1198,25 +1100,20 @@ def handle_sendemail_request_accept(email, name, teamname, managername, debug=False,**kwargs): fullemail = name + ' <' + email + '>' subject = 'Welcome to ' + teamname - message = 'Dear ' + name + ',\n\n' - message += managername - message += ' has accepted your request to be part of the team ' - message += teamname - message += '\n\n' - message += "Best Regards, the Rowsandall Team" + from_email = 'Rowsandall ' - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) + siteurl = SITE_URL + if debug: + siteurl = SITE_URL_DEV - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False + d = { + 'first_name':name, + 'managername':managername, + 'teamname':teamname, + } + res = send_template_email(from_email,[fullemail],subject, + 'teamwelcomeemail.html',d,**kwargs) - if not emailbounced: - res = email.send() - return 1 @@ -1226,26 +1123,19 @@ def handle_sendemail_request_reject(email, name, teamname, managername, debug=False,**kwargs): fullemail = name + ' <' + email + '>' subject = 'Your application to ' + teamname + ' was rejected' - message = 'Dear ' + name + ',\n\n' - message += 'Unfortunately, ' - message += managername - message += ' has rejected your request to be part of the team ' - message += teamname - message += '\n\n' - message += "Best Regards, the Rowsandall Team" + from_email = 'Rowsandall ' - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) + siteurl = SITE_URL + if debug: + siteurl = SITE_URL_DEV - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False - - if not emailbounced: - res = email.send() - + d = { + 'first_name':name, + 'managername':managername, + 'teamname':teamname, + } + res = send_template_email(from_email,[fullemail],subject, + 'teamrejectemail.html',d,**kwargs) return 1 @@ -1255,26 +1145,20 @@ def handle_sendemail_member_dropped(email, name, teamname, managername, debug=False,**kwargs): fullemail = name + ' <' + email + '>' subject = 'You were removed from ' + teamname - message = 'Dear ' + name + ',\n\n' - message += 'Unfortunately, ' - message += managername - message += ' has removed you from the team ' - message += teamname - message += '\n\n' - message += "Best Regards, the Rowsandall Team" + from_email = 'Rowsandall ' - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) + siteurl = SITE_URL + if debug: + siteurl = SITE_URL_DEV - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False + d = { + 'first_name':name, + 'managername':managername, + 'teamname':teamname, + } + res = send_template_email(from_email,[fullemail],subject, + 'teamdropemail.html',d,**kwargs) - if not emailbounced: - res = email.send() - return 1 @@ -1282,29 +1166,23 @@ def handle_sendemail_member_dropped(email, name, teamname, managername, @app.task def handle_sendemail_team_removed(email, name, teamname, managername, debug=False,**kwargs): + fullemail = name + ' <' + email + '>' - subject = 'Team ' + teamname + ' was deleted' - message = 'Dear ' + name + ',\n\n' - message += managername - message += ' has decided to delete the team ' - message += teamname - message += '\n\n' - message += 'The ' + teamname + ' tag has been removed from all your ' - message += 'workouts on rowsandall.com.\n\n' - message += "Best Regards, the Rowsandall Team" + subject = 'You were removed from ' + teamname + from_email = 'Rowsandall ' - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) + siteurl = SITE_URL + if debug: + siteurl = SITE_URL_DEV - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False + d = { + 'first_name':name, + 'managername':managername, + 'teamname':teamname, + } + res = send_template_email(from_email,[fullemail],subject, + 'teamremoveemail.html',d,**kwargs) - if not emailbounced: - res = email.send() - return 1 @@ -1314,26 +1192,20 @@ def handle_sendemail_invite_reject(email, name, teamname, managername, debug=False,**kwargs): fullemail = managername + ' <' + email + '>' subject = 'Your invitation to ' + name + ' was rejected' - message = 'Dear ' + managername + ',\n\n' - message += 'Unfortunately, ' - message += name - message += ' has rejected your invitation to be part of the team ' - message += teamname - message += '\n\n' - message += "Best Regards, the Rowsandall Team" - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) + from_email = 'Rowsandall ' - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False + siteurl = SITE_URL + if debug: + siteurl = SITE_URL_DEV - if not emailbounced: - res = email.send() - + d = { + 'first_name':name, + 'managername':managername, + 'teamname':teamname, + } + res = send_template_email(from_email,[fullemail],subject, + 'teaminviterejectemail.html',d,**kwargs) return 1 @@ -1343,22 +1215,21 @@ def handle_sendemail_invite_accept(email, name, teamname, managername, debug=False,**kwargs): fullemail = managername + ' <' + email + '>' subject = 'Your invitation to ' + name + ' was accepted' - message = 'Dear ' + managername + ',\n\n' - message += name + ' has accepted your invitation to be part of the team ' + teamname + '\n\n' - message += "Best Regards, the Rowsandall Team" - email = EmailMessage(subject, message, - 'Rowsandall ', - [fullemail]) + from_email = 'Rowsandall ' - if 'emailbounced' in kwargs: - emailbounced = kwargs['emailbounced'] - else: - emailbounced = False + siteurl = SITE_URL + if debug: + siteurl = SITE_URL_DEV + + d = { + 'first_name':name, + 'managername':managername, + 'teamname':teamname, + } + res = send_template_email(from_email,[fullemail],subject, + 'teaminviteacceptemail.html',d,**kwargs) - if not emailbounced: - res = email.send() - return 1 diff --git a/rowers/teams.py b/rowers/teams.py index ba802fd2..7ddbfcad 100644 --- a/rowers/teams.py +++ b/rowers/teams.py @@ -393,6 +393,7 @@ def send_request_email(rekwest): code = rekwest.code teamname = rekwest.team.name requestor = rekwest.user.first_name+' '+rekwest.user.last_name + print requestor,'aap' res = myqueue(queuehigh, handle_sendemail_request, diff --git a/rowers/templates/teamdropemail.html b/rowers/templates/teamdropemail.html new file mode 100644 index 00000000..d8255b15 --- /dev/null +++ b/rowers/templates/teamdropemail.html @@ -0,0 +1,16 @@ +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %} +

Dear {{ first_name }},

+ +

+ Unfortunately, + {{ managername }} has removed you from + the team {{ teamname }}. +

+

+ Best Regards, the Rowsandall Team +

+{% endblock %} diff --git a/rowers/templates/teaminviteacceptemail.html b/rowers/templates/teaminviteacceptemail.html new file mode 100644 index 00000000..86754ee1 --- /dev/null +++ b/rowers/templates/teaminviteacceptemail.html @@ -0,0 +1,16 @@ +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %} +

Dear {{ managername }},

+ +

+ {{ first_name }} has accepted your invitation to be + part of the team {{ teamname }}. +

+ +

+ Best Regards, the Rowsandall Team +

+{% endblock %} diff --git a/rowers/templates/teaminviterejectemail.html b/rowers/templates/teaminviterejectemail.html new file mode 100644 index 00000000..30ab689a --- /dev/null +++ b/rowers/templates/teaminviterejectemail.html @@ -0,0 +1,17 @@ +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %} +

Dear {{ managername }},

+ +

+ Unfortunately, + {{ first_name }} has rejected your invitation to be + part of the team {{ teamname }}. +

+ +

+ Best Regards, the Rowsandall Team +

+{% endblock %} diff --git a/rowers/templates/teamrejectemail.html b/rowers/templates/teamrejectemail.html new file mode 100644 index 00000000..34422898 --- /dev/null +++ b/rowers/templates/teamrejectemail.html @@ -0,0 +1,16 @@ +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %} +

Dear {{ first_name }},

+ +

+ Unfortunately, + {{ managername }} has rejected your request to be part + of the team {{ teamname }}. +

+

+ Best Regards, the Rowsandall Team +

+{% endblock %} diff --git a/rowers/templates/teamremoveemail.html b/rowers/templates/teamremoveemail.html new file mode 100644 index 00000000..64c92d62 --- /dev/null +++ b/rowers/templates/teamremoveemail.html @@ -0,0 +1,19 @@ +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %} +

Dear {{ first_name }},

+ +

+ {{ managername }} has decided to delete the team {{ teamname }}. +

+

+ The {{ teamname }} tag has been removed from all your + workouts on rowsandall.com +

+ +

+ Best Regards, the Rowsandall Team +

+{% endblock %} diff --git a/rowers/templates/teamrequestemail.html b/rowers/templates/teamrequestemail.html new file mode 100644 index 00000000..dd436837 --- /dev/null +++ b/rowers/templates/teamrequestemail.html @@ -0,0 +1,29 @@ +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %} +

Dear {{ first_name }},

+ +

+ {{ requestor }} is requesting access to your team {{ teamname }} + on rowsandall.com +

+

+ Click the direct link to accept: + + {{ siteurl }}/rowers/me/request/{{ code }} +

+

+ Click the following link to reject the request: + + {{ siteurl }}/rowers/me/request/{{ id }} +

+

+ You can find all pending requests on your team management page: + {{ siteurl }}/rowers/me/teams +

+

+ Best Regards, the Rowsandall Team +

+{% endblock %} diff --git a/rowers/templates/teamresponseemail.html b/rowers/templates/teamresponseemail.html index 3bb04e19..d0def71a 100644 --- a/rowers/templates/teamresponseemail.html +++ b/rowers/templates/teamresponseemail.html @@ -7,7 +7,7 @@

{{ commenter_first_name }} {{ commenter_last_name }} has written - a new comment on your workout {{ workoutname }} + a new comment on workout {{ workoutname }}

{{ comment }} diff --git a/rowers/templates/teamwelcomeemail.html b/rowers/templates/teamwelcomeemail.html new file mode 100644 index 00000000..d255002c --- /dev/null +++ b/rowers/templates/teamwelcomeemail.html @@ -0,0 +1,15 @@ +{% extends "emailbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block body %} +

Dear {{ first_name }},

+ +

+ {{ managername }} has accepted your request to be part + of the team {{ teamname }}. +

+

+ Best Regards, the Rowsandall Team +

+{% endblock %} diff --git a/temp.txt b/temp.txt deleted file mode 100644 index 5fdc2a13..00000000 --- a/temp.txt +++ /dev/null @@ -1,5 +0,0 @@ ---- -aap: noot -mies: jet -jet -... \ No newline at end of file From a466990b5cdbbee9bc688524b4e1c97a78fe0c3b Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 19 Mar 2018 21:16:02 +0100 Subject: [PATCH 9/9] smaller logo in emails --- rowers/templates/emailbase.html | 2 +- static/img/logoemail.png | Bin 0 -> 5143 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 static/img/logoemail.png diff --git a/rowers/templates/emailbase.html b/rowers/templates/emailbase.html index 58c339eb..4f457f2b 100644 --- a/rowers/templates/emailbase.html +++ b/rowers/templates/emailbase.html @@ -5,7 +5,7 @@ {% load rowerfilters %} - + {% block body %} diff --git a/static/img/logoemail.png b/static/img/logoemail.png new file mode 100644 index 0000000000000000000000000000000000000000..aacc2e3f43561ecc85985db7bf41c2420c6c270f GIT binary patch literal 5143 zcmV+y6zJ=TP)0~Z>t7Bng`1aYz>@Oz*Y7;CheQV>Uh0^fYX=nq^4>@P`A z0;7#quXbdDd#cT)B6S>Tw0gJbq5=iJK?vd``@eG#C#~{lf;d^%z261(-W9wF3&ewoz@*HLl7qefy;mhSW>7c1q$?F!U*D|1$YBk3s?xOZ?t-| zJEa@3nfw*_39zUjjRFO}J~X#M7W0HGz5td7-t5lC30YvY+6!xBZ7$T40tI>yVK@_V zCa@x~&}g+h(E4?(?ha{;0WK)ItU!St0>{94jTko<1#!~U!`gO5A!QUO&;uk4SFE!UYP(_8LbZQp_0&YSkKYI2>KmIsazqA z!f#yJ-xihRR#8RfeFM~{0}9pTJ53Z%mCBX0i^@K_RIapoX?;rNN^7ZHIp#aBk_2%= z5GTWceI2H&`E?L(#6l^`dy>d13gfh*c8|~h?5<#aW>Wk`qlC1hC!UHXtesM=;{Im zI!{+SUjER;^y0d1+sf1)MFa zSstzy@?7k;Gn*)-a%F$uROt^FPXfP7qwrqI-wLQS3LkLFcpaFLM&TZ%a^*;A#{jRK z=Yf;cD7-Ikayso8E(AX^=Q~^n9GXVqqEfjs6<8^a!mtWqtPYF=e#){&%y)q+(7!_{VXtAt>8{ltS`i%krMLmH|9M$mg6Y zll*MpEFcx4e*}A;X`l@D)38z7)&*_@`sWcwsazS24e0cNOt=Sue@Z#K04Iv%Gf>9N zoHPnYbS7a)|E?nCuTe+ej4)a~={!G17OJ*zkt*#v*ir&~*o*M>nvK6ph&T7@!m@QJoUyN20z0RtJ<=ZIpa;LMW=G(ds$pd#>-1 zMJsS8Hh$`g*ieW+kb6IN3zZf9Az4-SOr!8_Pn4gUMqyc0gK4F5%lPHb|;^YI->!$!WicO>|$>JnnWuw&~ zqm?hN*So{>cUe^jiOO=Hh=$o@z0=D-1z6W;)l1Zi1A#@({dIu@96ym4fp?ty|CZB+ z^K#O5@FcY1G7(*|-2I+=I`S zyq4imRG{;KHB05nYR;__q@G{ZW6TuwHV>!E|9vx~W*gY33&-g%yz9+8Dc8_*VR{j zUHwp}j3MseaR+e_C$8GGja#MB>SeFYyS>%oQ#sK)I*5~Pu@Tz)_^Mi|Tp1)%!}vNU z7r>DN`EPT^?~Pubxkjthk&v@=cW?yF&I&cZ9b#8k>}=G+ zeVyP`_E}rHr>{;KtsbvYXY5_~b)I|OQ}y<6K9BJXPcBxK_q#mHI-`xxY47u5aP%kk z^;b8ioJ#$j!yab-w=( z5yXivx!l#jBIinskF}BaGEd5=hFLj_olm%LRcYfgnn$x!QFA-q&Ck1$EEXB9cCR*Z zJNfKOi)Tcvg}F7J#S`P#3*sarl!Kl0Gd;cj6#4%LudE4q-`i-l32+7QX^nOs1bi06 zNwc$E+$MqM^+Ol*ZHpN68o`pBwBFcVutxA<7knSzu>N5Ki<~&))TkL7bGF>(9kO#DC(AS0cigA}l_YO6bOzpQhw(Ab$Typ% zJ3@7-H`LxiXt&mzW51{u3#zE2dDyixplT`};2Y$YjadbXdJANvT{pqKo?XS?tej)~iN9{&wXPV#lBX5?s9#78rjFz3WM0 zht?wn%YAn%f7KvPwy2VKHLUA`OEj(BK^Sky=M5XN4T$}scQ+A6&9Hnyob+|A$elnM z_j)?=*dR`J%`sYC&9WBlC#sxVacvZv1IOeL!D8&zbcS2JGVZ7`Smy?DGBHO_%|5!~ z{tBKBd`Mdp%(-_?7xnK|K;Kfi^2>Upf>OCsCf}KE9MG>+t{hvZ`}l=aci^jwEMy@$ zHHec_GU67v$1H*%P9F1*90YOFD~OY6nXyvtAM920lq=!NbIn+XFc$}R$AQrnS=mN< zt64ovctkgm#fL_#6B@8NbQVr$S?8I1gE;vV>ovGCc6Z3Hcdsh%YCKB=7`F&%WP0PD zv%wO?$*-{Fb34~J#C=yrtB(V9fu3ep zDQC2(fG=Skp7Jme`$OS7dFonw;7TaV1#z;5^!aSQx;@`Z$Xf}?XOq4k@R1WCe{+uz zo3U=}`^h5UlEo5W#qJ78(F{DCiK=qgrCw~%4P-IbXmx%aG_nn&%~XcFr^J=j3~^M%jZ{c6+TBh8nHrxdSVW!WlAn=KznE%9T$_<;r{V_py-L z%N-Hj>oh(h?YI#*qg1XeER`$sO6AJjQn@l;&amtT3`?W%wmh4akP5O2p9vgRDpwZg zlrst_x#wXzIEQ@uMK*q}@a$F9@VI<;99!9%)ON-~B$d9@xx>*ZDv8mm62!?|G5(y1 z-F|CpGHuGTCpQ;i_rG5i=Kny_mXj9|hy+t=uzhFL(Uuj+-(vH1+ldY%*DG#fw7NEk zlbf+8Y7dqb`3sR4ZUAOxk=5Jiv>UPK7F>_LJ9DI^ZKMv@;5)yKwjLYA$+_4w0f&pY zo8b}c_Uyw(t1qfd*!O`U;>@+ZNE%Jpb2@)dqi~LseJj3t?&tu|{!$B{OBs1b5tgJ; z`0u51WsIl{d&>Bk0o)GEOrx+>NZ~+oe1J02NTcu%rE+DQyvuz=m3kHHIzBUv!X=Io z+TYT>3HV1&ySH|1ep!F51e`1e#|wP>k#7RSrTS1)k3F2gM5GNyoI2jkj$wKExp54DU>nJOWY0;1syV2dCF8smi zPRm!P1-?zypwatoT7%oO4Y#AM`Wr2$t+v+~u-{geo%O>cq*fSQ5 zbnrk?Q3eZp_K_9pbL_EV1H7C@;agQ2KR}+}Lu>?_$ZC0OTkVh?l27W?lilkW>r^$f z2qj;jK%Io)OuQ`S!fQsW^{Y&})kXZ=1#77tjNLJ41oK3!n+8luqwuZ{Fyt24SQM>w z5X8Q~VIn$Tn?~X7dHD(yD9{FB$mAP_-C_mUSdM2?Dpw8?BhgMQjiWh7^vYL7dYFs# zTUaPIf?imUz?H=)w~pwN)zpV+z*AW3{-b_qxM~=9w(prEq%zRSOj8A#f($H*Z@Pgbvi||_pwa5Mp7;aN1qyuE&{WUl74rBQHV{k;)+eHr{q|yK z5{1;&3wz*Yp3&-0MK={F(8DDRSJDtnG+On>h7juum>^E3263`#7BQ$3RE8$8RlH)f zIu$6$qCkOfl7vx368OFlN9Odf0Qj{W1*cYIZ$C_#U?BGR`Fg;XMyokR*Ayu5Eg=kN zviHJ9#L9k~qZJ$P;c0CAhX;&SFL}?cf{hBb4>qPjKWr$xQ?Rigie4#D;M+zRp3R{d z8(emKY%IgQSvJ_LizV2AwpU?)-}F