migrate utils to v3, uprade nodemailer

This commit is contained in:
Matteo Pagliazzi
2015-11-13 16:09:51 +01:00
parent 9c8d4c383f
commit b315d10c79
17 changed files with 192 additions and 16 deletions

View File

@@ -28,7 +28,6 @@
"no-new": 2,
"no-octal-escape": 2,
"no-octal": 2,
"no-param-reassign": 2,
"no-process-env": 2,
"no-proto": 2,
"no-implied-eval": 2,

View File

@@ -12,10 +12,10 @@
"babel": "^5.5.4",
"babelify": "^7.2.0",
"body-parser": "^1.14.1",
"compression": "^1.6.0",
"bower": "~1.3.12",
"browserify": "~12.0.1",
"coffee-script": "1.6.x",
"compression": "^1.6.0",
"connect-ratelimit": "0.0.7",
"cookie-parser": "^1.4.0",
"cookie-session": "^1.2.0",
@@ -64,7 +64,7 @@
"nconf": "~0.8.2",
"newrelic": "~1.23.0",
"nib": "~1.0.1",
"nodemailer": "~0.5.2",
"nodemailer": "^1.9.0",
"pageres": "^1.0.1",
"passport": "~0.2.1",
"passport-facebook": "2.0.0",

View File

@@ -2,7 +2,7 @@ import mongoose from 'mongoose';
import autoinc from 'mongoose-id-autoinc';
import logger from '../website/src/libs/api-v3/logger';
import nconf from 'nconf';
import utils from '../website/src/libs/utils';
import utils from '../website/src/libs/api-v2/utils';
import repl from 'repl';
import gulp from 'gulp';

View File

