Merge lp:~deadlight/canonical-identity-provider/email-template into lp:~deadlight/canonical-identity-provider/vanilla

Proposed by Karl Williams on 2019-08-29
Status: Merged
Approved by: Karl Williams on 2019-08-30
Approved revision: 1715
Merged at revision: 1715
Proposed branch: lp:~deadlight/canonical-identity-provider/email-template
Merge into: lp:~deadlight/canonical-identity-provider/vanilla
Diff against target: 393 lines (+274/-17)
2 files modified
src/identityprovider/emailutils.py (+27/-17)
src/webui/templates/email/html/email.html (+247/-0)
To merge this branch: bzr merge lp:~deadlight/canonical-identity-provider/email-template
Reviewer Review Type Date Requested Status
Anthony Dillon (community) 2019-08-29 Approve on 2019-08-30
Review via email: mp+372011@code.launchpad.net

Description of the change

Added an HTML email template

QA:
In terminal 1:
- npm i
- ./node_modules/gulp/bin/gulp.js sass
- source env/bin/activate
- make start-db
- make run

In terminal 2:
- source env/bin/activate
- make mail-debug

- Visit http://[CONTAINER IP]:8000/
- Create an account
- Check the output of terminal 2 and see the email text
- Copy the HTML email into a file and open it in a browser to view ityo

To post a comment you must log in.
Karl Williams (deadlight) wrote :
Anthony Dillon (ya-bo-ng) wrote :

