最近我不得不使用CloudFlare隐藏我的IP地址,但是我的MX记录指向我自己的域名,我不能。
我知道Mailgun可以将所有电子邮件转发到user@example.com到Gmail,但我不想这样做。我希望这封电子邮件可以转发到example.com自己的SMTP服务器上。
我决定使用Mailgun catch_all()
和forward("https://exmaple.com/incoming-email?key=SECRET_KEY")
,并为此编写了一些node.js代码。
var nodemailer = require('nodemailer');
var express = require('express');
var multer = require('multer');
var router = express.Router();
var KEY = 'SECRET_KEY';
var ADDITIONAL_HEADERS = ['timestamp', 'token', 'signature', 'mime-version'];
var transporter = nodemailer.createTransport('smtp://127.0.0.1');
var storage = multer.memoryStorage();
var upload = multer({
storage: storage
});
router.post('/', upload.any(), function (req, res, next) {
if (!req.query.key || req.query.key !== KEY) {
res.sendStatus(403);
return;
}
console.log('Incoming mail: ', req.body.From);
req.body.to = req.body.To;
req.body.cc = req.body.Cc;
req.body.from = req.body.From;
req.body.date = req.body.Date;
req.body.references = req.body.References;
req.body.replyTo = req.body['Reply-To'];
req.body.inReplyTo = req.body['In-Reply-To'];
req.body.messageId = req.body['Message-Id'];
req.body.html = req.body['body-html'];
req.body.text = req.body['body-plain'];
req.body.headers = {};
for (var key in req.body) {
if (key.toLowerCase().indexOf('X-') !== -1 ||
ADDITIONAL_HEADERS.indexOf(key.toLowerCase()) !== -1) {
req.body.headers[key] = req.body[key];
}
}
if (req.files) {
req.body.attachments = req.files;
req.body.attachments.forEach(function (attachment) {
attachment.filename = attachment.originalname;
attachment.contentType = attachment.mimetype;
attachment.content = attachment.buffer;
});
}
transporter.sendMail(req.body, function (err, info) {
if (err) {
console.log(err);
res.status(400).send(err);
return;
}
console.log(info);
res.send(info);
});
});
module.exports = router;
如您所见,代码可以将任何传入的电子邮件转发到localhost SMTP服务器。使用代码,我可以使用user@example.com接收电子邮件。收到的电子邮件将具有正确的from,to,cc,subject和body甚至附件。
然而,一天后,我被迫取消订阅Arch Linux邮件列表,并且有人通过电子邮件发送给我:
您的邮件服务器似乎配置错误并至少发送 它从邮件列表收到的一些邮件返回列表。它也是 删除过程中的一些标题,帮助mailman检测这样的标题 行为。由于缺少这些标题,mailman将发送邮件 再次向所有人发出,导致永无止境的循环。
在我求助之后,我还收到了一些电子邮件,表明我在此期间无法收到来自邮件列表的任何电子邮件。
为什么会出错?什么是"一些标题"在转发/包装过程中删除的电子邮件中?是Mailgun的问题还是我自己的问题?如果这是我的问题,可以在上面的代码中添加什么?感谢。
答案 0 :(得分:1)
我发现当电子邮件是您的密件抄送时,邮件将显示为:
因此,当使用问题中的代码时,邮件将由node.js代码处理,然后邮件将使用smtp://127.0.0.1
发送回announce@example-mailing-list.com,从而导致无限循环。
我已更新我的代码,以便从收件人列表中查找我的域的所有电子邮件地址,并将其设置为To
字段,并且无限循环不再出现。
例如,收件人列表将显示为:announce@example-mailing-list.com, you@example.com
,因此我发现所有以@example.com
结尾的电子邮件地址并将其设为To
字段。
警告:但有些信息会丢失,就像我再也看不到电子邮件的原始To
字段了。但是,您可以将原始To
字段附加到任何字段,例如subject
。
var nodemailer = require('nodemailer');
var express = require('express');
var multer = require('multer');
var router = express.Router();
var MY_DOMAIN = 'example.com';
var KEY = 'SECRET_KEY;
var ADDITIONAL_HEADERS = ['timestamp', 'token', 'signature', 'mime-version',
'return-path', 'dkim-signature'
];
var transporter = nodemailer.createTransport('smtp://127.0.0.1');
var storage = multer.memoryStorage();
var upload = multer({
storage: storage
});
router.post('/', upload.any(), function (req, res, next) {
if (!req.query.key || req.query.key !== KEY) {
res.sendStatus(403);
return;
}
console.log('Incoming mail: ', req.body.From);
req.body.to = req.body.recipient.split(', ').filter(email => email.indexOf('@' + MY_DOMAIN) !== -1);
req.body.from = req.body.From;
req.body.date = req.body.Date;
req.body.references = req.body.References;
req.body.replyTo = req.body['Reply-To'];
req.body.inReplyTo = req.body['In-Reply-To'];
req.body.messageId = req.body['Message-Id'];
req.body.html = req.body['body-html'];
req.body.text = req.body['body-plain'];
req.body.headers = {};
for (var key in req.body) {
if (key.toLowerCase().indexOf('x-') !== -1 ||
ADDITIONAL_HEADERS.indexOf(key.toLowerCase()) !== -1) {
req.body.headers[key] = req.body[key];
}
}
console.log('Params: ' + JSON.stringify(req.body));
if (req.files) {
req.body.attachments = req.files;
req.body.attachments.forEach(function (attachment) {
attachment.filename = attachment.originalname;
attachment.contentType = attachment.mimetype;
attachment.content = attachment.buffer;
});
}
transporter.sendMail(req.body, function (err, info) {
if (err) {
console.log(err);
res.status(400).send(err);
return;
}
console.log(info);
res.send(info);
});
});
module.exports = router;
答案 1 :(得分:0)
电子邮件不仅具有To标头,还具有SMTP RCPT TO
值。此值可能与电子邮件中包含的To标头不同。
请参阅:In SMTP, must the RCPT TO: and TO: match?
您的代码似乎使用邮件内容,但似乎没有单独处理传输收件人(SMTP RCPT TO
)。我不知道mailgun是否提供了这个值。
只需将邮件提交到您的smtp服务器,沿途的某些库可能会从To标头中提取收件人,但是对于邮件列表,这通常是不正确的。