@@ -8,7 +8,7 @@ var Group = require('../../../website/src/models/group').model;
var groupsController = require('../../../website/src/controllers/api-v2/groups');
describe('Groups Controller', function() {
var utils = require('../../../website/src/libs/utils');
var utils = require('../../../website/src/libs/api-v2/utils');
describe('#invite', function() {
var res, req, user, group;

View File

@@ -3,7 +3,7 @@ var validator = require('validator');
var passport = require('passport');
var shared = require('../../../../common');
var async = require('async');
var utils = require('../../libs/utils');
var utils = require('../../libs/api-v2/utils');
var nconf = require('nconf');
var request = require('request');
var FirebaseTokenGenerator = require('firebase-token-generator');

View File

@@ -9,7 +9,7 @@ var Group = require('./../../models/group').model;
var Challenge = require('./../../models/challenge').model;
var logging = require('./../../libs/api-v2/logging');
var csv = require('express-csv');
var utils = require('../../libs/utils');
var utils = require('../../libs/api-v2/utils');
var api = module.exports;
var pushNotify = require('./../pushNotifications');

View File

@@ -9,7 +9,7 @@ var _ = require('lodash');
var nconf = require('nconf');
var async = require('async');
var Q = require('q');
var utils = require('./../../libs/utils');
var utils = require('./../../libs/api-v2/utils');
var shared = require('../../../../common');
var User = require('./../../models/user').model;
var Group = require('./../../models/group').model;

View File

@@ -5,7 +5,7 @@ var api = module.exports;
var async = require('async');
var _ = require('lodash');
var shared = require('../../../../common');
var utils = require('../../libs/utils');
var utils = require('../../libs/api-v2/utils');
var nconf = require('nconf');
var pushNotify = require('./../pushNotifications');

View File

@@ -1,6 +1,6 @@
var User = require('../../models/user').model;
var EmailUnsubscription = require('../../models/emailUnsubscription').model;
var utils = require('../../libs/utils');
var utils = require('../../libs/api-v2/utils');
var i18n = require('../../../../common').i18n;
var api = module.exports = {};

View File

@@ -5,7 +5,7 @@ var nconf = require('nconf');
var async = require('async');
var shared = require('../../../../common');
var User = require('./../../models/user').model;
var utils = require('./../../libs/utils');
var utils = require('./../../libs/api-v2/utils');
var analytics = utils.analytics;
var Group = require('./../../models/group').model;
var Challenge = require('./../../models/challenge').model;

View File

@@ -1,7 +1,7 @@
var _ = require('lodash');
var shared = require('../../../../common');
var nconf = require('nconf');
var utils = require('./../../libs/utils');
var utils = require('./../../libs/api-v2/utils');
var moment = require('moment');
var isProduction = nconf.get("NODE_ENV") === "production";
var stripe = require('./stripe');

View File

@@ -9,13 +9,13 @@ var logger = require('./libs/api-v3/logger');
// Initialize configuration
var setupNconf = require('./libs/api-v3/setupNconf');
setupNconf();
var utils = require('./libs/utils');
utils.setupConfig();
var IS_PROD = nconf.get('IS_PROD');
var IS_DEV = nconf.get('IS_DEV');
var cores = Number(nconf.get('WEB_CONCURRENCY')) || 0;
if (IS_DEV) Error.stackTraceLimit = Infinity;
// Setup the cluster module
if (cores !== 0 && cluster.isMaster && (IS_DEV || IS_PROD)) {
// Fork workers. If config.json has CORES=x, use that - otherwise, use all cpus-1 (production)

View File

@@ -0,0 +1,153 @@
import { createTransport } from 'nodemailer';
import nconf from 'nconf';
import logger from './logger';
import { encrypt } from './encryption';
import request from 'request';
const IS_PROD = nconf.get('IS_PROD');
const EMAIL_SERVER = {
url: nconf.get('EMAIL_SERVER:url'),
auth: {
user: nconf.get('EMAIL_SERVER:authUser'),
password: nconf.get('EMAIL_SERVER:authPassword'),
},
};
const BASE_URL = nconf.get('BASE_URL');
let smtpTransporter = createTransport({
service: nconf.get('SMTP_SERVICE'),
auth: {
user: nconf.get('SMTP_USER'),
pass: nconf.get('SMTP_PASS'),
},
});
// Send email directly from the server using the smtpTransporter,
// used only to send password reset emails because users unsubscribed on Mandrill wouldn't get them
export function send (mailData) {
return smtpTransporter
.sendMail(mailData)
.catch((error) => logger.error(error));
}
export function getUserInfo (user, fields) {
let info = {};
if (fields.indexOf('name') !== -1) {
if (user.auth.local) {
info.name = user.profile.name || user.auth.local.username;
} else if (user.auth.facebook) {
info.name = user.profile.name || user.auth.facebook.displayName || user.auth.facebook.username;
}
}
if (fields.indexOf('email') !== -1) {
if (user.auth.local && user.auth.local.email) {
info.email = user.auth.local.email;
} else if (user.auth.facebook && user.auth.facebook.emails && user.auth.facebook.emails[0] && user.auth.facebook.emails[0].value) {
info.email = user.auth.facebook.emails[0].value;
}
}
if (fields.indexOf('_id') !== -1) {
info._id = user._id;
}
if (fields.indexOf('canSend') !== -1) {
info.canSend = user.preferences.emailNotifications.unsubscribeFromAll !== true;
}
return info;
}
// Send a transactional email using Mandrill through the external email server
export function txnEmail (mailingInfoArray, emailType, variables, personalVariables) {
mailingInfoArray = Array.isArray(mailingInfoArray) ? mailingInfoArray : [mailingInfoArray];
variables = [
{name: 'BASE_URL', content: BASE_URL},
].concat(variables || []);
// It's important to pass at least a user with its `preferences` as we need to check if he unsubscribed
mailingInfoArray = mailingInfoArray.map((mailingInfo) => {
return mailingInfo._id ? getUserInfo(mailingInfo, ['_id', 'email', 'name', 'canSend']) : mailingInfo;
}).filter((mailingInfo) => {
// Always send reset-password emails
// Don't check canSend for non registered users as already checked before
return mailingInfo.email && (!mailingInfo._id || mailingInfo.canSend || emailType === 'reset-password');
});
// Personal variables are personal to each email recipient, if they are missing
// we manually create a structure for them with RECIPIENT_NAME and RECIPIENT_UNSUB_URL
// otherwise we just add RECIPIENT_NAME and RECIPIENT_UNSUB_URL to the existing personal variables
if (!personalVariables || personalVariables.length === 0) {
personalVariables = mailingInfoArray.map((mailingInfo) => {
return {
rcpt: mailingInfo.email,
vars: [
{
name: 'RECIPIENT_NAME',
content: mailingInfo.name,
},
{
name: 'RECIPIENT_UNSUB_URL',
content: `/unsubscribe?code=${encrypt(JSON.stringify({
_id: mailingInfo._id,
email: mailingInfo.email,
}))}`,
},
],
};
});
} else {
let temporaryPersonalVariables = {};
mailingInfoArray.forEach((mailingInfo) => {
temporaryPersonalVariables[mailingInfo.email] = {
name: mailingInfo.name,
_id: mailingInfo._id,
};
});
personalVariables.forEach((singlePersonalVariables) => {
singlePersonalVariables.vars.push(
{
name: 'RECIPIENT_NAME',
content: temporaryPersonalVariables[singlePersonalVariables.rcpt].name,
},
{
name: 'RECIPIENT_UNSUB_URL',
content: `/unsubscribe?code=${encrypt(JSON.stringify({
_id: temporaryPersonalVariables[singlePersonalVariables.rcpt]._id,
email: singlePersonalVariables.rcpt,
}))}`,
}
);
});
}
if (IS_PROD && mailingInfoArray.length > 0) {
request({
url: `${EMAIL_SERVER.url}/job`,
method: 'POST',
auth: {
user: EMAIL_SERVER.auth.user,
pass: EMAIL_SERVER.auth.password,
},
json: {
type: 'email',
data: {
emailType,
to: mailingInfoArray,
variables,
personalVariables,
},
options: {
priority: 'high',
attempts: 5,
backoff: {delay: 10 * 60 * 1000, type: 'fixed'},
},
},
}, (err) => logger.error(err));
}
}

View File

@@ -0,0 +1,24 @@
import {
createCipher,
createDecipher,
} from 'crypto';
import nconf from 'nconf';
const algorithm = 'aes-256-ctr';
const SESSION_SECRET = nconf.get('SESSION_SECRET');
export function encrypt (text) {
let cipher = createCipher(algorithm, SESSION_SECRET);
let crypted = cipher.update(text, 'utf8', 'hex');
crypted += cipher.final('hex');
return crypted;
}
export function decrypt (text) {
let decipher = createDecipher(algorithm, SESSION_SECRET);
let dec = decipher.update(text, 'hex', 'utf8');
dec += decipher.final('utf8');
return dec;
}

View File

@@ -1,6 +1,6 @@
var nconf = require('nconf');
var _ = require('lodash');
var utils = require('../libs/utils');
var utils = require('../libs/api-v2/utils');
var shared = require('../../../common');
var i18n = require('../libs/api-v2/i18n');
var buildManifest = require('../libs/buildManifest');

View File

@@ -2,7 +2,7 @@
import nconf from 'nconf';
import logger from './libs/api-v3/logger';
import utils from './libs/utils';
import utils from './libs/api-v2/utils';
import express from 'express';
import http from 'http';
// import path from 'path';