LGTM +1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/identityprovider/emailutils.py'
--- src/identityprovider/emailutils.py 2018-08-22 22:33:08 +0000
+++ src/identityprovider/emailutils.py 2019-08-29 15:29:29 +0000
@@ -64,22 +64,28 @@
64 return formataddr((name, address))64 return formataddr((name, address))
6565
6666
67def send_templated_email(subject, template, context, email, from_address=None):67def send_templated_email(subject, template, context, email, from_address=None, title=None):
68 msg = render_to_string(template, context=context)68 msg = render_to_string(template, context=context)
6969
70 if from_address is None:70 if from_address is None:
71 from_address = format_address(settings.NOREPLY_FROM_ADDRESS)71 from_address = format_address(settings.NOREPLY_FROM_ADDRESS)
72 if title is None:
73 title = 'Ubuntu One'
74
75 html = render_to_string('email/html/email.html', {'title':title, 'content':msg})
76
72 if not isinstance(email, (tuple, list)):77 if not isinstance(email, (tuple, list)):
73 email = [email]78 email = [email]
74 return send_mail(79 return send_mail(
75 subject,80 subject = subject,
76 msg,81 message = msg,
77 from_address,82 from_email = from_address,
78 [format_address(e) for e in email]83 recipient_list = [format_address(e) for e in email],
84 html_message = html
79 )85 )
8086
8187
82def send_fancy_email(subject, template, context, email, from_address=None):88def send_fancy_email(subject, template, context, email, from_address=None, title=None):
83 if from_address is None:89 if from_address is None:
84 from_address = format_address(90 from_address = format_address(
85 settings.NOREPLY_FROM_ADDRESS,91 settings.NOREPLY_FROM_ADDRESS,
@@ -87,7 +93,7 @@
87 )93 )
88 subject = u"%s: %s" % (settings.NOREPLY_FROM_NAME, subject)94 subject = u"%s: %s" % (settings.NOREPLY_FROM_NAME, subject)
89 return send_templated_email(subject, template, context, email,95 return send_templated_email(subject, template, context, email,
90 from_address)96 from_address, title)
9197
9298
93def _should_add_invalidation_link(email):99def _should_add_invalidation_link(email):
@@ -178,7 +184,7 @@
178 template = 'email/desktop-newuser.txt'184 template = 'email/desktop-newuser.txt'
179185
180 send_fancy_email(186 send_fancy_email(
181 _('Finish your registration'), template, context, email)187 _('Finish your registration'), template, context, email, None, 'Finish your registration')
182 return token, invalidate_email_token188 return token, invalidate_email_token
183189
184190
@@ -219,7 +225,7 @@
219 context, token, invalidate_email_token = _context_for_email_request(225 context, token, invalidate_email_token = _context_for_email_request(
220 root_url, account, email, AuthTokenType.PASSWORDRECOVERY,226 root_url, account, email, AuthTokenType.PASSWORDRECOVERY,
221 redirection_url, requester_email=email)227 redirection_url, requester_email=email)
222 send_fancy_email(subject, template, context, email)228 send_fancy_email(subject, template, context, email, None, 'Password reset')
223 return token, invalidate_email_token229 return token, invalidate_email_token
224230
225231
@@ -236,7 +242,7 @@
236 send_fancy_email(242 send_fancy_email(
237 _("Password change notification"),243 _("Password change notification"),
238 'email/password-changed.txt',244 'email/password-changed.txt',
239 context=context, email=email.email)245 context=context, email=email.email, from_address=None, title='Password changed')
240246
241247
242def send_printed_codes_renewal_email(root_url, account, devices):248def send_printed_codes_renewal_email(root_url, account, devices):
@@ -257,7 +263,7 @@
257 send_fancy_email(263 send_fancy_email(
258 _("Printed list of backup codes is nearly used up"),264 _("Printed list of backup codes is nearly used up"),
259 'email/printed-codes-nearly-exhausted-warning.txt',265 'email/printed-codes-nearly-exhausted-warning.txt',
260 context=context, email=email)266 context=context, email=email, from_address=None, title='Backup codes')
261267
262268
263def send_validation_email_request(root_url, account, email,269def send_validation_email_request(root_url, account, email,
@@ -281,7 +287,7 @@
281 requester_email=preferredemail_email, oid_token=oid_token)287 requester_email=preferredemail_email, oid_token=oid_token)
282 send_fancy_email(288 send_fancy_email(
283 _("Validate your email address"), 'email/validate-email.txt',289 _("Validate your email address"), 'email/validate-email.txt',
284 context, email)290 context, email, None, 'Validate your email address')
285 return token, invalidate_email_token291 return token, invalidate_email_token
286292
287293
@@ -300,7 +306,8 @@
300 send_fancy_email(306 send_fancy_email(
301 _("The email address {email} was removed from your account").format(307 _("The email address {email} was removed from your account").format(
302 email=invalidated_email),308 email=invalidated_email),
303 'email/email-invalidated.txt', context=context, email=email)309 'email/email-invalidated.txt', context=context, email=email,
310 from_address=None, title='Email address removed')
304311
305312
306def send_notification_to_invalidated_email_address(root_url, account,313def send_notification_to_invalidated_email_address(root_url, account,
@@ -315,14 +322,16 @@
315 ),322 ),
316 'email/invalidate_email_confirmation.txt',323 'email/invalidate_email_confirmation.txt',
317 context=context,324 context=context,
318 email=invalidated_email325 email=invalidated_email,
326 from_address=None,
327 title='Email address invalidated'
319 )328 )
320329
321330
322def send_preferred_changed_notification(email, new_preferred):331def send_preferred_changed_notification(email, new_preferred):
323 send_fancy_email(332 send_fancy_email(
324 _('E-mail change notification'), 'email/preferred-changed.txt',333 _('E-mail change notification'), 'email/preferred-changed.txt',
325 {'new_preferred': new_preferred}, email)334 {'new_preferred': new_preferred}, email, None, 'Preferred email changed')
326335
327336
328def send_invitation_after_password_reset(root_url, email):337def send_invitation_after_password_reset(root_url, email):
@@ -330,7 +339,7 @@
330 url = urljoin(root_url, reverse('new_account'))339 url = urljoin(root_url, reverse('new_account'))
331 send_fancy_email(340 send_fancy_email(
332 _("Password reset request"), 'email/invitation.txt',341 _("Password reset request"), 'email/invitation.txt',
333 {'email': email, 'signup': url}, email,342 {'email': email, 'signup': url}, email, None, 'Password reset request'
334 )343 )
335344
336345
@@ -363,7 +372,8 @@
363 else:372 else:
364 subject = _('Account to be deleted - action required')373 subject = _('Account to be deleted - action required')
365 send_fancy_email(374 send_fancy_email(
366 subject, 'email/account-action-required.txt', context, email,375 subject, 'email/account-action-required.txt', context, email, None,
376 'Action required'
367 )377 )
368 return token, invalidate_email_token378 return token, invalidate_email_token
369379
370380
=== added directory 'src/webui/templates/email/html'
=== added file 'src/webui/templates/email/html/email.html'
--- src/webui/templates/email/html/email.html 1970-01-01 00:00:00 +0000
+++ src/webui/templates/email/html/email.html 2019-08-29 15:29:29 +0000
@@ -0,0 +1,247 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2<html xmlns="http://www.w3.org/1999/xhtml"
3xmlns:v="urn:schemas-microsoft-com:vml"
4xmlns:o="urn:schemas-microsoft-com:office:office">
5
6<head>
7 <!--[if gte mso 9]><xml>
8 <o:OfficeDocumentSettings>
9 <o:AllowPNG/>
10 <o:PixelsPerInch>96</o:PixelsPerInch>
11 </o:OfficeDocumentSettings>
12 </xml><![endif]-->
13
14 <!-- Define Charset -->
15 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
16
17 <!-- Responsive Meta Tag -->
18 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
19
20 <link href="https://fonts.googleapis.com/css?family=Ubuntu:100,300,400,500,700" rel="stylesheet">
21
22 <title>{{ title }}</title>
23
24 <!-- Responsive Styles and Valid Styles -->
25
26 <style type="text/css">
27 /* iOS BLUE LINKS */
28 a[x-apple-data-detectors] {
29 color: inherit !important;
30 text-decoration: none !important;
31 font-size: inherit !important;
32 font-family: inherit !important;
33 font-weight: inherit !important;
34 line-height: inherit !important;
35 }
36
37 body{
38 width: 100%;
39 background-color: #E1E1E1;
40 margin:0;
41 padding:0;
42 -webkit-font-smoothing: antialiased;
43 mso-margin-top-alt:0px;
44 mso-margin-bottom-alt:0px;
45 mso-padding-alt: 0px 0px 0px 0px;
46 -webkit-text-size-adjust:none;
47 }
48
49 p,h1,h2,h3,h4{
50 margin-top:0;
51 margin-bottom:0;
52 padding-top:0;
53 padding-bottom:0;
54 }
55
56 p {
57 margin-bottom: 1em;
58 }
59
60 [style*="Ubuntu"] {
61 font-family: Ubuntu, Sans Serif, Arial, Helvetica !important;
62 }
63
64 span.Preheader{display: none; font-size: 1px;}
65
66 html{
67 width: 100%;
68 }
69
70 .ZedFix {
71 display:none;
72 display:none!important;
73 }
74
75 /* ----------- responsivity ----------- */
76 @media only screen and (max-width: 640px){
77 /*-------- Table --------*/
78 *[class=Table800] {width: 100% !important;}
79 *[class=Table799] {width: 90% !important;}
80 *[class=Table740] {width: 100% !important;}
81 *[class=Tds200] {width: 150px !important; padding-left:0 !important;}
82 *[class=Tds540] {width: 610px !important;}
83
84 /*----- Image -------*/
85 *[class=Inbox] img{width: 50% !important; height: auto !important;}
86
87 /*----- Others -------*/
88 *[class=Zwidth] {min-width:100% !important;}
89 *[class=MobileHide] {display:none !important;}
90 *[class=TextC] {text-align:center !important;}
91 }
92
93 @media only screen and (max-width: 479px){
94 /*-------- Table --------*/
95 *[class=Table800] {width: 100% !important; min-width:360px !important;}
96 *[class=Tds200] {width: 110px !important; padding-left:0 !important;}
97 *[class=Tds540] {width: 210px !important;}
98
99 /*----- Image -------*/
100 *[class=Inbox] img{width: 50% !important; height: auto !important;}
101
102 /*----- Others -------*/
103 *[class=Zwidth] {min-width:100% !important;}
104 *[class=MobileHide] {display:none !important;}
105 *[class=TextC] {text-align:center !important;}
106 *[class=Fonts48] {font-size:35.65px !important; line-height:48px !important;}
107 }
108 </style>
109</head>
110
111<body leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">
112 <table border="0" width="100%" cellpadding="0" cellspacing="0" bgcolor="#E1E1E1">
113 <tr>
114 <td align="center" class="Zwidth" style="min-width:800px;">
115 <div class="mktEditable" id="Header">
116 <table align="center" width="800" border="0" cellspacing="0" cellpadding="0" bgcolor="#380426" style="border-collapse:collapse; mso-table-lspace:0pt; mso-table-rspace:0pt; width:800px;" class="Table800">
117 <tr>
118 <td background="https://assets.ubuntu.com/v1/1d8ce799-email-hero-background.png?w=800" bgcolor="#380426" width="800" height="289" valign="top" style="background-image:url(https://assets.ubuntu.com/v1/1d8ce799-email-hero-background.png?w=800); background-position:top center; background-size:cover;">
119 <!--[if gte mso 9]>
120 <v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="width:800px;height:289px;">
121 <v:fill type="tile" src="https://assets.ubuntu.com/v1/1d8ce799-email-hero-background.png?w=800" color="#7D335B" />
122 <v:textbox inset="0,0,0,0">
123 <![endif]-->
124 <div>
125 <table align="center" width="800" border="0" cellspacing="0" cellpadding="0" style="border-collapse:collapse; mso-table-lspace:0pt; mso-table-rspace:0pt; width:800px;" class="Table799">
126 <tr>
127 <td align="center">
128 <table align="center" width="740" border="0" cellspacing="0" cellpadding="0" style="border-collapse:collapse; mso-table-lspace:0pt; mso-table-rspace:0pt; width:740px;" class="Table740">
129 <tr>
130 <td align="left" valign="bottom" style="padding: 65px 0 0;">
131 <img height="55" width="120" src="https://assets.ubuntu.com/v1/d738f754-Ubuntu_One_Mono_Logo.svg" />
132 </td>
133 </tr>
134 <tr>
135 <td align="left" valign="bottom" class="Fonts48" style="color:#FFFFFF; font-family: Arial, Sans Serif, Ubuntu; font-size:46.5667px; line-height:56px; font-weight:100; font-style:normal; padding:30px 0 50px 0;">
136 {{ title }}
137 </td>
138 </tr>
139 </table>
140 </td>
141 </tr>
142 </table>
143 </div>
144 <!--[if gte mso 9]>
145 </v:textbox>
146 </v:rect>
147 <![endif]-->
148 </td>
149 </tr>
150 </table>
151 </div>
152 </td>
153</tr>
154
155<tr>
156 <td align="center" class="Zwidth" style="min-width:800px;">
157 <div class="mktEditable" id="Primary_talking">
158 <table align="center" width="800" border="0" cellspacing="0" cellpadding="0" bgcolor="#FFFFFF" style="border-collapse:collapse; mso-table-lspace:0pt; mso-table-rspace:0pt; width:800px;" class="Table800">
159 <tr>
160 <td align="center" style="padding:54px 20px">
161 <table align="center" width="740" border="0" cellspacing="0" cellpadding="0" style="border-collapse:collapse; mso-table-lspace:0pt; mso-table-rspace:0pt; width:740px;" class="Table740">
162 <tr>
163 <td align="left" style="color:#0E0E0E; font-family: Arial, Sans Serif, Ubuntu; font-size:16px; line-height:24px; font-weight:300; font-style:normal; padding:16px 0 0 0">
164 {{ content|linebreaks|urlize }}
165 </td>
166 </tr>
167 </table>
168 </td>
169 </tr>
170 </table>
171 </div>
172 </td>
173</tr>
174
175<tr>
176 <td align="center" class="Zwidth" style="min-width:800px;">
177 <div class="mktEditable" id="Footer">
178 <table align="center" width="800" cellpadding="0" bgcolor="#F7F7F7" border="0" cellspacing="0" style="border-collapse:collapse; mso-table-lspace:0pt; mso-table-rspace:0pt; width:800px;" class="Table800">
179 <tr>
180 <td align="center" style="padding:40px 20px 0 20px;">
181 <table align="center" width="740" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse; mso-table-lspace:0pt; mso-table-rspace:0pt; width:740px;" class="Table740">
182 <tr>
183 <td align="left">
184 <table align="left" width="167" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse; mso-table-lspace:0pt; mso-table-rspace:0pt; width:167px;" class="Table740">
185 <tr>
186 <td align="center">
187 <table align="center" width="167" cellpadding="0" cellspacing="0" border="0" style="border-collapse:collapse; mso-table-lspace:0pt; mso-table-rspace:0pt;">
188 <tr>
189 <td align="left" valign="middle" width="32">
190 <a href="https://www.linkedin.com/company/ubuntu/" target="_blank"> <img src="https://assets.ubuntu.com/v1/885320bd-social-linkedin.png" width="32" height="32" border="0" style="display:block; width:32px; height:32px" alt="" /> </a>
191 </td>
192 <td align="left" valign="middle" width="13">&nbsp;</td>
193 <td align="left" valign="middle" width="32">
194 <a href="https://twitter.com/ubuntu" target="_blank"> <img src="https://assets.ubuntu.com/v1/28569fb0-social-twitter.png" width="32" height="32" border="0" style="display:block; width:32px; height:32px" alt="" /> </a>
195 </td>
196 <td align="left" valign="middle" width="13">&nbsp;</td>
197 <td align="left" valign="middle" width="32">
198 <a href="https://www.facebook.com/ubuntulinux/" target="_blank"> <img src="https://assets.ubuntu.com/v1/63b1275f-social-facebook.png" width="32" height="32" border="0" style="display:block; width:32px; height:32px" alt="" /> </a>
199 </td>
200 </tr>
201 </table>
202 </td>
203 </tr>
204 </table>
205 </td>
206 </tr>
207 <tr>
208 <td align="left" class="TextC" style="color:#000000; font-family: Arial, Sans Serif, Ubuntu; font-size:16px; line-height:24px; font-weight:300; font-style:normal; padding:20px 0 5px 0">
209 <a style="color:#000000; text-decoration:none" href="http://www.canonical.com" target="_blank">www.canonical.com</a> &nbsp; | &nbsp; <a style="color:#000000; text-decoration:none" href="http://www.ubuntu.com" target="_blank">www.ubuntu.com</a>
210 </td>
211 </tr>
212 <tr>
213 <td align="left" class="TextC" style="color:#000000; font-family: Arial, Sans Serif, Ubuntu; font-size:14px; line-height:22px; font-weight:300; font-style:normal; padding:0 0 50px 0">
214 © 2019 Canonical Ltd. Ubuntu and Canonical are registered trademarks of Canonical Ltd.
215 </td>
216 </tr>
217 </table>
218 </td>
219 </tr>
220 </table>
221 </div>
222 </td>
223</tr>
224
225<tr>
226 <td align="center" class="Zwidth" style="min-width:800px">
227 <table align="center" width="800" border="0" cellpadding="0" cellspacing="0" bgcolor="#FFFFFF" style="border-collapse:collapse; mso-table-lspace:0pt; mso-table-rspace:0pt; width:800px;" class="Table800">
228 <tr>
229 <td align="left" class="Inbox" valign="top" width="50%">
230 <img src="https://assets.ubuntu.com/v1/99e75450-inbox.png" width="400" height="1" border="0" style="display:block; width:400px; height:1px;" alt="" />
231 </td>
232 <td align="right" class="Inbox" valign="top" width="50%">
233 <img src="https://assets.ubuntu.com/v1/99e75450-inbox.png" width="400" height="1" border="0" style="display:block; width:400px; height:1px;" alt="" />
234 </td>
235 </tr>
236 </table>
237 </td>
238</tr>
239</table>
240<div class="ZedFix" style="white-space:nowrap; font:15px courier; line-height:0;">
241 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
242 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
243 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
244</div>
245
246</body>
247</html>

Subscribers

People subscribed via source and target branches

to all changes: