receive mail with nodemailer without setting "Allow less secure apps to access" - node.js

I want to ask something about nodemailer, i make code like
Var client = nodemailer.createTransport ({
Service: 'gmail',
Auth: {
User: 'example#gmail.com', // Your email address
Pass: '123' // Your password},
Tls: {rejectUnauthorized: false}
});
And this works, but after successful delivery, when I have to receive email messages that have been sent, I need to enable gmail settings like "Allow less secure apps to access". I do not want to set it.
So how do I send emails from example#gmail.com TO example1#gmail.com, without setting "Allow less secure apps to access" and message directly accept in email box !!??? Or any other plugin that should be added ??
THANX;)

Obtain accessToken & refreshToken from Google OAuth2.0 Playground,
clientId & clientSecret from Google developer console
const nodemailer = require('nodemailer');
const xoauth2 = require('xoauth2');
var express = require('express');
var router = express.Router();
var smtpTransport = nodemailer.createTransport('SMTP',{
service:"Gmail",
auth:{
XOAuth2: {
user:'sender#emailaddress.com',
clientId: 'your-client-id',
clientSecret: 'your-cliet-secret',
accessToken:'your-access-token',
refreshToken: 'your-refresh-token'
}
}
});
router.get('/emaildemo', function(req, res, next) {
var mailOptions = {
from: 'sender#emailaddress.com',
to: 'xxx#email.com',
subject: 'TEST SUBJECTT',
text: 'TEST MAIL',
};
smtpTransport.sendMail(mailOptions, function(error, info){
if(error){
console.log('Error Occured', error);
return res.send(error);
}
return res.send("mail send successfully");
});
});
module.exports = router;

You need to get the access token, you cannot give it statically.
googleapis can be user for gmail.
for example:
const { google } = require('googleapis');
const { OAuth2 } = google.auth;
const {
MAILING_SERVICE_CLIENT_ID,
MAILING_SERVICE_CLIENT_SECRET,
MAILING_SERVICE_REFRESH_TOKEN,
SENDER_EMAIL_ADDRESS,
OAUTH_PLAYGROUND //https://developers.google.com/oauthplayground
} = process.env;
const oauth2Client = new OAuth2(
MAILING_SERVICE_CLIENT_ID,
MAILING_SERVICE_CLIENT_SECRET,
OAUTH_PLAYGROUND
);
oauth2Client.setCredentials({
refresh_token: MAILING_SERVICE_REFRESH_TOKEN,
});
//>>> get the accessToken
const accessToken = oauth2Client.getAccessToken();
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
type: 'OAuth2',
user: SENDER_EMAIL_ADDRESS,
clientId: MAILING_SERVICE_CLIENT_ID,
clientSecret: MAILING_SERVICE_CLIENT_SECRET,
refreshToken: MAILING_SERVICE_REFRESH_TOKEN,
accessToken,
},
});
let mailOptions = {
from: 'no-reply#blah.com',
to: 'to_blah#blah.com',
subject: 'test',
text: 'test'
};
let result = await transporter.sendMail(mailOptions);

Related

Why is my password reset link logic showing undefined in my Express app?

I am trying to create a route that sends someone a JWT token reset link. The Route that I am having issues with is as follows:
// REQUIREMENTS
require("dotenv").config();
const express = require("express"),
expressSanitizer= require("express-sanitizer"),
router = express.Router(),
passport = require("passport"),
User = require("../models/user"),
middleware = require("../middleware"),
mailchimp = require('#mailchimp/mailchimp_marketing'),
request = require('request'),
https = require('https'),
nodemailer = require("nodemailer"),
jwt = require('jsonwebtoken');
const JWT_SECRET = "jwt_secret";
router.post('/forgot-password', (req, res, next) =>{
let userEmail = req.body.email;
let link;
User.findOne({'email': req.query.email}, function(err, username){
let userEmail = req.body.email;
if(err) {
console.log(err);
}
var message;
if(username) {
console.log(username);
message = "email exists";
console.log(message);
// SEND TOKEN HERE
const secret = JWT_SECRET + username.password;
const payload = {
id: username.id,
email: userEmail
};
let token = jwt.sign(payload, secret, {expiresIn: '15m'});
// CHECK URL PARAMS
let link = process.env.URL`/${username.id}/${token}`;
console.log(link);
console.log(payload);
return link, payload;
}
});
let transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
type: 'OAuth2',
clientId: authClient,
clientSecret: authCSecret
}
});
// Email Data
let mailOptions = {
from: *****, // sender address
to: userEmail, // list of receivers
replyTo: *****,
subject: 'Reset Your Password', // Subject line
html: '<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet"/><link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"rel="stylesheet"/><link href="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/6.0.1/mdb.min.css" rel="stylesheet"/><p class="lead">Hey, it looks like you forgot your password.</p><p class="card-text">Follow the link below to reset your password.<div class="text-center"><a class="btn btn-lg btn-primary my-3" href="'+link+'" target="_blank">click here</a></div></p><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/6.0.1/mdb.min.js"></script>', // html body
auth: {
user: authUser,
refreshToken: authRefreshToken,
accessToken: authAccessToken,
expires: 3599
}
};
// send mail with defined transport object
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
res.send("A link has been sent to your email.");
});
});
I have confirmed the Nodemailer part works. I am just at a loss why the link is always showing as undefined when in my console it prints out a valid link to follow. All help would be appreciated!

