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)
Related
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.
Hey When I'm trying to send a mail via Nodemailer (using postman). I got this error!
Failed to create access token : error message**(FetchError: request to https://oauth2.googleapis.com/token failed, reason: certificate has expired**
// Googleapis
const { google } = require("googleapis");
// Pull out OAuth from googleapis
const OAuth2 = google.auth.OAuth2;
const createTransporter = async () => {
//Connect to the oauth playground
const oauth2Client = new OAuth2(
process.env.OAUTH_CLIENT_ID,
process.env.OAUTH_CLIENT_SECRET,
"https://developers.google.com/oauthplayground"
);
// Add the refresh token to the Oauth2 connection
oauth2Client.setCredentials({
refresh_token: process.env.OAUTH_REFRESH_TOKEN,
});
const accessToken = await new Promise((resolve, reject) => {
oauth2Client.getAccessToken((err, token) => {
if (err) {
reject("Failed to create access token : error message(" + err);
}
resolve(token);
});
});
// Authenticating and creating a method to send a mail
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
type: "OAuth2",
user: process.env.SENDER_EMAIL,
accessToken,
clientId: process.env.OAUTH_CLIENT_ID,
clientSecret: process.env.OAUTH_CLIENT_SECRET,
refreshToken: process.env.OAUTH_REFRESH_TOKEN,
},
});
return transporter;
};
Update
This error only happens when I am trying to send a mail from my home network otherwise it works perfectly fine.
Thank You
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
Every time I make a forgot password request, it gives me this error and the mail is never sent to the Mailtrap.
Nodemailer Setup
This is the basic node mailer setup I did.
port = 25
const nodemailer = require('nodemailer');
const sendEmail = async (options) => {
// 1) Create a Transporter
const transporter = nodemailer.createTransport({
host: process.env.EMAIL_HOST,
port: process.env.EMAIL_PORT,
auth: {
user: process.env.EMAIL_USERNAME,
pass: process.env.EMAIL_PASSWORD,
},
});
// 2) Define the email Options
const mailOptions = {
from: 'Sachin Yadav <sachin.yadav#gmail.com',
to: options.email,
subject: options.subject,
text: options.text,
};
// 3) Send the email
await transporter.sendMail(mailOptions);
};
Forgot Password Function
catchAsync is just a wrapper function which is created just to catch asynchronous errors separately. It returns the async function passed into it and call it with the req, res and next parameters.
exports.forgotPassword = catchAsync(async (req, res, next) => {
// 1) Get user based on posted email
const user = await User.findOne({ email: req.body.email });
if (!user)
return next(
new AppError('No user with that email. Please try again!', 404)
);
// 2) Generate Random
const resetToken = user.createPasswordResetToken();
await user.save({ validateBeforeSave: false });
// 3) Send back the token on email
const resetURL = `${req.protocol}://${req.get('host')}/api/v1/users/resetPassword/${resetToken})}`;
const message = `Forgot your password? Submit a PATCH request with your new password and passwordConfirm to : ${resetURL}`;
// Send Email
try {
await sendEmail({
email: user.email,
subject: 'Password reset link (Valid for 10mins)',
message,
});
res.status(200).json({
status: 'success',
message: 'Token send',
});
// Err
} catch (err) {
// Set back the token and expire time
user.createPasswordResetToken = undefined;
user.passwordResetExpires = undefined;
await user.save({ validateBeforeSave: false });
return next(
new AppError(`There was an error sending the email ${err.message}`, 500)
);
}
});
I just changed the port from 25 to 2525 and for some reason it worked. If anyone know why this worked, please let me know.
One reason could be some other application is using port '25' in your system. If you're using a Windows PC you can check the ports that are being used with the below command(you need to open cmd as an administrator):
netstat -aon
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);