【问题标题】:Why is nodemailer sending duplicate emails?为什么 nodemailer 发送重复的电子邮件?
【发布时间】:2020-07-20 21:20:42
【问题描述】:

所以这是一个非常奇怪的问题,我不希望有人真正回答这个问题,但我在这里尝试看看是否有人遇到过同样的问题。

我注意到的问题是我们的应用程序似乎在发送重复的电子邮件。例如,我可以从我们的应用程序发送一份报告,它会发送该电子邮件一次,然后看起来另一封邮件会在一分钟后发送。

我使用nodemailer 从我们的应用服务器发送电子邮件,我们在办公室使用的默认电子邮件是Outlook v16.0.12130.20272 使用IMAP。这些电子邮件是通过我们的 noreply 电子邮件发送的,我相信该电子邮件是通过 GoDaddy 托管的。

我自己发送了测试电子邮件并查看了网络选项卡以查看是否可能是超时问题,但响应以200 OK status 完成,并且时间也显示为已完成。此外,当我控制台记录响应时,它只发生一次,这让我相信它实际上只发送一封电子邮件。在主机发送电子邮件和我们的收件人实际收到它们之间一定发生了一些事情,但我不太确定。

这是 server.js 文件。这是发出smtp 请求的地方。

var nodemailer = require("nodemailer");

const path = require('path');
const express = require('express');
const http = require('http');
const fs = require('fs');
const socketIO = require('socket.io');
const bodyParser = require('body-parser')



import env from '../env.config.json';

const PORT = require('../env.config.json').SERVER.PORT;
const publicPath = path.join(__dirname, '../public');
import api from './routers/api-routing';
//---------------------------------------------------------------------------

var smtpTransport = nodemailer.createTransport({
    service: env.EMAIL.SERVICE,
    host: env.EMAIL.HOST,
    auth: {
        user:env.EMAIL.AUTH.USER,
        pass:env.EMAIL.AUTH.PASS
    }
});

var mailCounter = 0;
var numPeople = 0;

var app = express();
var server = http.createServer(app);
const port = PORT || 3000;
app.use(express.static(publicPath));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true}));

const io = socketIO(server);
app.use('/api', api(app, io));
// require('./routers/api-routing')(app, io);
//$.get("/send", { to: to, subject: subject).value, text: 'html' }, function (data) { });
app.get('*', function (request, response) {
    if (request.get('x-auth')) console.log("x-auth: ", request.get('x-auth'));
    const proto = request.get('X-Forwarded-Proto');
    if (proto) {
        if (proto === 'http') response.redirect(301, "https://ourdomain.com".concat(request.url));
    }
    response.sendFile(path.resolve(__dirname, '../', 'public', 'index.html'))
    if ((request.url).substring(0, 5) == "/send") {
        var mailOptions = {
            to: request.query.to,
            bcc: request.query.bcc,
            subject: request.query.subject,
            text: request.query.text
        }
        //console.log(mailOptions); Read up on NodeMailer for details.
        smtpTransport.sendMail({  //email options
            from: "COMPANY <noreply@ouremail.com>", // sender address.  Must be the same as authenticated user if using Gmail.
            to: mailOptions.to,
            bcc: "COMPANY <noreply@ouremail.com>",    // sending to itself
            subject: mailOptions.subject, // subject
            html: mailOptions.text, // body
        }, function (error, response) {  //callback
            if (error) {
                console.log(error);
            } else {
                console.log("Message sent");
               //console.log("Amount of people getting this email: " + response.accepted.length);
            }

            smtpTransport.close(); // shut down the connection pool, no more messages.  Comment this line out to continue sending emails.
        });
    }

});



io.on('connection', (socket) => {

    require('./middleware/sockets')(socket);


});

server.listen(port, () => {
  console.log(`Server is up on port ${port}.`);
});

这是我们的 env.config.file 中与电子邮件相关的部分。

"EMAIL": {
    "SERVICE": "Godaddy",
    "HOST": "smtp.gmail.com",
    "AUTH": {
      "USER": "noreply@ouremail.com",
      "PASS": "OURPASS"
    }
  }

如果有人有任何想法或建议,我将非常感激,谢谢!

【问题讨论】:

  • 这里需要ReactJS标签吗?
  • 应该不会,我刚删了。
  • 我也遇到过同样的问题(一分钟后出现重复邮件)。我通过在响应中显式添加“状态(200)”来修复它。让我知道它是否有效!
  • 代码使用了大量的差异技术来导入库,只是一个尝试统一的建议。此外,您正在发送重定向但允许脚本的其余部分运行,这可能是一个问题。 60 秒让我觉得请求超时并再次点击 URL 或其他东西。您还在侦听所有 GET 请求 (*),我会将其限制为您希望此代码实际运行的路由。最后,您确定您只在 node 应用程序中看到控制台输出 1 次吗?如果是这种情况,请检查 GoDaddy。也许您的密件抄送 noreply 会导致自动回复?
  • @Krishna 你是说把 response.status(200) 放在 else 语句中?

标签: javascript node.js express nodemailer


【解决方案1】:

您的电子邮件将根据发送到您服务器的任何请求发送,因此如果您通过浏览器访问它,浏览器将发送两个请求,一个针对请求的路径,一个针对 favicon.ico,您还发送了一个请求 /favicon.ico 时发送电子邮件。

这可能是因为您的路由处理程序配置为:

app.get('*', ...);

这意味着您正在尝试为每个传入的 http 请求发送一封电子邮件,而不管路径如何。

因此,如果您使用浏览器访问主机http://yourdomain/,它将首先请求/,然后浏览器将请求/favicon.ico,从而导致您发送第二封电子邮件。

我的建议是改变这个:

app.get('*', ...);

到这里:

app.get('/', ...);

或者,更具体的例如:

app.get('/sendemail', ...);

因此,您仅在一个特定路径请求上发送电子邮件,它不会发送电子邮件而不发送其他请求,例如网站图标。您可能希望为任何其他路由添加通用 express 404 处理程序。


注意:在 REST 设计中,您可能会发送带有 POST 请求的电子邮件,而不是 GET 请求。 GET 将以只读方式检索资源,不会更改任何状态,因此不会产生发送电子邮件的副作用。注意:这根本与您的问题无关,只是对典型 REST 设计的评论。

【讨论】:

  • 这些都是非常好的观点。我还应该提到重复电子邮件的事情并不总是发生。直到最近才发生,如果这有什么不同的话。
  • @Michael - 为什么不解决这个问题,看看问题是否消失?我无法谈论您的代码的早期版本的行为方式。有几件事可能发生了变化,导致这个问题现在发生。
  • 是的,我正在努力,我只是想指出这一点,仅此而已。
  • @Michael - 您可以通过将"*" 更改为"/" 来查看修复此问题的效果。
  • @jfriend00 browser will send two requests - 为什么你认为这些请求之间会有一分钟的延迟?
【解决方案2】:

一段时间后,我终于弄清楚了这种行为的原因。该问题部分与jfriend00 发布的内容有关。我最终为电子邮件本身制作了一个单独的路由处理程序,这样它就不会干扰主路由处理程序。问题是每个请求仍将通过该路由,因为它正在寻找由* 指示的任何请求,并且如果有人在发出请求而不是 https 的 http 路由上,那么它会创建第二个请求或在我的发送第二封电子邮件。

你可以在这里看到这一行发生的事情:

if (proto) {
        if (proto === 'http') response.redirect(301, "https://ourdomain.com".concat(request.url));
    }

对此的实际解决方法是为电子邮件本身创建一个单独的路由处理程序,然后将我的nginx 服务器配置为重新路由到 https,如果有人转而使用应用程序的 http 路由。在此之后,我们再也没有遇到过重复的电子邮件。

另一种方法是完全删除 ```*```` 路由处理程序并单独设置其他路由。希望这将在不久的将来对某人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-25
    • 1970-01-01
    • 2017-05-16
    • 2015-05-19
    相关资源
    最近更新 更多