Node.js: smtp-server и nodemailer не отправляют сообщения на удалённые хосты, а сохраняют на localhost
Есть сервер на smtp-server, есть отправщик на nodemailer. Письма с удалённых адресов принимаются, но когда я пытаюсь отправить со своего сервера письмо на удалённый адрес, оно не доходит, а принимается как будто извне. В чём причина?
Вот код сервера и отправителя (некоторые адреса и пароли заменены):
server.js
"use strict";
const DOMAIN = "sode.su";
const fs = require("fs");
const SMTPServer = require("smtp-server").SMTPServer;
const parser = require("mailparser").simpleParser;
const sqlite3 = require("sqlite3").verbose();
const server = new SMTPServer({
secure: false,
key: fs.readFileSync("/etc/letsencrypt/live/sode.su/privkey.pem"),
cert: fs.readFileSync("/etc/letsencrypt/live/sode.su/cert.pem"),
onRcptTo({address}, session, callback)
{
if (address.startsWith("noreply@"))
return callback(new Error(`Address ${address} is not allowed receiver`));
callback();
},
onAuth(auth, session, callback)
{
if (auth.username !== "!SECRET!" || auth.password !== "!SECRET!")
return callback(new Error("Invalid username or password!"));
callback(null, { user: 1 });
},
onConnect(session, callback) {
return callback();
},
onClose(session) {},
onMailFrom(address, session, callback) {
return callback();
},
authOptional: true,
onData(stream, session, callback)
{
// Stream – Поток с данными письма. Callback вызывается по окончанию парсинга.
// в этом обработчике мы будем парсить письмо.
var parts = [];
var buffer;
stream.on("data", data => {
parts.push(data);
});
stream.on("end", () => {
buffer = Buffer.concat(parts);
parser(buffer, {}, (err, mail) => {
try {
if (err)
return console.error(err);
if (!mail.to) {
mail.to = "[email protected]";
}
mail.headers = undefined;
mail.headerLines = undefined;
mail.textAsHtml = undefined;
mail.from = mail.from.text;
for (let to_val of (mail.to.value ? mail.to.value : mail.to[0].value)) {
if (to_val.address.endsWith("@" + DOMAIN)) {
mail.to = to_val.address.split("@")[0];
break;
}
}
for (let att in mail.attachments) {
mail.attachments[att].content = mail.attachments[att].content.toString("base64");
}
const json = JSON.stringify(mail);
const path = "/home/mail/" + DOMAIN + "/" + mail.to + "/" + mail.messageId;
// если письмо переадресовано, а адресовалось не на sode.su, положить в admin.
if (mail.to.value) {
mail.to = "admin";
}
mail.to = mail.to.toLowerCase();
console.log(mail.to + " :: " + mail.messageId);
// если у сообщения нет id, дописать его в конец общего списка в .wo_id/
if (!mail.messageId) {
fs.appendFileSync("/home/mail/" + DOMAIN + "/.wo_id/" + mail.to, buffer + "\n\n\n");
return callback();
} else {
// проверяем файл на существование
fs.access(path, err => {
try {
if (err) {
// проверяем каталог адресата на существование
fs.access("/home/mail/" + DOMAIN + "/" + mail.to, err => {
// если каталога нет, создаём его
if (err) {
fs.mkdirSync("/home/mail/" + DOMAIN + "/" + mail.to);
}
// записываем разобранное письмо в файл
fs.writeFileSync("/home/mail/" + DOMAIN + "/" + mail.to + "/" + mail.messageId, json);
try {
// надо записать письмо и в бд
var db = new sqlite3.Database("/home/mail/sode.su/mail.db");
db.get("select id from addresses where name = ?", [ mail.to ], (err, row) => {
if (err)
return console.error(err);
// если такого адресата в бд ещё нет, создаём
if (!row) {
db.run("insert into addresses (name) values (?)", [ mail.to ], err => {
if (err)
return console.error(err);
// и получаем его id
db.get("select id from addresses where name = ?", [ mail.to ], (err, row) => {
if (err)
return console.error(err);
var id = row["id"];
// вставляем инфу о письме
db.run("insert into messages (message_id, addressee_id) values (?, ?)", [ mail.messageId, id ], err => {
if (err)
return console.error(err);
});
});
});
} else {
var id = row["id"];
// вставляем инфу о письме
db.run("insert into messages (message_id, addressee_id) values (?, ?)", [ mail.messageId, id ], err => {
if (err)
return console.error(err);
});
}
});
} catch (err) {
console.error(err);
} finally {
db.close();
}
});
// если файл с таким id сообщения уже есть, дописать его в конец общего списка в .err/
} else {
fs.appendFileSync("/home/mail/" + DOMAIN + "/.err/" + mail.to, json + "\n\n\n");
}
} catch(err) {
console.error(err);
}
return callback();
});
}
} catch(err) {
console.error(err);
}
});
});
}
});
process.on('uncaughtException', err => {
console.error("Caught exception: " + err);
});
server.listen(25);
sender.js
const nodemailer = require("nodemailer");
(async () => {
try {
var transporter = nodemailer.createTransport({
host: "localhost",
port: 25,
secure: false,
auth: {
user: "!SECRET!",
pass: "!SECRET!"
},
tls: {
rejectUnauthorized: false
},
});
var mail_options = {
from: "!SECRET!",
to: "!SECRET!",
subject: "Hello",
text: "Hello!"
};
var info = await transporter.sendMail(mail_options);
console.log("Message sent:\n", info);
} catch (err) {
console.error(err);
}
}) ();
Кода много, но я не знаю, где именно может быть проблема.