Nodemailer is only sending emails for gmail

i'm using Oauth2 and nodemailer to send emails using nodejs.
when i send the email to a gmail email ex: example#gmail.com everything is working fine,
but when i try to send the email to a hotmail email ex: example#hotmail.com, it's returning for me a success message, but when i check my email, i see that the email was not sent.
this is my code:
const nodemailer = require('nodemailer');
const { google } = require('googleapis');
const CLIENT_ID = 'My client id';
const CLEINT_SECRET = 'the secret';
const REDIRECT_URI = 'https://developers.google.com/oauthplayground';
const REFRESH_TOKEN = 'the refresh token';
const oAuth2Client = new google.auth.OAuth2(
CLIENT_ID,
CLEINT_SECRET,
REDIRECT_URI
);
oAuth2Client.setCredentials({ refresh_token: REFRESH_TOKEN });
exports.sendEmail = async (email, subject, text, html) => {
try {
const accessToken = await oAuth2Client.getAccessToken();
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
type: 'OAuth2',
user: process.env.EMAIL,
clientId: CLIENT_ID,
clientSecret: CLEINT_SECRET,
refreshToken: REFRESH_TOKEN,
accessToken: accessToken,
}
});
const mailOptions = {
from: 'Twitter from AliExpress <process.env.EMAIL>',
to: email,
subject: subject,
text: text,
html: html
};
const result = await transporter.sendMail(mailOptions);
return result
}
catch (error) {
let err = new Error('Email err: '+ error.message)
return err
}
}
Thank you.

"Invalid login: 535-5.7.8 Username and Password not accepted" while sending mail from nodejs using office 365 mail

