48

I've set up a basic NodeJS server (using the nodemailer module) locally (http://localhost:8080) just so that I can test whether the server can actually send out emails.

If I understand the SMTP option correctly (please correct me if I'm wrong), I can either try to send out an email from my server to someone's email account directly, or I can send the email, still using Node.js, but via an actual email account (in this case my personal Gmail account), i.e using SMTP. This option requires me to login into that acount remotely via NodeJS.

So in the server below I'm actually trying to use NodeJs to send an email from my personal email account to my personal email account.

Here's my simple server :

var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport("SMTP", {
    service: 'Gmail',
    auth: {
        user: '*my personal Gmail address*',
        pass: '*my personal Gmail password*'
    }
});

var http = require('http');
var httpServer = http.createServer(function (request, response)
{
    transporter.sendMail({
       from: '*my personal Gmail address*',
       to: '*my personal Gmail address*',
       subject: 'hello world!',
       text: 'hello world!'
    });
}).listen(8080);

However, it's not working. I got an email by Google saying :

Google Account: sign-in attempt blocked If this was you You can switch to an app made by Google such as Gmail to access your account (recommended) or change your settings at https://www.google.com/settings/security/lesssecureapps so that your account is no longer protected by modern security standards.

I couldn't find a solution for the above problem on the nodemailer GitHub page. Does anyone have a solution/suggestion ?

Thanks! :-)

Kawd
  • 4,122
  • 10
  • 37
  • 68

12 Answers12

86

The answer is in the message from google.

For the second part of the problem, and in response to

I'm actually simply following the steps from the nodemailer github page so there are no errors in my code

I will refer you to the nodemailer github page, and this piece of code :

var transporter = nodemailer.createTransport({
service: 'Gmail',
auth: {
    user: 'gmail.user@gmail.com',
    pass: 'userpass'
}
});

It differs slightly from your code, in the fact that you have : nodemailer.createTransport("SMTP". Remove the SMTP parameter and it works (just tested). Also, why encapsulating it in a http server? the following works :

var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
    service: 'Gmail',
    auth: {
        user: 'xxx',
        pass: 'xxx'
    }
});

console.log('created');
transporter.sendMail({
from: 'xxx@gmail.com',
  to: 'xxx@gmail.com',
  subject: 'hello world!',
  text: 'hello world!'
});
xShirase
  • 11,975
  • 4
  • 53
  • 85
  • I wanted to avoid that thinking it might actually make my account more vulnerable.. I thought I could bypass that via some nodemailer setting that I was maybe overlooking.. Maybe setting some extra certification property.. Thanks though! – Kawd Oct 04 '14 at 20:00
  • 1
    Having enabled that now, I know longer get that notification from Google but I don't get the email either so it's still not working I'm afraid.. – Kawd Oct 04 '14 at 20:28
  • 1
    try using a different 'to' and 'from' address, I've had a similar issue in the past with gmail and any other recipient than myself was working. – xShirase Oct 04 '14 at 20:29
  • that defeats the purpose of sending emails from my site to my personal Gmail account. Creating a new Gmail account so that I can use that one as the `from:`in nodemailer does not make much sense, there must be some other way around that other than such a big "hack" – Kawd Oct 04 '14 at 20:32
  • I suggested it more as a debugging procedure, to see if the problem comes from your code or from gmail. – xShirase Oct 04 '14 at 20:39
  • I'm actually simply following the steps from the nodemailer github page so there are no errors in my code unfortunately. But I'll keep looking for an answer thanks! – Kawd Oct 04 '14 at 20:45
  • Damn! You're right, it does work! :-) Thank you so much! I'm encapsulating it in an http server because I'm basically listening for a specific URL request (that will contain the subject, email, text etc..) and then I either send the email or serve some static page. I've just omitted those other parts from here to make my code more readable.. – Kawd Oct 04 '14 at 21:09
  • I know that my question is irrelevant to this post. How can we send email via node mailer through open relay servers ? – Balaji Boggaram Ramanarayan Aug 07 '15 at 14:21
  • @BalajiBoggaramRamanarayan If the question is irrelevant to this post, you can ask a new one on Stack Overflow – xShirase Aug 07 '15 at 19:18
  • this code (for my gmail account) doesn't send anymail to me. – SuperUberDuper May 21 '16 at 20:06
  • in fact I get no error, even if using wrong password – SuperUberDuper May 21 '16 at 20:07
  • after looking at error I see: [Error: Invalid login: 535-5.7.8 Username and Password not accepted. even if I allow non secure acces – SuperUberDuper May 21 '16 at 20:09
  • this also happened, when Google tries to prevent us from login. Just click "yes" to allow the sign in method from your server, so the google doesn't lock you out. – mochadwi Feb 14 '19 at 19:19
  • I have tried it but getting the error, "getaddrinfo ENOTFOUND Gmail" anyone can help me? – Kamlesh Jul 24 '19 at 09:20
  • In my case, in windows, machine mail is working perfectly fine but in the ubuntu machine, it's not working. can anyone help with this? – Amit Patel Jun 18 '20 at 05:48
32

Outdated: refreshToken and accessToken no longer exist in JSON file output

For those who actually want to use OAuth2 / don't want to make the app "less secure", you can achieve this by

  1. Search "Gmail API" from the google API console and click "Enable"
  2. Follow the steps at https://developers.google.com/gmail/api/quickstart/nodejs. In the quickstart.js file, changing the SCOPES var from ['https://www.googleapis.com/auth/gmail.readonly'] to ['https://mail.google.com/'] in the quickstart js file provided as suggested in troubleshooting at https://nodemailer.com/smtp/oauth2/
  3. After following the steps in (2), the generated JSON file will contain the acessToken, refreshToken, and expires attributes needed in the OAuth2 Examples for Nodemailer

This way you can use OAuth2 authentication like the following

let transporter = nodemailer.createTransport({
    service: 'Gmail',
    auth: {
        type: 'OAuth2',
        user: 'user@example.com',
        clientId: '000000000000-xxx0.apps.googleusercontent.com',
        clientSecret: 'XxxxxXXxX0xxxxxxxx0XXxX0',
        refreshToken: '1/XXxXxsss-xxxXXXXXxXxx0XXXxxXXx0x00xxx',
        accessToken: 'ya29.Xx_XX0xxxxx-xX0X0XxXXxXxXXXxX0x',
        expires: 1484314697598
    }
});

instead of storing your gmail password in plaintext and downgrading the security on your account.

Kevin Danikowski
  • 4,620
  • 6
  • 41
  • 75
ironicaldiction
  • 1,200
  • 4
  • 12
  • 27
  • 1
    Is no longer valid, the accessToken and refreshToken doesn't exist in that file anymore – CaptRisky Jun 19 '17 at 06:25
  • 2
    To get it to work, I used a combination of this answer transport definition (without specifiying accessToken and expires) and this post which uses google's oauth playground to obtain the refresh token: https://medium.com/@pandeysoni/nodemailer-service-in-node-js-using-smtp-and-xoauth2-7c638a39a37e – apricity Sep 01 '17 at 19:14
  • i didn't have a SCOPES variable in my gmail-nodejs-quickstart.json – Kirby Jan 28 '18 at 18:35
  • 2
    @CaptRisky re: your comment "the accessToken and refreshToken doesn't exist in that file anymore" is simply inaccurate. I followed the instructions and it did indeed produce a token.json file with all of the values: access_token,refresh_token, scope, token_type and expiry_date. – user2101068 Feb 13 '19 at 16:42
  • @Kirby, FYI...I just followed instructions and the quickstart nodejs file did indeed have a SCOPES variable. – user2101068 Feb 13 '19 at 16:49
  • 1
    @ironicaldiction Hoping you might be able to give me some advice. I've followed all of the steps you outlined above but each time the Access token expires my nodejs app fails to send out the email. Specifically I get the following message response in Postman {"code": "EAUTH", "command": "AUTH XOAUTH2"}. Any thoughts? – user2101068 Feb 13 '19 at 21:28
  • @ironicaldiction I followed the article, did all they asked for and got the required credentials but can't send any email. It is simply not sending – Nicholas Mberev Jul 17 '22 at 19:10
18

i just set my domain to: smtp.gmail.com and it works. I am using a VPS Vultr.

the code:

const nodemailer = require('nodemailer');
const ejs = require('ejs');
const fs = require('fs');

let transporter = nodemailer.createTransport({
    host: 'smtp.gmail.com',
    port: 465,
    secure: true,
    auth: {
        user: 'xxx@gmail.com',
        pass: 'xxx'
    }
});

let mailOptions = {
    from: '"xxx" <xxx@gmail.com>',
    to: 'yyy@gmail.com',
    subject: 'Teste Templete ✔',
    html: ejs.render( fs.readFileSync('e-mail.ejs', 'utf-8') , {mensagem: 'olá, funciona'})
};

transporter.sendMail(mailOptions, (error, info) => {
    if (error) {
        return console.log(error);
    }
    console.log('Message %s sent: %s', info.messageId, info.response);
});

my ejs template (e-mail.ejs):

<html>
    <body>
        <span>Esse é um templete teste</span>
        <p> gerando com o EJS - <%=mensagem%> </p>
    </body>
</html>

Make sure:

  • install ejs: npm install ejs --save
  • install nodemailer: npm install nodemailer --save
  • ping to smtp.gmail.com works: ping smtp.gmail.com
  • change xxx@gmail.com to your gmail email
  • change yyy@gmail.com to the email that you want to send a email
  • Enable less secure apps
  • Disable Captcha temporarily

have a nice day ;)

  • Use use `port: 465` ? Does it make any difference? Also, if you have `host:`, does that remove the need to add `service: 'Gmail'` ? – Cezar Cobuz Nov 25 '19 at 08:14
  • smtp default ports are: 25, 465 and 587, so `port: 465` is important for make it explict. As nodemailer docs, for `createTransport` is not available this `service` property, just `host`; – Mathias Gheno Azzolini Dec 05 '19 at 04:14
