diff --git a/package.json b/package.json index 44e0d44b..ce86ed1b 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "lodash": "^4.13.1", "morgan": "^1.6.1", "mysql": "^2.9.0", - "nodemailer": "^1.4.0", + "nodemailer": "^4.1.1", "prom-client": "^10.0.2", "proxy-addr": "^1.1.4", "pug": "^2.0.0-beta3", diff --git a/src/configuration/emailconfig.js b/src/configuration/emailconfig.js new file mode 100644 index 00000000..0a62df6e --- /dev/null +++ b/src/configuration/emailconfig.js @@ -0,0 +1,29 @@ +class EmailConfig { + constructor(config) { + this.config = config; + } + + getPasswordReset() { + const reset = this.config['password-reset']; + + return { + getHTML() { + return reset['html-template']; + }, + + getText() { + return reset['text-template']; + }, + + getFrom() { + return reset['from']; + }, + + getSubject() { + return reset['subject']; + } + }; + } +} + +export { EmailConfig }; diff --git a/src/controller/email.js b/src/controller/email.js new file mode 100644 index 00000000..b3506174 --- /dev/null +++ b/src/controller/email.js @@ -0,0 +1,31 @@ +class EmailController { + constructor(mailer, config) { + this.mailer = mailer; + this.config = config; + } + + async sendPasswordReset(params = {}) { + const { address, username, url } = params; + + const resetConfig = this.config.getPasswordReset(); + + const html = resetConfig.getHTML() + .replace(/\$user\$/g, username) + .replace(/\$url\$/g, url); + const text = resetConfig.getText() + .replace(/\$user\$/g, username) + .replace(/\$url\$/g, url); + + const result = await this.mailer.sendMail({ + from: resetConfig.getFrom(), + to: `${username} <${address}>`, + subject: resetConfig.getSubject(), + html, + text + }); + + return result; + } +} + +export { EmailController }; diff --git a/test/controller/email.js b/test/controller/email.js new file mode 100644 index 00000000..1f9ad494 --- /dev/null +++ b/test/controller/email.js @@ -0,0 +1,50 @@ +const assert = require('assert'); +const { createTransport } = require('nodemailer'); +const { EmailController } = require('../../lib/controller/email'); +const { EmailConfig } = require('../../lib/configuration/emailconfig'); + +describe('EmailController', () => { + describe('sendPasswordReset', () => { + it('sends a password reset email', () => { + const mailer = createTransport({ + jsonTransport: true + }); + const config = new EmailConfig({ + 'password-reset': { + from: 'Test ', + subject: 'Password Reset', + 'html-template': 'Reset here $user$', + 'text-template': 'Text is better than HTML $user$ $url$' + } + }); + + const controller = new EmailController(mailer, config); + + return controller.sendPasswordReset({ + address: 'some-user@example.com', + username: 'SomeUser', + url: 'http://localhost/password-reset/blah' + }).then(info => { + const sentMessage = JSON.parse(info.message); + + assert.strictEqual(sentMessage.subject, 'Password Reset'); + assert.deepStrictEqual( + sentMessage.from, + { name: 'Test', address: 'test@example.com' } + ); + assert.deepStrictEqual( + sentMessage.to, + [{ name: 'SomeUser', address: 'some-user@example.com' }] + ); + assert.strictEqual( + sentMessage.html, + 'Reset here SomeUser' + ); + assert.strictEqual( + sentMessage.text, + 'Text is better than HTML SomeUser http://localhost/password-reset/blah' + ); + }); + }); + }); +});