I am getting error "Invalid login: 535-5.7.8 Username and Password not accepted" while trying to send mail using nodejs.
Below is my configuration
this._transport = nodemailer.createTransport({
service: 'Outlook365',
name: 'smtp.office365.com',
host: 'smtp.office365.com', // Office 365 server
port: '587',
secure: false,
auth: {
user: process.env.MAIL_USERNAME,
pass: process.env.MAIL_PASSWORD,
},
secureConnection: false,
tls: { ciphers: 'SSLv3' }
})
and while sending the mail
var mailOptions = {
from: `Admin<${settingObj.Contact_Email}>`,
to: req.body.email,
subject: "Subject",
html: 'Hello ' + '<b>' + req.body.email + '<br>Thank You for contacting'
};
var sendMail = await transporter.sendMail(mailOptions);
below is sendmail function
async sendMail(from, to, subject, tplName, locals) {
try {
const mailer = new Mailer();
const templateDir = path.join(__dirname, "../views/", 'email-templates', tplName + '/html')
const email = new Email({
message: { from: from },
transport: { jsonTransport: true },
views: { root: templateDir, options: { extension: 'ejs' } }
});
let getResponse = await email.render(templateDir, locals);
if (getResponse) {
let options = { from: from, to: to, subject: subject, html: getResponse };
let mailresponse = await mailer._transport.sendMail(options);
if (mailresponse) {
return true;
}
else {
return false;
}
}
}
catch (e) {
console.log("44>>", e.message);
return false;
}
};
Before doing anything, ensure you are able to log in to your office 365 account with your username and password.
if you're facing this error in a hosted app, make sure you've created the env variables in config-vars/parameter-store/secrets or whichever is applicable for the platform?
Use telnet to access your office 365 SMTP account, doing so, you can get to know if it's a problem with your code or the settings.
Here is my working code,
const express = require('express');
const nodemailer = require('nodemailer');
const app = express();
app.get('/', (req, resp)=>{
const email = `
<h3>Hello dee.....</h3>
<ul>
<li>Name: Deepak </li>
<li>Email: dee#dee.com </li>
</ul>
<h2>Message<h2>
<p>Wassup....howdeeee</p>
`
let transporter = nodemailer.createTransport({
host: "smtp.office365.com",
port: '587',
auth: {
user: '....',
pass: 'blahhhhh'
},
secureConnection: false,
tls: { ciphers: 'SSLv3' }
});
transporter.sendMail({
from: '.....',
to: '.....',
subject: 'Test for twix',
text: 'hello twix',
html: email
}).then(res=>{
console.log("success........", res)
resp.send("yeahhhhhhhh", res);
}).catch(e=>{
console.log("failed........", e)
});
});
app.listen(5000, console.log("Server listening to 6k"));
I enabled two-factor authentication and logged out of all active sessions then tried again, it worked fine with the above code.
Updated answer in response to comments
const express = require('express');
const nodemailer = require('nodemailer');
const app = express();
app.get('/send', async (req, resp) => {
let transporter = nodemailer.createTransport({
host: "smtp.office365.com",
port: '587',
auth: {
user: '......',
pass: '......'
},
secureConnection: false,
tls: { ciphers: 'SSLv3' }
});
var mailOptions = {
from: '.......',
to: '.......',
subject: "Twix mailer",
html: 'Hello ' + '<b>' + 'deechris27' + '<br>Thank You for contacting'
};
let sendMail = await transporter.sendMail(mailOptions);
console.log("twix email.....", sendMail.response);
});
app.listen(5000, console.log("Server listening to 5k"));
Success message below
Suggested changes
this._transport = nodemailer.createTransport({
service: 'Outlook365', // remove this
name: 'smtp.office365.com', // not needed
host: 'smtp.office365.com',
port: '587',
secure: false, // remove this
auth: {
user: process.env.MAIL_USERNAME, // hardcode username to try
pass: process.env.MAIL_PASSWORD, // hardcode pwd to try in local
},
secureConnection: false,
tls: { ciphers: 'SSLv3' }
});
comment out sendMail(from, to, subject, tplName, locals) function. Where is this called? this appears to be like you're trying to do what Nodemailer does internally. Though it wouldn't throw an invalid login error, I advise you to comment out for debugging.
I got the email "Hello deechris27 Thank You for contacting" to my inbox when this
let sendMail = await transporter.sendMail(mailOptions); promise was resolved.
createTransport of nodemailer returns an instance of Mailer which provides the sendMail function. The "From" address in mailOptions should be same as the auth.user.
I'm using Nodemailer Version 6.6.3. Refer to node_modules -> nodemailer -> lib -> nodemailer.js for more clarity.
Helpful Resources:
https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/concept-fundamentals-security-defaults
https://answers.microsoft.com/en-us/outlook_com/forum/all/i-cant-send-e-mails-from-my-server-through-office/999b353e-9d4f-49b2-9da9-14d6d4e6dfb5
On your Outlook dashboard, you need to allow less secure apps from your outlook account to send emails. Through this link. Allow less secure apps

Nodemailer: set configuration to send email from custom email

I am using Nodemailer to send emails to my users.
Email used to send emails is 'xyz#toyjunction.online' not gmail.
const nodemailer = require('nodemailer');
let sendMail = async (userName, email, password) => {
return new Promise(function (resolve, reject) {
var smtpConfig = {
host: 'smtp.gmail.com',
port: 465,
secure: true, // use SSL
auth: {
user: 'xyz#toyjunciton.online',
pass:'xxxxxx'
}
};
var transporter = nodemailer.createTransport(smtpConfig);
const mailOptions = {
from: 'xyz#toyjunciton.online',
to: email,
subject: 'Demo Subject',
html: `Hi ${userName}, Your new password is ${password}.`
};
transporter.sendMail(mailOptions, (err, info) => {
let rtnStatus;
if (err) {
reject(false);
} else {
resolve(true);
}
return rtnStatus;
});
});
}
module.exports = sendMail;
Getting error:
Invalid login: 535-5.7.8 Username and Password not accepted.
I have seen a lot of solutions on the internet but not worked for me.

Implement a mailing solution in Express nodejs

I'm creating an API that handles account verification via email, password recovery and possibly other things.
I want to create one place to send emails across my entire API.
i'm using nodeMailer.
My current setup is i'm a calling a method on the user model that send EmailVerification email.
I want to create a template outside the User model that could send either password recovery, email verification or other things.. Depending on the params that i pass to the function.
My user model:
userSchema.methods.generateEmailVerificationToken = function() {
const token = jwt.sign({_id: this._id, role: this.role},
config.get('jwtPrivateKey'));
return token;
};
userSchema.methods.generateAuthToken = function() {
const token = jwt.sign({_id: this._id, role: this.role},
config.get('jwtPrivateKey'));
return token;
};
userSchema.methods.sendEmailVerification = function (user) {
sendMail(user);
};
and this is my sendMail function:
const nodemailer = require('nodemailer');
module.exports = function sendMail (user) {
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'mymail#gmail.com',
pass: 'mypass'
}
});
const mailOptions = {
from: 'mymail#gmail.com',
to: user.email,
subject: 'Email verification.',
html: `Please click this link to verify your email`
};
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
}
Thank you

Resources