10

While the above answers do work, I'd like to point out that you can decrease security from Gmail by the following TWO steps.

STEP #1

Google Account: sign-in attempt blocked If this was you You can switch to an app made by Google such as Gmail to access your account (recommended) or change your settings at https://www.google.com/settings/security/lesssecureapps so that your account is no longer protected by modern security standards.

STEP #2

In addition to enabling Allow less secure apps, you might also need to navigate to https://accounts.google.com/DisplayUnlockCaptcha and click continue.

Ahmad Awais
  • 33,440
  • 5
  • 74
  • 56
7

You only need App password for google auth, then replace your google password in your code. go here https://myaccount.google.com/apppasswords

sample code:

const nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
    service: "Gmail",
    auth: {
      user: 'example@gmail.com',
      pass: 'app password here'
    }
  });
transporter.sendMail(option, function(error, info){
    if (error) {
      console.log(error);
    } else {
      console.log('Email sent: ' + info.response);
    }
});

screenshot

kdgilang
  • 501
  • 5
  • 7
4

For debugging purpose it is handy to implement a callback function (they never do on the nodemailer github page) which shows the error message (if there is one).

transporter.sendMail({
    from: from,
    to: to,
    subject: subject,
    html: text
}, function(err){
    if(err)
        console.log(err);
})

It helped me solve my problem... Turns out newer versions are not working properly:

"Looks like nodemailer 1.0 has breaking changes so 0.7 must be used instead: http://www.nodemailer.com/

Message posted on nodemailer as of 12/17/15:

Do not upgrade Nodemailer from 0.7 or lower to 1.0 as there are breaking changes. You can continue to use the 0.7 branch as long as you like. See the documentation for 0.7 here."

I found this answer here

Community
  • 1
  • 1
