From 7a85b92a09fd0cd6379612bc6d0e9e07985c9e9d Mon Sep 17 00:00:00 2001 From: Zoltan Olah Date: Fri, 24 Jan 2014 12:21:39 -0800 Subject: [PATCH 1/3] Optionally pass in 'html' template function to Accounts email templates --- docs/client/api.html | 4 ++- packages/accounts-password/password_server.js | 34 +++++++++++++++---- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/docs/client/api.html b/docs/client/api.html index 2b49d7b8a5..43b2340c3b 100644 --- a/docs/client/api.html +++ b/docs/client/api.html @@ -1953,7 +1953,7 @@ To customize the contents of the email, see {{> api_box accounts_emailTemplates}} -This is an `Object` with several fields that are used to generate text +This is an `Object` with several fields that are used to generate text/html for the emails sent by `sendResetPasswordEmail`, `sendEnrollmentEmail`, and `sendVerificationEmail`. @@ -1970,6 +1970,8 @@ Override fields of the object by assigning to them: a `String` for the subject line of a reset password email. - `resetPassword.text`: A `Function` that takes a user object and a url, and returns the body text for a reset password email. + - `resetPassword.html`: An optional `Function` that takes a user object and a + url, and returns the body html for a reset password email. - `enrollAccount`: Same as `resetPassword`, but for initial password setup for new accounts. - `verifyEmail`: Same as `resetPassword`, but for verifying the users email diff --git a/packages/accounts-password/password_server.js b/packages/accounts-password/password_server.js index 6ea1526125..c011f81d27 100644 --- a/packages/accounts-password/password_server.js +++ b/packages/accounts-password/password_server.js @@ -264,11 +264,19 @@ Accounts.sendResetPasswordEmail = function (userId, email) { }}); var resetPasswordUrl = Accounts.urls.resetPassword(token); - Email.send({ + + var options = { to: email, from: Accounts.emailTemplates.from, subject: Accounts.emailTemplates.resetPassword.subject(user), - text: Accounts.emailTemplates.resetPassword.text(user, resetPasswordUrl)}); + text: Accounts.emailTemplates.resetPassword.text(user, resetPasswordUrl) + }; + + if (typeof Accounts.emailTemplates.resetPassword.html === 'function') + options.html = + Accounts.emailTemplates.resetPassword.html(user, resetPasswordUrl); + + Email.send(options); }; // send the user an email informing them that their account was created, with @@ -305,12 +313,19 @@ Accounts.sendEnrollmentEmail = function (userId, email) { }}); var enrollAccountUrl = Accounts.urls.enrollAccount(token); - Email.send({ + + var options = { to: email, from: Accounts.emailTemplates.from, subject: Accounts.emailTemplates.enrollAccount.subject(user), text: Accounts.emailTemplates.enrollAccount.text(user, enrollAccountUrl) - }); + }; + + if (typeof Accounts.emailTemplates.enrollAccount.html === 'function') + options.html = + Accounts.emailTemplates.enrollAccount.html(user, enrollAccountUrl); + + Email.send(options); }; @@ -418,12 +433,19 @@ Accounts.sendVerificationEmail = function (userId, address) { {$push: {'services.email.verificationTokens': tokenRecord}}); var verifyEmailUrl = Accounts.urls.verifyEmail(tokenRecord.token); - Email.send({ + + var options = { to: address, from: Accounts.emailTemplates.from, subject: Accounts.emailTemplates.verifyEmail.subject(user), text: Accounts.emailTemplates.verifyEmail.text(user, verifyEmailUrl) - }); + }; + + if (typeof Accounts.emailTemplates.verifyEmail.html === 'function') + options.html = + Accounts.emailTemplates.verifyEmail.html(user, verifyEmailUrl); + + Email.send(options); }; // Take token from sendVerificationEmail, mark the email as verified, From 0b9368e6ce2c1fb39d637ed6ece022d68db22496 Mon Sep 17 00:00:00 2001 From: Zoltan Olah Date: Thu, 6 Mar 2014 17:10:46 -0800 Subject: [PATCH 2/3] Tests for the html option to email templates --- packages/accounts-password/email_tests.js | 21 +++++++++++-------- .../accounts-password/email_tests_setup.js | 11 ++++++++-- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/packages/accounts-password/email_tests.js b/packages/accounts-password/email_tests.js index 61bd7458e2..bb4a5df990 100644 --- a/packages/accounts-password/email_tests.js +++ b/packages/accounts-password/email_tests.js @@ -31,12 +31,13 @@ testAsyncMulti("accounts emails - reset password flow", [ test.equal(error, undefined); test.notEqual(result, undefined); test.equal(result.length, 2); // the first is the email verification - var content = result[1]; + var options = result[1]; - var match = content.match( - new RegExp(Meteor.absoluteUrl() + "#/reset-password/(\\S*)")); + var re = new RegExp(Meteor.absoluteUrl() + "#/reset-password/(\\S*)") + var match = options.text.match(re); test.isTrue(match); resetPasswordToken = match[1]; + test.isTrue(options.html.match(re)); })); }, function (test, expect) { @@ -71,12 +72,13 @@ var getVerifyEmailToken = function (email, test, expect) { test.equal(error, undefined); test.notEqual(result, undefined); test.equal(result.length, 1); - var content = result[0]; + var options = result[0]; - var match = content.match( - new RegExp(Meteor.absoluteUrl() + "#/verify-email/(\\S*)")); + var re = new RegExp(Meteor.absoluteUrl() + "#/verify-email/(\\S*)"); + var match = options.text.match(re); test.isTrue(match); verifyEmailToken = match[1]; + test.isTrue(options.html.match(re)); })); }; @@ -164,12 +166,13 @@ var getEnrollAccountToken = function (email, test, expect) { test.equal(error, undefined); test.notEqual(result, undefined); test.equal(result.length, 1); - var content = result[0]; + var options = result[0]; - var match = content.match( - new RegExp(Meteor.absoluteUrl() + "#/enroll-account/(\\S*)")); + var re = new RegExp(Meteor.absoluteUrl() + "#/enroll-account/(\\S*)") + var match = options.text.match(re); test.isTrue(match); enrollAccountToken = match[1]; + test.isTrue(options.html.match(re)); })); }; diff --git a/packages/accounts-password/email_tests_setup.js b/packages/accounts-password/email_tests_setup.js index 30a542aa12..6c21b4d452 100644 --- a/packages/accounts-password/email_tests_setup.js +++ b/packages/accounts-password/email_tests_setup.js @@ -3,7 +3,14 @@ // the string "intercept", storing them in an array that can then // be retrieved using the getInterceptedEmails method // -var interceptedEmails = {}; // (email address) -> (array of contents) +var interceptedEmails = {}; // (email address) -> (array of options) + +// add html email templates that just contain the url +Accounts.emailTemplates.resetPassword.html = + Accounts.emailTemplates.enrollAccount.html = + Accounts.emailTemplates.verifyEmail.html = function (user, url) { + return url; + }; EmailTest.hookSend(function (options) { var to = options.to; @@ -13,7 +20,7 @@ EmailTest.hookSend(function (options) { if (!interceptedEmails[to]) interceptedEmails[to] = []; - interceptedEmails[to].push(options.text); + interceptedEmails[to].push(options); return false; // skip sending } }); From 6f6528143dc02d2b64ace1605be52adefde39389 Mon Sep 17 00:00:00 2001 From: Nick Martin Date: Wed, 12 Mar 2014 17:49:18 -0700 Subject: [PATCH 3/3] history note for #1785 --- History.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/History.md b/History.md index 5a08e6d332..55efed0461 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,8 @@ attempts, logging an audit trail, account lockout flags, etc. See: http://docs.meteor.com/#accounts_validLoginAttempt #1815 +* Add support for HTML email in `Accounts.emailTemplates`. #1785 + * Use "faye-websocket" (0.7.2) npm module instead of "websocket" (1.0.8) for server-to-server DDP.