Nodemailer is only sending emails for gmail - node.js

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.

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 error: verification email doesn't works

I am writing this code to sign up the user.
I used Nodemailer to send a verification email to activate the account.
The post request works well but I did not receive a verification email and here is my code:
const transporter = nodemailer.createTransport({
service: "Gmail",
auth: {
user: process.env.EMAIL_USERNAME,
pass: process.env.EMAIL_PASSWORD,
},
});
exports.signup = async(req, res) => {
const { email } = req.body
if (!email) {
return res.status(422).send({ message: "Missing email." })
}
try {
const existingUser = await User.findOne({ email }).exec();
if (existingUser) {
return res.status(409).send({
message: "Email is already in use."
});
}
const user = await new User({
_id: new mongoose.Types.ObjectId,
email: email
}).save();
const verificationToken = user.generateVerificationToken();
const url = `http://localhost:5000/api/verify/${verificationToken}`
transporter.sendMail({
to: email,
subject: 'Verify Account',
html: `Click <a href = '${url}'>here</a> to confirm your email.`
})
return res.status(201).send({
message: `Sent a verification email to ${email}`
});
} catch (err) {
return res.status(500).send(err);
}
}
WHEN I SEND THE REQUEST, SHOWS ME LIKE THIS
Go to Google account, than Security and Less secure app access, and set to ON. Restart Your app and Now should up and running ;-)
Note That - In Your .env file, enter Your credentials without any quotes

How to solve Native promise missing Error in Nodejs?

I was trying to use google API to send mail through Nodemailer
Getting this error multiple times;
Code:
const oAuth2Client = new google.auth.OAuth2(
CLIENT_ID,
CLEINT_SECRET,
REDIRECT_URI
);
oAuth2Client.setCredentials({ refresh_token: REFRESH_TOKEN });
async function sendMail() {
try {
const accessToken = await oAuth2Client.getAccessToken();
const transport = nodemailer.createTransport({
service: 'gmail',
auth: {
type: 'OAuth2',
user: 'email',
clientId: CLIENT_ID,
clientSecret: CLEINT_SECRET,
refreshToken: REFRESH_TOKEN,
accessToken: accessToken,
},
});
const mailOptions = {
from: 'SENDER NAME <email>',
to: 'to email address here',
subject: 'Hello from gmail using API',
text: 'Hello from gmail email using API',
html: '<h1>Hello from gmail email using API</h1>',
};
const result = await transport.sendMail(mailOptions);
return result;
} catch (error) {
return error;
}
}
sendMail()
.then((result) => console.log('Email sent...', result))
.catch((error) => console.log(error.message));
When I started running the code it passed through then function and showing the error in .then() only this error is not caught by .catch() but by.then() Not getting any modern javascript solution
Email sent... Error: native promise missing, set fetch.Promise to your favorite alternative
at fetch (E:\WORK\D-FLOW\C-Flow\C-FLow-Back-end\node_modules\node-fetch\lib\index.js:1401:9)
at Gaxios._defaultAdapter (E:\WORK\D-FLOW\C-Flow\C-FLow-Back-end\node_modules\gaxios\build\src\gaxios.js:111:28)
at Gaxios._request (E:\WORK\D-FLOW\C-Flow\C-FLow-Back-end\node_modules\gaxios\build\src\gaxios.js:126:49)
at Gaxios.request (E:\WORK\D-FLOW\C-Flow\C-FLow-Back-end\node_modules\gaxios\build\src\gaxios.js:107:21)
at Object.request (E:\WORK\D-FLOW\C-Flow\C-FLow-Back-end\node_modules\gaxios\build\src\index.js:30:29)
at DefaultTransporter.request (E:\WORK\D-FLOW\C-Flow\C-FLow-Back-end\node_modules\google-auth-library\build\src\transporters.js:74:29)
at OAuth2Client.refreshTokenNoCache (E:\WORK\D-FLOW\C-Flow\C-FLow-Back-end\node_modules\google-auth-library\build\src\auth\oauth2client.js:172:44)
at OAuth2Client.refreshToken (E:\WORK\D-FLOW\C-Flow\C-FLow-Back-end\node_modules\google-auth-library\build\src\auth\oauth2client.js:150:24)
at OAuth2Client.refreshAccessTokenAsync (E:\WORK\D-FLOW\C-Flow\C-FLow-Back-end\node_modules\google-auth-library\build\src\auth\oauth2client.js:196:30)
at OAuth2Client.getAccessTokenAsync (E:\WORK\D-FLOW\C-Flow\C-FLow-Back-end\node_modules\google-auth-library\build\src\auth\oauth2client.js:216:34)

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

receive mail with nodemailer without setting "Allow less secure apps to access"

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);

Resources