Skip to content

Instantly share code, notes, and snippets.

@AlexeyKhristov
Created November 25, 2015 12:48
Show Gist options
  • Save AlexeyKhristov/951a0423b9759ce70de8 to your computer and use it in GitHub Desktop.
Save AlexeyKhristov/951a0423b9759ce70de8 to your computer and use it in GitHub Desktop.
simple API example && mailer daemon
'use strict';
var pmx = require('./common/pmx')('mailer');
const config = require('config');
var co = require('co');
var fs = require('fs');
var nodemailer = require('nodemailer');
var signer = require('nodemailer-dkim').signer;
var debug = require('debug')('mailer');
var MAIL_LIMIT = 20;
var TEN_SECONDS = 10 * 1000;
var THIRTY_SECONDS = 30 * 1000;
co(function *init() {
var initResults = yield {
'checkConfig': checkConfig,
'mongoose': new Promise(function (resolve, reject) {
var mongoose = require('./common/mongoose');
mongoose.connection.once('open', function () {
resolve(mongoose);
});
mongoose.connection.once('error', function (err) {
reject(err);
});
}),
'MailModel': require('./apps/email').MailModel.bind(null, null),
'transporter': function mailer(cb) {
// create reusable transporter object using SMTP transport
var transporter = nodemailer.createTransport({
service: 'yandex',
auth: {
user: config.mail.auth.user,
pass: config.mail.auth.password
}
});
//DKIM
transporter.use('stream', signer({
domainName: config.API.domain,
keySelector: 'mail',
privateKey: fs.readFileSync('config/yandex.ppd.private.pem')
}));
cb(null, transporter);
}
};
var mongoose = initResults.mongoose;
var transporter = initResults.transporter;
var MailModel = initResults.MailModel;
console.log('Start mailer');
debug('Start mailer for domain "%s" with pair: %s/%s', config.API.domain, config.mail.auth.user, config.mail.auth.password);
var isMongodbOk = true;
mongoose.connection.on('error', function (err) {
isMongodbOk = false;
});
mongoose.connection.on('reconnected', function (err) {
isMongodbOk = true;
});
function forever() {
if (!isMongodbOk) { // test mongo
console.error('Mongo is down, wait 30 seconds');
return setTimeout(forever, THIRTY_SECONDS);
}
co(function *loop() {
var models = yield MailModel.find({
'status': MailModel.CONSTS.STATUSES.READY,
'mailType': MailModel.CONSTS.MAIL_TYPES.REGISTRATION
}).limit(MAIL_LIMIT).exec();
if (models.length === 0) {
return setTimeout(forever, TEN_SECONDS);
}
for (let i in models) {
let mailModel = models[i];
yield new Promise(function sendEmail(resolve, reject) {
var mailOptions = {
from: config.mail.from,
to: mailModel.email,
subject: 'subject',
html: 'body'
};
transporter.sendMail(mailOptions, function (err, info) {
if (err) {
return reject(err);
}
debug('sent email for "%s", response: %s', mailModel.email, info.response);
resolve();
});
});
mailModel.status = MailModel.CONSTS.STATUSES.SEND;
yield new Promise(function saveStatus(resolve, reject) {
mailModel.save(function (err) {
if (err) {
return reject(err);
}
resolve();
});
});
}
process.nextTick(forever);
}).catch(function (err) {
console.error('Send email / Save email model error, retry after 30 seconds: ', err);
pmx.notify(err);
setTimeout(forever, THIRTY_SECONDS);
});
}
process.nextTick(forever);
}).catch(function initError(err) {
console.error('Catch init error', err);
pmx.notify(err);
});
function checkConfig(cb) {
fs.readFile('config/yandex.ppd.private.pem', function (err, data) {
if (err) {
console.error('Mail Yandex PPD private key file not exists, application stopped');
process.exit(1);
}
cb(null, true);
});
}
'use strict';
const config = require('config');
var mount = require('koa-mount');
var koa = require('koa');
var app = koa();
require('./initializers')(app);
// routes
var AuthAPI = require('./apps/auth');
var UsersAPI = require('./apps/users');
app
.use(mount('/auth', AuthAPI.middleware()))
.use(mount('/users', UsersAPI.middleware()));
app.use(function *notFoundRoute() {
app.pmx.Inc404HttpCalls();
this.status = 404;
this.body = {
error: `Route not found for '${this.method}: ${this.request.url}'`
};
});
var http = require('http');
var mongoose = require('mongoose');
var server = http.createServer(app.callback());
console.log('Start with environment %s', app.env);
mongoose.connection.once('open', function () {
console.log('Mongoose connected');
server.listen(config.API.port, function () {
console.log('server started on port: %d', config.API.port);
});
});
'use strict';
var Router = require('koa-router');
var appRouter = new Router();
var bodyParser = require('koa-bodyparser')();
var debug = require('debug')('app:auth:index');
/* internal deps */
var LocalController = require('./controller.local');
var FacebookController = require('./controller.facebook');
var VkController = require('./controller.vk');
/* external deps */
module.exports.checkUserAuthentification = require('./check.user.authentification.middleware');
appRouter.post('/local', bodyParser, LocalController.loginLocal);
appRouter.post('/registration', bodyParser, LocalController.registrationLocal);
appRouter.post('/logout', LocalController.logout);
appRouter.post('/authenticate', LocalController.isAuthenticated);
appRouter.get('/facebook', FacebookController.loginFacebook);
appRouter.get('/facebook/callback', FacebookController.callbackFacebook);
appRouter.post('/facebook/deauthorize', bodyParser, FacebookController.deauthorizeFacebook);
appRouter.get('/vk', VkController.loginVk);
appRouter.get('/vk/callback', VkController.callbackVk);
module.exports.middleware = appRouter.middleware.bind(appRouter);
'use strict';
var passport = require('koa-passport');
var debug = require('debug')('app:auth:vk-controller');
var Controller = {};
Controller.loginVk = function *(next) {
yield* passport.authenticate('vkontakte').call(this, next);
};
Controller.callbackVk = function *(next) {
var ctx = this;
yield passport.authenticate('vkontakte', function *(err, user, options) {
if (err) {
console.error('Vk passport strategy callback return error: ', err);
ctx.throw(500);
}
try {
yield ctx.login(user);
user.lastLogin = Date.now();
yield user.save();
ctx.redirect('/');
} catch (e) {
console.error('Passport vk user login/save error: ', e);
ctx.throw(500);
}
}).call(this, next);
};
module.exports = Controller;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment