使用 nodemailer 通过 Node.js 发送电子邮件不起作用

Posted

技术标签:

【中文标题】使用 nodemailer 通过 Node.js 发送电子邮件不起作用【英文标题】:Sending email via Node.js using nodemailer is not working 【发布时间】:2014-11-29 13:06:30 【问题描述】:

我已经在本地 (http://localhost:8080) 设置了一个基本的 NodeJS 服务器(使用 nodemailer 模块),以便我可以测试服务器是否可以真正发送电子邮件。

如果我正确理解了 SMTP 选项(如果我错了请纠正我),我可以尝试从我的服务器向某人的电子邮件帐户发送电子邮件直接 我可以发送电子邮件,仍然使用 Node.js,但是通过一个实际的电子邮件帐户(在本例中是我的个人 Gmail 帐户),即使用 SMTP。此选项要求我通过 NodeJS 远程登录该帐户。

所以在下面的服务器中,我实际上是在尝试使用 NodeJs 将电子邮件从我的个人电子邮件帐户发送到我的个人电子邮件帐户。

这是我的简单服务器:

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

但是,它不起作用。我收到了 Google 发来的电子邮件:

Google 帐户:登录尝试被阻止 如果这是你 您可以切换到谷歌制作的应用程序(例如 Gmail)来访问您的帐户(推荐)或更改 您在https://www.google.com/settings/security/lesssecureapps 的设置,这样您的帐户就没有 受到现代安全标准的更长时间的保护。

我在 nodemailer GitHub 页面上找不到上述问题的解决方案。有没有人有解决方案/建议?

谢谢! :-)

【问题讨论】:

【参考方案1】:

答案在谷歌的消息中。

转至:https://www.google.com/settings/security/lesssecureapps

访问不太安全的应用程序设置为启用

对于第二部分的问题,并针对

我实际上只是按照 nodemailer github 页面中的步骤进行操作,因此我的代码中没有错误

我会推荐你​​到 nodemailer 的 github 页面,以及这段代码:

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

);

它与您的代码略有不同,事实上您有:nodemailer.createTransport("SMTP"。 删除 SMTP 参数,它可以工作(刚刚测试过)。另外,为什么将它封装在 http 服务器中?以下作品:

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

【讨论】:

我想避免认为它实际上可能使我的帐户更容易受到攻击。我想我可以通过一些我可能忽略的 nodemailer 设置绕过它。也许设置一些额外的认证属性。谢谢不过! 现在启用了它,我知道从 Google 收到通知的时间更长,但我也没有收到电子邮件,所以恐怕它仍然无法正常工作.. 尝试使用不同的“收件人”和“发件人”地址,我过去曾在 gmail 和除我自己以外的任何其他收件人工作时遇到过类似的问题。 这违背了将电子邮件从我的站点发送到我的个人 Gmail 帐户的目的。创建一个新的 Gmail 帐户以便我可以将其用作 from:in nodemailer 没有多大意义,除了这么大的“黑客”之外,必须有其他方法 我建议它更多地作为一个调试过程,看看问题是来自你的代码还是来自 gmail。【参考方案2】:

过时:JSON 文件输出中不再存在 refreshToken 和 accessToken

对于那些真正想使用 OAuth2/不想让应用“不那么安全”的人,你可以通过

    在google API console 中搜索“Gmail API”并点击“启用” 按照https://developers.google.com/gmail/api/quickstart/nodejs 的步骤进行操作。在 quickstart.js 文件中,将 quickstart js 文件中的SCOPES var 从['https://www.googleapis.com/auth/gmail.readonly'] 更改为['https://mail.google.com/'],如https://nodemailer.com/smtp/oauth2/ 故障排除中所建议的那样 按照(2)中的步骤,生成的JSON文件将包含OAuth2 Examples for Nodemailer中需要的acessTokenrefreshTokenexpires属性

这样你就可以像下面这样使用 OAuth2 身份验证

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

而不是以明文形式存储您的 gmail 密码并降低您帐户的安全性。

【讨论】:

不再有效,accessToken 和 refreshToken 不再存在于该文件中 为了让它工作,我结合了这个答案传输定义(没有指定 accessToken 和过期)和这篇使用谷歌的 oauth 游乐场获取刷新令牌的帖子:medium.com/@pandeysoni/… 我的 gmail-nodejs-quickstart.json 中没有 SCOPES 变量 @CaptRisky 回复:您的评论“该文件中不再存在 accessToken 和 refreshToken”完全不准确。我按照说明操作,它确实生成了一个包含所有值的 token.json 文件:access_token、refresh_token、scope、token_type 和 expiry_date。 @ironicaldiction 希望你能给我一些建议。我已按照您上面概述的所有步骤进行操作,但每次访问令牌过期时,我的 nodejs 应用程序都无法发送电子邮件。具体来说,我在 Postman "code": "EAUTH", "command": "AUTH XOAUTH2" 中收到以下消息响应。有什么想法吗?【参考方案3】:

我只是将我的域设置为:smtp.gmail.com 并且它可以工作。我正在使用 VPS Vultr。

代码:

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

我的 ejs 模板(e-mail.ejs):

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

确保:

安装 ejs:npm install ejs --save 安装nodemailer:npm install nodemailer --save ping smtp.gmail.com 有效:ping smtp.gmail.com 将 xxx@gmail.com 更改为您的 gmail 电子邮件 将 yyy@gmail.com 更改为您要发送电子邮件的电子邮件 Enable less secure apps Disable Captcha temporarily

祝你有美好的一天;)

【讨论】:

使用port: 465 ?它有什么不同吗?另外,如果你有host:,那是否不需要添加service: 'Gmail' smtp 默认端口为:25、465 和 587,因此port: 465 对使其显式很重要。作为 nodemailer 文档,对于 createTransport 这个 service 属性不可用,只有 host;【参考方案4】:

虽然上述答案确实有效,但我想指出,您可以通过以下 两个 步骤降低 Gmail 的安全性。

第 1 步

Google 帐户:登录尝试被阻止 如果这是您您可以切换到由 Google 开发的应用程序(例如 Gmail)来访问您的帐户(推荐)或在 https://www.google.com/settings/security/lesssecureapps 更改您的设置,以便您的帐户不再受到保护符合现代安全标准。

第 2 步

除了启用允许安全性较低的应用之外,您可能还需要导航到 https://accounts.google.com/DisplayUnlockCaptcha 并点击继续。

【讨论】:

那是缺少的步骤:accounts.google.com/DisplayUnlockCaptcha 谢谢!!【参考方案5】:

您只需要谷歌身份验证的应用程序密码,然后在您的代码中替换您的谷歌密码。 去这里https://myaccount.google.com/apppasswords

示例代码:

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

【讨论】:

不知道为什么,但这适用于本地主机,而不是我的暂存环境 @HarpreetSingh 嗨,它可以在天蓝色的云环境中工作吗?对我来说,它也在本地工作,但不在云端。如果您能对此进行更新,这对我将非常有用.. @sasi,它以某种方式起作用,但我不记得如何。对不起【参考方案6】:

出于调试目的,实现一个回调函数(他们从不在 nodemailer github 页面上执行)很方便,它显示错误消息(如果有的话)。

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

它帮助我解决了我的问题...结果新版本无法正常工作:

“看起来 nodemailer 1.0 有重大更改,因此必须改用 0.7:http://www.nodemailer.com/

截至 2015 年 12 月 17 日在 nodemailer 上发布的消息:

不要将 Nodemailer 从 0.7 或更低版本升级到 1.0,因为存在重大更改。只要你愿意,你可以继续使用 0.7 分支。请参阅 0.7 here 的文档。”

我找到了这个答案here

【讨论】:

【参考方案7】:

并安装 smtp 模块作为依赖:

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

转到 https://myaccount.google.com/lesssecureapps 并将其更改为 ON 因为 某些应用程序和设备使用的登录技术不太安全,这使您的帐户更容易受到攻击。您可以关闭我们推荐的这些应用程序的访问权限,或者如果您想使用这些应用程序,尽管存在风险,也可以打开访问权限。

【讨论】:

【参考方案8】:

试试这个代码,它对我有用。

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

回复:

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' 

【讨论】:

【参考方案9】:

添加到 xShirase 答案只是提供屏幕截图在哪里启用。还要安全地确认之前的尝试来自您。

Xshirase 值得大家点赞。我只是显示屏幕截图。

【讨论】:

以上是关于使用 nodemailer 通过 Node.js 发送电子邮件不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Node.js Nodemailer 和 SES - 错误:未定义传输方法

Node.js使用Nodemailer发送邮件

工具Node.js邮件发送组件- Nodemailer 1.0发布

Node.js使用NodeMailer发送邮件

node.js使用Nodemailer发送邮件

使用 node.js、node mailer 和 nodemailer-mailgun-transport 发送模板化电子邮件