1panel搭建邮局问题
近期准备开发一个“记账”系统,考虑到有重置密码,到表到邮箱的功能,于是在服务器上搭建了一个邮局服务。之后出现了一个问题,服务是可以正常接收邮件,代码没有报错,但是服务器却没有收到第三方的邮件,以及第三方邮件也没接收到服务器的邮件。
问题出现的原因是,1panel 搭建的邮局服务,我接着把涉及到的端口全部开放,后面查询资料说是需要 25 端口,但是我开放了 25 端口,还是没有解决问题。之后我看了一下服务器的 ip 所属的区域内 25 端口全部封禁,导致邮件无法发送。尽管服务器开启了 25 端口,但是由于区域内 25 端口封禁,导致邮件无法发送。后联系厂商之后,说该服务器区域暂不支持。
所以,暂时不考虑邮箱功能。所以我也就砍掉了对应的功能,只保留了登录功能。
接下来,大致记录一下邮局如何搭建:

- 准备好域名,服务器,服务器安装好 1panel 面板。
- 1panel 面板,应用市场找到
Maddy Mail Server应用。然后接着安装就好了。 - 首次安装时运行不起来的,是因为需要配置对应的证书。具体的操作例如上图的步骤,一步步完成就可以了。
代码模板
import nodemailer from "nodemailer";
import dotenv from "dotenv";
// 加载环境变量
dotenv.config();
/**
* 创建 Stalwart SMTP 传输器
*/
const createTransporter = () => {
return nodemailer.createTransport({
host: process.env.STALWART_SMTP_HOST || "localhost", // Stalwart SMTP 服务器地址
port: parseInt(process.env.STALWART_SMTP_PORT || "587"), // SMTP 端口(587 用于 STARTTLS,465 用于 SSL)
secure: process.env.STALWART_SMTP_SECURE === "true", // true 表示使用 SSL,false 表示使用 STARTTLS
auth: {
user: process.env.STALWART_SMTP_USER, // SMTP 用户名/邮箱
pass: process.env.STALWART_SMTP_PASS, // SMTP 密码
},
// 调试与超时(方便排查 Unexpected socket close)
logger: false, // 在控制台输出 SMTP 日志
debug: false,
connectionTimeout: 10_000, // 连接阶段超时 10 秒
greetingTimeout: 10_000, // 等待服务器问候语超时
socketTimeout: 20_000, // 整个会话的 socket 超时
// 可选:TLS 选项
tls: {
rejectUnauthorized:
process.env.STALWART_SMTP_TLS_REJECT_UNAUTHORIZED !== "false", // 在生产环境中建议设为 true
},
});
};
/**
* 发送邮件
* @param {Object} options - 邮件选项
* @param {string|string[]} options.to - 收件人邮箱(支持字符串或数组)
* @param {string} options.subject - 邮件主题
* @param {string} options.text - 纯文本内容
* @param {string} options.html - HTML 内容
* @param {string} [options.from] - 发件人(可选,默认使用环境变量)
* @param {string|string[]} [options.cc] - 抄送(可选)
* @param {string|string[]} [options.bcc] - 密送(可选)
*/
export const sendEmail = async options => {
try {
const transporter = createTransporter();
// 验证连接
await transporter.verify();
console.log("✓ SMTP 服务器连接成功");
// 准备邮件选项
const mailOptions = {
from:
options.from ||
process.env.STALWART_SMTP_FROM ||
process.env.STALWART_SMTP_USER,
to: options.to,
subject: options.subject,
text: options.text,
html: options.html,
cc: options.cc,
bcc: options.bcc,
};
// 发送邮件
const info = await transporter.sendMail(mailOptions);
console.log("✓ 邮件发送成功");
console.log(" 消息 ID:", info.messageId);
console.log(" 响应:", info.response);
return info;
} catch (error) {
console.error("✗ 邮件发送失败:", error.message);
throw error;
}
};
sendEmail({
to: "其他邮箱地址",
subject: "测试邮件 - 使用 Stalwart",
text: "这是一封通过 Stalwart 邮件服务器发送的测试邮件。",
html: "<p>这是一封通过 <strong>Stalwart</strong> 邮件服务器发送的测试邮件。</p>",
})
.then(() => {
console.log("\n邮件发送完成!");
process.exit(0);
})
.catch(error => {
console.error("\n邮件发送失败:", error);
process.exit(1);
});