Maarten Meeusen
  • 482
  • 1
  • 9
  • 23
4

And install smtp module as dependency:

npm install smtp

var nodemailer = require('nodemailer');

var transporter = nodemailer.createTransport({
  service: 'gmail',
  type: "SMTP",
  host: "smtp.gmail.com",
  secure: true,
  auth: {
    user: 'writeYourGmailId@gmail.com',
    pass: 'YourGmailPassword'
  }
});

var mailOptions = {
  from: 'xyz.khan704@gmail.com',
  to: 'azran.khan704@gmail.com',
  subject: 'Sending Email to test Node.js nodemailer',
  text: 'That was easy to test!'
};

transporter.sendMail(mailOptions, function(error, info){
  if (error) {
    console.log(error);
  } else {
    console.log('Email sent');
  }
});

Go to https://myaccount.google.com/lesssecureapps and change it ON because Some apps and devices use less secure sign-in technology, which makes your account more vulnerable. You can turn off access for these apps, which we recommend, or turn on access if you want to use them despite the risks.

Fullstack Guy
  • 16,368
  • 3
  • 29
  • 44
Azran Khan
  • 41
  • 3
1

try this code its work for me.

var http = require('http');
var nodemailer = require('nodemailer');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});

  var fromEmail = 'akarthi@xyz.com';
  var toEmail = 'akarthi@xyz.com';

  var transporter = nodemailer.createTransport({
    host: 'domain',
    port: 587,
    secure: false, // use SSL
    debug: true,
      auth: {
        user: 'fromEmail@xyz.com',
        pass: 'userpassword'
      }
  });
   transporter.sendMail({
      from: fromEmail,
      to: toEmail,
      subject: 'Regarding forget password request',
      text: 'This is forget password response from your app',
      html: '<p>Your password is <b>sample</b></p>'
  }, function(error, response){
      if(error){
          console.log('Failed in sending mail');
          console.dir({success: false, existing: false, sendError: true});
          console.dir(error);
          res.end('Failed in sending mail');
      }else{
          console.log('Successful in sending email');
          console.dir({success: true, existing: false, sendError: false});
          console.dir(response);
          res.end('Successful in sending email');
      }
  });
}).listen(8000);
console.log('Server listening on port 8000');

response:

Successful in sending email
{ success: true, existing: false, sendError: false }
{ accepted: [ 'akarthi@xyz.com' ],
  rejected: [],
  response: '250 2.0.0 uAMACW39058154 Message accepted for delivery',
  envelope: 
   { from: 'akarthi@xyz.com',
     to: [ 'akarthi@xyz.com' ] },
  messageId: '1479809555147-33de4987-29d605fa-6ee150f1@xyz.com' }
Clomp
  • 3,168
  • 2
  • 23
  • 36
KARTHIKEYAN.A
  • 18,210
  • 6
  • 124
  • 133
1

You should not use gmail password for it anymore!

Recently google has provided a new method to use in 3rd party apps or APIs. You need to use App Password instead of the gmail password. But for creating it, you need to enable 2-step Authentication mode in your google account:

You can find steps here: https://support.google.com/mail/answer/185833?hl=en

Siamak Ferdos
  • 3,181
  • 5
  • 29
  • 56
1

It is important to note that nodemailer may not work in development. Although, when you will move the application to production it works fine.

  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/33999914) – 0xLogN Mar 14 '23 at 17:55
  • 1
    Sure, I just thought it can solve time and effort to many that are trying to use the package – Giorgos Philippou Mar 16 '23 at 13:38
0

enter image description here

Adding to xShirase answer just providing screenshots where to enable. Also confirm in security that previous attempt was from you.

Xshirase deserves all upvotes.Iam just showing screenshot.

-1

Here is best way send email using gmail

const transporter = nodemailer.createTransport({
    service: 'gmail',
    auth: {
        user: '******@gmail.com',
        pass: '**********',
    },
});

use two authentication from google => security => app password and do fill some stuff get app password

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103