From 0412f70724475274f684ac93107d46e89cb4ad4f Mon Sep 17 00:00:00 2001 From: Shane Tomlinson Date: Fri, 20 May 2016 15:01:28 +0100 Subject: [PATCH 1/2] feat(mailer): Add the `write-to-disk.js` script. --- Gruntfile.js | 2 +- scripts/write-to-disk.js | 121 +++++++++++++++++++++++++++++++++++++++ tasks/eslint.js | 2 +- 3 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 scripts/write-to-disk.js diff --git a/Gruntfile.js b/Gruntfile.js index aa965626..726245de 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -79,7 +79,7 @@ module.exports = function (grunt) { * Gruntfile causes an error and should contain no strings * bin/server.js extracts "/", so it is excluded. */ - exclude: /(node_modules|test|Gruntfile|bin)/, + exclude: /(node_modules|test|Gruntfile|bin|scripts)/, 'output-dir': __dirname, 'output': 'server.pot', 'join-existing': true, diff --git a/scripts/write-to-disk.js b/scripts/write-to-disk.js new file mode 100644 index 00000000..3e8c6736 --- /dev/null +++ b/scripts/write-to-disk.js @@ -0,0 +1,121 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Write emails to disk. Output is written to ./.mail_output/.html + * + * Usage: + * node ./scripts/write-to-disk.js + * + * Where is one of: + * all + * newDeviceLoginEmail + * passwordChangedEmail + * passwordResetEmail + * passwordResetRequiredEmail + * postVerifyEmail + * recoveryEmail + * suspiciousLocationEmail + * unlockEmail + * verificationReminderEmail:first + * verificationReminderEmail:second + * verifyEmail + * verifyLoginEmail + * + * Emails that are written to disk can be previewed in Firefox + * to give a rough idea of how they would render in real life. + */ + +var P = require('bluebird') +var config = require('../config') +var createMailer = require('../index') +var fs = require('fs') +var log = require('../log')('server') +var path = require('path') + +var OUTPUT_DIRECTORY = path.join(__dirname, '..', '.mail_output') + +function getEmailOutputPath(subject, extension) { + var outputFilename = subject.replace(/\s+/g, '_') + '.' + extension + return path.join(OUTPUT_DIRECTORY, outputFilename) +} + +var mailSender = { + sendMail: function (emailConfig, done) { + var htmlOutputPath = getEmailOutputPath(emailConfig.subject, 'html') + fs.writeFileSync(htmlOutputPath, emailConfig.html) + + var textOutputPath = getEmailOutputPath(emailConfig.subject, 'txt') + fs.writeFileSync(textOutputPath, emailConfig.text) + + done(null) + } +} + + +var MESSAGE_TYPES = [ + 'newDeviceLoginEmail', + 'passwordChangedEmail', + 'passwordResetEmail', + 'passwordResetRequiredEmail', + 'postVerifyEmail', + 'recoveryEmail', + 'suspiciousLocationEmail', + 'unlockEmail', + 'verificationReminderEmail:first', + 'verificationReminderEmail:second', + 'verifyEmail', + 'verifyLoginEmail' +] + +var messageToSend = process.argv[2] || '' +if (MESSAGE_TYPES.indexOf(messageToSend) === -1 && messageToSend !== 'all') { + log.error('invalid message name' + messageToSend) + process.exit(1) +} + +var messagesToSend +if (messageToSend === 'all') { + messagesToSend = MESSAGE_TYPES +} else { + messagesToSend = [messageToSend] +} + +createMailer(log, config.getProperties(), mailSender) + .then((mailer) => { + return sendMails(mailer, messagesToSend) + }) + .then(() => { + log.info('done') + }) + +function sendMails(mailer, messagesToSend) { + return P.all(messagesToSend.map(sendMail.bind(null, mailer))) +} + +function sendMail(mailer, messageToSend) { + var parts = messageToSend.split(':') + var messageType = parts[0] + var messageSubType = parts[1] + + var message = { + acceptLanguage: 'en', + code: 'ae35999f861ffc81d594034eb4560af8', + email: 'testuser@testuser.com', + locations: [], + redirectTo: 'https://redirect.com/', + resume: 'eyJjYW1wYWlnbiI6bnVsbCwiZW50cnlwb2ludCI6bnVsbCwiZmxvd0lkIjoiM2Q1ODZiNzY4Mzc2NGJhOWFiNzhkMzMxMTdjZDU4Y2RmYjk3Mzk5MWU5NTk0NjgxODBlMDUyMmY2MThhNmEyMSIsInJlc2V0UGFzc3dvcmRDb25maXJtIjp0cnVlLCJ1bmlxdWVVc2VySWQiOiI1ODNkOGFlYS00NzU3LTRiZTQtYWJlNC0wZWQ2NWZhY2Y2YWQiLCJ1dG1DYW1wYWlnbiI6bnVsbCwidXRtQ29udGVudCI6bnVsbCwidXRtTWVkaXVtIjpudWxsLCJ1dG1Tb3VyY2UiOm51bGwsInV0bVRlcm0iOm51bGx9', + service: 'sync', + token: '47b22cd271963448cf36da95cccfcfb342b5693d66f58aa635f9a95579431002', + type: messageSubType, + uaBrowser: 'Firefox', + uaBrowserVersion: '47', + uaOS: 'Mac OSX', + uaOSVersion: '10.11', + uid: '6510cb04abd742c6b3e4abefc7e39c9f' + } + + return mailer[messageType](message) +} + diff --git a/tasks/eslint.js b/tasks/eslint.js index 64e8a5d7..4fcf8352 100644 --- a/tasks/eslint.js +++ b/tasks/eslint.js @@ -10,7 +10,7 @@ module.exports = function (grunt) { eslintrc: '.eslintrc' }, app: [ - '*.js', 'bin/*.js', 'tasks/*.js', 'templates/*.js', 'test/**/*.js' + '*.js', 'bin/*.js', 'tasks/*.js', 'templates/*.js', 'test/**/*.js', 'scripts/**/*.js' ] }) } From 4a30c795d256259220ebc73ff6c0207c5de5ceb5 Mon Sep 17 00:00:00 2001 From: Shane Tomlinson Date: Wed, 25 May 2016 10:10:27 +0100 Subject: [PATCH 2/2] fix(script): Cleanup of write-to-disk.js based on @philbooth's feedback. * Include mkdirp so output dir is automatically created. * Generate the list of acceptable mail types from the mailer. --- .gitignore | 1 + package.json | 1 + scripts/write-to-disk.js | 87 ++++++++++++++++++++++++---------------- 3 files changed, 54 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 1b120853..d867aeef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules server.pot *.log +.mail_output diff --git a/package.json b/package.json index c9f292f5..6823b0c9 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "husky": "0.10.2", "jsxgettext-recursive": "0.0.5", "load-grunt-tasks": "3.3.0", + "mkdirp": "0.5.1", "proxyquire": "1.7.4", "simplesmtp": "0.3.32", "sinon": "1.17.3", diff --git a/scripts/write-to-disk.js b/scripts/write-to-disk.js index 3e8c6736..23f26942 100644 --- a/scripts/write-to-disk.js +++ b/scripts/write-to-disk.js @@ -32,14 +32,12 @@ var config = require('../config') var createMailer = require('../index') var fs = require('fs') var log = require('../log')('server') +var mkdirp = require('mkdirp') var path = require('path') var OUTPUT_DIRECTORY = path.join(__dirname, '..', '.mail_output') -function getEmailOutputPath(subject, extension) { - var outputFilename = subject.replace(/\s+/g, '_') + '.' + extension - return path.join(OUTPUT_DIRECTORY, outputFilename) -} +var messageToSend = process.argv[2] || '' var mailSender = { sendMail: function (emailConfig, done) { @@ -50,46 +48,30 @@ var mailSender = { fs.writeFileSync(textOutputPath, emailConfig.text) done(null) - } + }, + + close: function () {} } -var MESSAGE_TYPES = [ - 'newDeviceLoginEmail', - 'passwordChangedEmail', - 'passwordResetEmail', - 'passwordResetRequiredEmail', - 'postVerifyEmail', - 'recoveryEmail', - 'suspiciousLocationEmail', - 'unlockEmail', - 'verificationReminderEmail:first', - 'verificationReminderEmail:second', - 'verifyEmail', - 'verifyLoginEmail' -] - -var messageToSend = process.argv[2] || '' -if (MESSAGE_TYPES.indexOf(messageToSend) === -1 && messageToSend !== 'all') { - log.error('invalid message name' + messageToSend) - process.exit(1) -} - -var messagesToSend -if (messageToSend === 'all') { - messagesToSend = MESSAGE_TYPES -} else { - messagesToSend = [messageToSend] -} - createMailer(log, config.getProperties(), mailSender) .then((mailer) => { - return sendMails(mailer, messagesToSend) + checkMessageType(mailer, messageToSend) + + ensureTargetDirectoryExists() + + return sendMails(mailer, getMessageTypesToWrite(mailer, messageToSend)) }) .then(() => { - log.info('done') + console.info('done') //eslint-disable-line no-console }) +function getEmailOutputPath(subject, extension) { + var outputFilename = subject.replace(/\s+/g, '_') + '.' + extension + return path.join(OUTPUT_DIRECTORY, outputFilename) +} + + function sendMails(mailer, messagesToSend) { return P.all(messagesToSend.map(sendMail.bind(null, mailer))) } @@ -119,3 +101,38 @@ function sendMail(mailer, messageToSend) { return mailer[messageType](message) } +function checkMessageType(mailer, messageToSend) { + var messageTypes = getMailerMessageTypes(mailer) + messageTypes.push('all') + + if (messageTypes.indexOf(messageToSend) === -1) { + console.error('invalid message name: `' + messageToSend + '`\n' + //eslint-disable-line no-console + 'choose from: ' + messageTypes.join(', ')) + process.exit(1) + } +} + + +function getMailerMessageTypes(mailer) { + var messageTypes = [] + + for (var key in mailer) { + if (typeof mailer[key] === 'function' && ! /^_/.test(key) && /Email$/.test(key)) { + messageTypes.push(key) + } + } + + return messageTypes.sort() +} + +function getMessageTypesToWrite(mailer, messageToSend) { + if (messageToSend === 'all') { + return getMailerMessageTypes(mailer) + } else { + return [messageToSend] + } +} + +function ensureTargetDirectoryExists() { + mkdirp.sync(OUTPUT_DIRECTORY) +}