Skip to content

Instantly share code, notes, and snippets.

@jonataswalker
Last active February 16, 2020 07:25
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jonataswalker/75d10240ee9dbeb112b0 to your computer and use it in GitHub Desktop.
Save jonataswalker/75d10240ee9dbeb112b0 to your computer and use it in GitHub Desktop.
Sending mail with Gmail (XOAuth2) and Nodemailer
'use strict';
var xoauth2 = require('xoauth2');
var nodemailer = require('nodemailer');
var smtp = require('nodemailer-smtp-transport');
var htmlToText = require('nodemailer-html-to-text').htmlToText;
// Sending mail with Gmail using XOAuth2
// http://masashi-k.blogspot.com.br/2013/06/sending-mail-with-gmail-using-xoauth2.html
/**
* @param {Object} constants expects the following:
* {
* stmp_host: 'smtp-relay.gmail.com',
* user: 'some@gmail.com',
* user_name: 'Some Name',
* clientId: '...........', // see link above how to get one
* clientSecret: '.......',
* refreshToken: '.......'
* }
*/
function myMailer(constants) {
this.token = '';
this.xoauth2_generator = '';
this.transporter = '';
this.constants = constants;
}
myMailer.prototype.createTransporter = function() {
var self = this;
var constants = this.constants;
return new Promise(function(resolve, reject) {
self.createXOAuth().then(function() {
self.transporter = nodemailer.createTransport(smtp({
name: constants.stmp_host,
host: constants.stmp_host,
port: 587,
secure: false,
ignoreTLS: false,
tls: { rejectUnauthorized: true },
debug: false,
auth: { xoauth2: self.xoauth2_generator }
}));
self.transporter.use('compile', htmlToText());
resolve();
})
.catch((err) => reject(err));
});
};
myMailer.prototype.getAccessToken = function(transporter) {
var self = this;
return new Promise(function(resolve, reject) {
self.xoauth2_generator.getToken(function(err, token){
if(err) reject(err);
else {
self.token = token;
resolve();
}
});
});
};
myMailer.prototype.createXOAuth = function() {
var self = this;
var constants = this.constants;
return new Promise(function(resolve, reject) {
self.xoauth2_generator = xoauth2.createXOAuth2Generator({
user: constants.user,
clientId: constants.clientId,
clientSecret: constants.clientSecret,
refreshToken: constants.refreshToken,
accessToken: self.google_token
});
self.xoauth2_generator.getToken(function(err, token){
if(err) reject(err);
else {
self.google_token = token;
resolve();
}
});
});
};
/**
* @param {Object} data expects the following:
* {
* subject: 'Hi There!',
* html: 'some<br>formatted<strong>text</strong>',
* to_name: 'Some Name',
* to_email: 'to_email@mail.com'
* }
*/
myMailer.prototype.getMailObject = function(data) {
var mail = {
headers: {
'X-Sender': this.constants.user_name + '<'+this.constants.user+'>'
},
from: this.constants.user_name + '<'+this.constants.user+'>'
};
return new Promise(function(resolve, reject) {
mail.subject = data.subject;
mail.html = data.html;
mail.to = {
name: data.to_name,
address: data.to_email
};
resolve(mail);
});
};
myMailer.prototype.sendMail = function(mail) {
var self = this;
return new Promise(function(resolve, reject) {
self.getAccessToken(self.transporter).then(function(){
self.transporter.sendMail(mail, function(error, info) {
if (error) {
reject(error);
} else {
resolve(info);
}
});
}).catch((err) => reject(err));
});
};
module.exports = myMailer;
// USAGE
// testing-mailer.js
// response is coming (in my case) from REDIS
var constants = {
stmp_host: 'smtp-relay.gmail.com',
user: resp.SUPORTE_MAIL,
user_name: resp.SUPORTE_NAME,
clientId: resp.OAUTH_CLIENT_ID,
clientSecret: resp.OAUTH_CLIENT_SECRET,
refreshToken: resp.OAUTH_REFRESH_TOKEN
};
var Mailer = require('./my-mailer.js');
var mailer = new Mailer(constants);
mailer.createTransporter().then(function(){
var send_info = {
subject: 'A test!',
html: 'some<br>formatted <strong>text</strong>',
to_name: 'Some Name',
to_email: 'some@gmail.com'
};
return mailer.getMailObject(send_info);
}).then(function(mail_obj){
mailer.sendMail(mail_obj).then(function(info) {
console.info('sent to: ', info);
process.exit();
}).catch(function(err) {
console.info('error: ', err);
});
});
@Fritiof
Copy link

Fritiof commented May 3, 2018

This doesn't work, it complains about missing credentials for "PLAIN"

@hasanzia1993
Copy link

This doesn't work, it complains about missing credentials for "PLAIN"

I am getting the same error, how did you fix yours?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment