From 7fc22fd41d4f8fef1fd03ccdab14014a73ca1e5a Mon Sep 17 00:00:00 2001 From: nicola Date: Fri, 6 May 2016 10:47:05 -0400 Subject: [PATCH 01/11] using node mailer as email service --- lib/create-app.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/create-app.js b/lib/create-app.js index 66a7ddd14..ea9d7ab6f 100644 --- a/lib/create-app.js +++ b/lib/create-app.js @@ -10,6 +10,8 @@ var proxy = require('./handlers/proxy') var IdentityProvider = require('./identity-provider') var vhost = require('vhost') var path = require('path') +var nodemailer = require('nodemailer') + var corsSettings = cors({ methods: [ 'OPTIONS', 'HEAD', 'GET', 'PATCH', 'POST', 'PUT', 'DELETE' @@ -42,6 +44,10 @@ function createApp (argv) { // Setting options as local variable app.locals.ldp = ldp + if (argv.email) { + app.locals.email = nodemailer.createTransport(argv.email) + } + var sessionSettings = { secret: ldp.secret || uuid.v1(), saveUninitialized: false, From 1357116a2a481a7273841f5f1d355676fc985129 Mon Sep 17 00:00:00 2001 From: nicola Date: Fri, 6 May 2016 10:56:46 -0400 Subject: [PATCH 02/11] update to node v6 and adding email --- .travis.yml | 4 ++-- lib/create-app.js | 6 +++--- lib/email-service.js | 19 +++++++++++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 lib/email-service.js diff --git a/.travis.yml b/.travis.yml index 1325ca428..32e58f9eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ sudo: false language: node_js node_js: - - "4.0" - - "5.0" + - "6.0" + cache: directories: - node_modules diff --git a/lib/create-app.js b/lib/create-app.js index ea9d7ab6f..5783c121c 100644 --- a/lib/create-app.js +++ b/lib/create-app.js @@ -10,7 +10,7 @@ var proxy = require('./handlers/proxy') var IdentityProvider = require('./identity-provider') var vhost = require('vhost') var path = require('path') -var nodemailer = require('nodemailer') +var EmailService = require('./email-service') var corsSettings = cors({ methods: [ @@ -22,7 +22,7 @@ var corsSettings = cors({ origin: true }) -function createApp (argv) { +function createApp (argv = {}) { var ldp = new LDP(argv) var app = express() @@ -45,7 +45,7 @@ function createApp (argv) { app.locals.ldp = ldp if (argv.email) { - app.locals.email = nodemailer.createTransport(argv.email) + app.locals.email = new EmailService(argv.email) } var sessionSettings = { diff --git a/lib/email-service.js b/lib/email-service.js new file mode 100644 index 000000000..7fa2058d2 --- /dev/null +++ b/lib/email-service.js @@ -0,0 +1,19 @@ +'use strict' + +const nodemailer = require('nodemailer') +const extend = require('extend') + +class EmailService { + constructor (settings = {}) { + // This reflects nodemailer string option, we allow it + if (typeof settings !== 'string') { + settings = extend(settings, {secure: true}) + } + this.mailer = nodemailer.createTransport(settings) + } + sendEmail (email, callback) { + this.mailer.sendEmail(email, callback) + } +} + +module.exports = EmailService From d2ec595fa1956c2a36dafd65e607a84d6db665fe Mon Sep 17 00:00:00 2001 From: nicola Date: Fri, 6 May 2016 11:17:05 -0400 Subject: [PATCH 03/11] adding initial test for email --- lib/email-service.js | 5 +++-- package.json | 2 ++ test/email-service.js | 31 +++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 test/email-service.js diff --git a/lib/email-service.js b/lib/email-service.js index 7fa2058d2..bacd19bae 100644 --- a/lib/email-service.js +++ b/lib/email-service.js @@ -11,8 +11,9 @@ class EmailService { } this.mailer = nodemailer.createTransport(settings) } - sendEmail (email, callback) { - this.mailer.sendEmail(email, callback) + sendMail (email, callback) { + console.log(this.mailer) + this.mailer.sendMail(email, callback) } } diff --git a/package.json b/package.json index c7008e0fd..902daf3aa 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "negotiator": "^0.6.0", "node-forge": "^0.6.38", "node-uuid": "^1.4.3", + "nodemailer": "^2.3.2", "nomnom": "^1.8.1", "rdflib": "^0.6.1", "request": "^2.72.0", @@ -60,6 +61,7 @@ "mocha": "^2.2.5", "nock": "^7.0.2", "rsvp": "^3.1.0", + "sinon": "^1.17.4", "standard": "^6.0.4", "supertest": "^1.0.1" }, diff --git a/test/email-service.js b/test/email-service.js new file mode 100644 index 000000000..e2a7180cc --- /dev/null +++ b/test/email-service.js @@ -0,0 +1,31 @@ +const EmailService = require('../lib/email-service') +const sinon = require('sinon') +const expect = require('chai').expect + +describe('Email Service', function () { + let email, transport + + beforeEach(() => { + transport = { + name: 'testsend', + version: '1', + send: function (data, callback) { + callback(); + }, + logger: false + } + email = new EmailService(transport) + }) + + it('should send emails', (done) => { + sinon.stub(transport, 'send').yields(null, 'bep bop') + + email.sendMail({ + subject: 'test' + }, function (err, info) { + expect(err).to.not.exist; + expect(info).to.equal('bep bop') + done() + }) + }) +}) From f893bc4c9ccb2ed97d446fe3357120b9f19fb452 Mon Sep 17 00:00:00 2001 From: nicola Date: Fri, 6 May 2016 11:28:36 -0400 Subject: [PATCH 04/11] removing extra semicolons --- test/email-service.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/email-service.js b/test/email-service.js index e2a7180cc..a2a8d9f24 100644 --- a/test/email-service.js +++ b/test/email-service.js @@ -10,7 +10,7 @@ describe('Email Service', function () { name: 'testsend', version: '1', send: function (data, callback) { - callback(); + callback() }, logger: false } @@ -23,7 +23,7 @@ describe('Email Service', function () { email.sendMail({ subject: 'test' }, function (err, info) { - expect(err).to.not.exist; + expect(err).to.not.exist expect(info).to.equal('bep bop') done() }) From f482c6fbd698bde5582476a4a26a33bacce2d203 Mon Sep 17 00:00:00 2001 From: nicola Date: Fri, 6 May 2016 16:52:52 -0400 Subject: [PATCH 05/11] adding command line for email --- bin/lib/init.js | 17 ++++++++++++++ bin/lib/options.js | 48 ++++++++++++++++++++++++++++++++++++++++ bin/lib/start.js | 1 + lib/email-service.js | 6 +++++ lib/identity-provider.js | 16 ++++++++++++++ 5 files changed, 88 insertions(+) diff --git a/bin/lib/init.js b/bin/lib/init.js index 4ec4a4725..ea1b10583 100644 --- a/bin/lib/init.js +++ b/bin/lib/init.js @@ -31,6 +31,23 @@ module.exports = function (program) { // Prompt to the user inquirer.prompt(questions) .then((answers) => { + // setting email + if (answers.useEmail) { + answers.email = { + host: answers['email-host'], + port: answers['email-port'], + secure: true, + auth: { + user: answers['email-auth-user'], + pass: answers['email-auth-pass'] + } + } + delete answers['email-host'] + delete answers['email-port'] + delete answers['email-auth-user'] + delete answers['email-auth-pass'] + } + // clean answers Object.keys(answers).forEach((answer) => { if (answer.startsWith('use')) { diff --git a/bin/lib/options.js b/bin/lib/options.js index c7fbfc02d..f4094eb8b 100644 --- a/bin/lib/options.js +++ b/bin/lib/options.js @@ -162,6 +162,54 @@ module.exports = [ help: 'Enforce same origin policy in the ACL', flag: true, prompt: true + }, + { + name: 'useEmail', + help: 'Do you want to set up an email service?', + flag: true, + prompt: true, + default: true + }, + { + name: 'email-host', + help: 'Host of your email service', + prompt: true, + default: 'smtp.gmail.com', + when: (answers) => { + return answers.useEmail + } + }, + { + name: 'email-port', + help: 'Port of your email service', + prompt: true, + default: '465', + when: (answers) => { + return answers.useEmail + } + }, + { + name: 'email-auth-user', + help: 'User of your email service', + prompt: true, + when: (answers) => { + return answers.useEmail + }, + validate: (value) => { + if (!value || value === '') { + return 'You must enter this information' + } + return true + } + }, + { + name: 'email-auth-pass', + help: 'Password of your email service', + type: 'password', + prompt: true, + when: (answers) => { + return answers.useEmail + } } ] diff --git a/bin/lib/start.js b/bin/lib/start.js index ce4877c83..bd86695ee 100644 --- a/bin/lib/start.js +++ b/bin/lib/start.js @@ -44,6 +44,7 @@ module.exports = function (program) { } function bin (argv) { + // Set up --no-* argv.live = !argv.noLive diff --git a/lib/email-service.js b/lib/email-service.js index bacd19bae..06d0029ed 100644 --- a/lib/email-service.js +++ b/lib/email-service.js @@ -10,6 +10,12 @@ class EmailService { settings = extend(settings, {secure: true}) } this.mailer = nodemailer.createTransport(settings) + + if (settings.sender) { + this.sender = settings.sender + } else if (settings.host) { + this.sender = `no-reply@${settings.host}` + } } sendMail (email, callback) { console.log(this.mailer) diff --git a/lib/identity-provider.js b/lib/identity-provider.js index ff09e1be6..dd7bb2552 100644 --- a/lib/identity-provider.js +++ b/lib/identity-provider.js @@ -508,6 +508,7 @@ IdentityProvider.prototype.post = function (req, res, next) { } var self = this + var email = req.app.locals.email var options = req.body options.host = req.get('host') options.firstUser = res.locals.firstUser @@ -531,8 +532,23 @@ IdentityProvider.prototype.post = function (req, res, next) { function (newCert, callback) { cert = newCert self.create(options, cert, callback) + }, + function (callback) { + if (email) { + email.sendEmail({ + from: `"no-reply" <${email.sender}>`, // sender address + to: options.email, + subject: 'Account created', + text: 'Your account has been created', + html: 'Your account has been created' + }, callback) + } else { + callback() + } } ], function (err) { + // TODO at the moment this will collect the email error + // maybe we don't need to do so if (err) { err.status = err.status || 500 debug('Error creating ' + options.user + ': ' + err.message) From c7af9d84323ed40c6118f629a2023f60a5fe0f52 Mon Sep 17 00:00:00 2001 From: nicola Date: Fri, 6 May 2016 16:55:16 -0400 Subject: [PATCH 06/11] adding support to email flags --- bin/lib/start.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/bin/lib/start.js b/bin/lib/start.js index bd86695ee..17ec0fd19 100644 --- a/bin/lib/start.js +++ b/bin/lib/start.js @@ -45,6 +45,22 @@ module.exports = function (program) { function bin (argv) { + if (!argv.email) { + argv.email = { + host: answers['emailHost'], + port: answers['emailPort'], + secure: true, + auth: { + user: answers['emailAuthUser'], + pass: answers['emailAuthPass'] + } + } + delete answers['emailHost'] + delete answers['emailPort'] + delete answers['emailAuthUser'] + delete answers['emailAuthPass'] + } + // Set up --no-* argv.live = !argv.noLive From 30c4d65717fd5920b77a4179157e099d5cd0424f Mon Sep 17 00:00:00 2001 From: nicola Date: Fri, 6 May 2016 17:09:06 -0400 Subject: [PATCH 07/11] fixing the error in start --- bin/lib/start.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bin/lib/start.js b/bin/lib/start.js index 17ec0fd19..feb81314f 100644 --- a/bin/lib/start.js +++ b/bin/lib/start.js @@ -47,18 +47,18 @@ function bin (argv) { if (!argv.email) { argv.email = { - host: answers['emailHost'], - port: answers['emailPort'], + host: argv['emailHost'], + port: argv['emailPort'], secure: true, auth: { - user: answers['emailAuthUser'], - pass: answers['emailAuthPass'] + user: argv['emailAuthUser'], + pass: argv['emailAuthPass'] } } - delete answers['emailHost'] - delete answers['emailPort'] - delete answers['emailAuthUser'] - delete answers['emailAuthPass'] + delete argv['emailHost'] + delete argv['emailPort'] + delete argv['emailAuthUser'] + delete argv['emailAuthPass'] } // Set up --no-* From f54a96c71c36d3df5553e9979a263d5addbd4723 Mon Sep 17 00:00:00 2001 From: nicola Date: Fri, 6 May 2016 17:09:39 -0400 Subject: [PATCH 08/11] removing extra space --- bin/lib/start.js | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/lib/start.js b/bin/lib/start.js index feb81314f..9832c7511 100644 --- a/bin/lib/start.js +++ b/bin/lib/start.js @@ -44,7 +44,6 @@ module.exports = function (program) { } function bin (argv) { - if (!argv.email) { argv.email = { host: argv['emailHost'], From ccb50d9be289595eb3ac4c008795dbbe284965b6 Mon Sep 17 00:00:00 2001 From: nicola Date: Fri, 6 May 2016 17:12:43 -0400 Subject: [PATCH 09/11] adding resolving path of root --- bin/lib/options.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bin/lib/options.js b/bin/lib/options.js index f4094eb8b..a74da1ab1 100644 --- a/bin/lib/options.js +++ b/bin/lib/options.js @@ -1,4 +1,5 @@ const fs = require('fs') +const path = require('path') module.exports = [ // { @@ -11,7 +12,8 @@ module.exports = [ help: 'Root folder to serve (defaut: \'./\')', question: 'Path to the folder you want to serve. Default is', default: './', - prompt: true + prompt: true, + filter: (value) => path.resolve(value) }, { name: 'port', From cb7dd2ea86fcfdceeaaa48c5a6a87cbf23f0df64 Mon Sep 17 00:00:00 2001 From: nicola Date: Mon, 9 May 2016 11:58:27 -0400 Subject: [PATCH 10/11] do not start email if argvs not passed --- lib/create-app.js | 2 +- lib/email-service.js | 1 - lib/identity-provider.js | 11 ++++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/create-app.js b/lib/create-app.js index 5783c121c..4909077f7 100644 --- a/lib/create-app.js +++ b/lib/create-app.js @@ -44,7 +44,7 @@ function createApp (argv = {}) { // Setting options as local variable app.locals.ldp = ldp - if (argv.email) { + if (argv.email && argv.email.host) { app.locals.email = new EmailService(argv.email) } diff --git a/lib/email-service.js b/lib/email-service.js index 06d0029ed..510841c85 100644 --- a/lib/email-service.js +++ b/lib/email-service.js @@ -18,7 +18,6 @@ class EmailService { } } sendMail (email, callback) { - console.log(this.mailer) this.mailer.sendMail(email, callback) } } diff --git a/lib/identity-provider.js b/lib/identity-provider.js index dd7bb2552..df401268d 100644 --- a/lib/identity-provider.js +++ b/lib/identity-provider.js @@ -534,21 +534,22 @@ IdentityProvider.prototype.post = function (req, res, next) { self.create(options, cert, callback) }, function (callback) { - if (email) { - email.sendEmail({ + if (email && options.email) { + email.sendMail({ from: `"no-reply" <${email.sender}>`, // sender address to: options.email, subject: 'Account created', text: 'Your account has been created', html: 'Your account has been created' - }, callback) + }, (err) => { + debug('Error sending email', err) + callback() + }) } else { callback() } } ], function (err) { - // TODO at the moment this will collect the email error - // maybe we don't need to do so if (err) { err.status = err.status || 500 debug('Error creating ' + options.user + ': ' + err.message) From b94b36ecd337b4e73dc88d94fef596882ce4dfd6 Mon Sep 17 00:00:00 2001 From: nicola Date: Mon, 9 May 2016 12:06:31 -0400 Subject: [PATCH 11/11] adding email helper in README --- README.md | 4 ++++ lib/identity-provider.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b554e4912..47b2c25f1 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,10 @@ $ solid --allow-signup --port 8443 --cert /path/to/cert --key /path/to/key --roo Your users will have a dedicated folder under `./accounts`. Also, your root domain's website will be in `./accounts/yourdomain.tld`. New users can create accounts on `/accounts/new` and create new certificates on `/accounts/cert`. An easy-to-use sign-up tool is found on `/accounts`. +##### How can send emails to my users with my Gmail? + +> To use Gmail you may need to configure ["Allow Less Secure Apps"](https://www.google.com/settings/security/lesssecureapps) in your Gmail account unless you are using 2FA in which case you would have to create an [Application Specific](https://security.google.com/settings/security/apppasswords) password. You also may need to unlock your account with ["Allow access to your Google account"](https://accounts.google.com/DisplayUnlockCaptcha) to use SMTP. + ### Run the Linked Data Platform (intermediate) If you don't want WebID Authentication and Web Access Control, you can run a simple Linked Data Platform. diff --git a/lib/identity-provider.js b/lib/identity-provider.js index df401268d..0570ca4a1 100644 --- a/lib/identity-provider.js +++ b/lib/identity-provider.js @@ -542,7 +542,7 @@ IdentityProvider.prototype.post = function (req, res, next) { text: 'Your account has been created', html: 'Your account has been created' }, (err) => { - debug('Error sending email', err) + if (err) debug('Error sending email', err) callback() }) } else {