# mailer **Repository Path**: OpenFlun/mailer ## Basic Information - **Project Name**: mailer - **Description**: Node.js 邮件发送库;支持 SMTP、SMTP Pool、Sendmail、Stream、JSON、SES 多种传输; - **Primary Language**: Unknown - **License**: ISC - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-11-05 - **Last Updated**: 2026-11-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # @flun/mailer ## 简介 一个简单易用的 Node.js 邮件发送库,支持多种邮件服务商,无需依赖外部邮件测试服务; 本包以 ESM 模块系统编写;只要你的 Node.js 版本大于 22.12,可保留 CJS `require()` 语法调用,否则请使用 `import` 语法; ### 项目运行导图 ```mermaid graph TD A[开始使用] --> B[安装依赖] B --> C[配置邮件参数] C --> D[验证配置] D --> E{配置是否有效?} E -->|是| F[创建传输器] E -->|否| C F --> G[发送邮件] G --> H{发送结果} H -->|成功| I[显示成功信息] H -->|失败| J[显示错误信息] I --> K[结束] J --> K ``` ## 特性 - **安全性**:不依赖外部服务,数据完全可控 - **真实性**:使用真实邮箱测试,结果更准确 - **灵活性**:支持各种邮件服务商(Gmail、Outlook、QQ邮箱等) - **简单性**:安装时在项目根目录动态创建邮件示例,配置更直接,无需理解复杂的测试服务概念 - **配置验证**:发送前可验证配置,确保必要的配置项已填写 - **清晰的错误提示**:指导用户正确使用 ## 包目录结构 随包发布的文件: ``` @flun/mailer/ ├── bin/ │ └── cli.js 命令行入口 ├── lib/ 核心实现:传输器、MIME 编解码、SMTP 连接、DKIM 等 ├── copy-files.js postinstall 脚本,安装时复制 Mail.js ├── index.js 库入口,导出 Mailer 与各传输器 ├── index.d.ts 类型声明 ├── Mail.js 邮件示例模板,mailer example 复制到项目根目录 ├── CHANGELOG.md 更新日志 ├── README.md 本文件 ├── package.json 包配置 └── LICENSE 许可 ``` --- ## 安装前准备 ### 允许安装脚本执行 本包在安装时可能触发某些依赖包的自动脚本(如 `postinstall` 等);如果你的 npm 全局配置或项目配置禁止了脚本执行(例如设置了 `ignore-scripts=true`),可能会导致安装不完整或运行时异常; 推荐在项目根目录的 `package.json` 中添加 `allowScripts` 字段,显式放行本包及其依赖的脚本: ```json { "allowScripts": { "@flun/mailer": true // 如果依赖的其它包(如 bcrypt、electron-winstaller 等)也有脚本,请按需添加,格式相同 } } ``` --- ## 安装 ```sh npm i @flun/mailer ``` --- ## 命令行 包内声明一个 `bin`: | 命令 | 作用 | | -------- | ------------------------------------------ | | `mailer` | 发送邮件、校验配置、生成示例文件、输出版本 | ### 快速开始 ```bash # 一行 URL 配置发送;格式为-> 指令 --smtp-url 协议://账号:密码@服务器:端口 --to 收件方 --subject 主题 --text 正文 mailer send --smtp-url smtps://user:pass@smtp.qq.com:465 --to v@x.com --subject 你好 --text 正文 ``` ### 子命令 | 子命令 | 作用 | | --------- | ---------------------------------------- | | `send` | 发送邮件,需同时提供 SMTP 连接与邮件参数 | | `check` | 校验 SMTP 配置,不实际投递 | | `example` | 在项目根目录生成 `Mail.js` 示例文件 | | `version` | 输出版本信息 | | `help` | 输出帮助;无参数、`-h`、`--help` 行为相同 | ### SMTP 连接(三选一) - `--smtp-url `:完整 URL,如 `smtps://user:pass@smtp.qq.com:465`; 465 端口用 `smtps://`,587 端口用 `smtp://`;账号密码按原样书写; - `--smtp-service `:服务商名(QQ、139、126 等),自动补齐 host/port/secure;须另给 user/pass; - `--smtp-host `:服务器地址;须另给 user/pass; | 参数 | 作用 | | ---------------------------- | -------------------------------------------- | | `--smtp-user ` | 账号 | | `--smtp-pass ` | 密码或授权码 | | `--smtp-port ` | 端口;不填时 secure 为 true 用 465,否则用 587 | | `--smtp-secure ` | 是否启用 SSL;端口 465 时自动为 true | ### 邮件参数 | 参数 | 作用 | | ---------------------- | --------------------------------- | | `--to
` | 收件人,多个用逗号分隔;必填 | | `--subject ` | 主题;必填 | | `--from
` | 发件人,缺省用 SMTP 账号 | | `--text ` | 纯文本正文;与 `--html` 二选一 | | `--html ` | HTML 正文 | | `--cc
` | 抄送,可重复 | | `--bcc
` | 密送,可重复 | | `--reply-to
` | 回复地址 | | `--attach ` | 附件,本地路径/URL/data URL,可重复 | | `--attach-name ` | 对应上一个附件的显示名 | | `--attach-cid ` | 对应上一个附件的 cid | | `--ical ` | iCalendar 事件文件 | 环境变量 `SMTP_SERVICE`、`SMTP_HOST`、`SMTP_PORT`、`SMTP_USER`、`SMTP_PASS`、`SMTP_SECURE` 作默认值,命令行优先; `example` 仅在目标目录存在 `package.json` 时生成文件; --- ## 函数方式 包入口导出两个函数: | 导出 | 作用 | | ----------------- | ------------------------------------------------------------------------------ | | `createTransport` | 创建传输器,入参决定传输方式(SMTP / SMTP Pool / Sendmail / Stream / JSON / SES) | | `validateConfig` | 发送前校验配置,返回校验结果 | ### 快速开始 一行 URL 完成配置,直接发送; ```js import { createTransport } from '@flun/mailer'; // 格式为 协议://账号:密码@服务器:端口;465 端口用 smtps://,587 端口用 smtp:// const transporter = createTransport('smtps://you@example.com:your-password@smtp.qq.com:465'); await transporter.sendMail({ from: 'you@example.com', to: 'recipient@example.com', subject: '测试邮件', text: '这是一封测试邮件' }); ``` ### 完整示例 以下为对象配置方式,可自定义 host、port、secure; ```javascript import { createTransport } from '@flun/mailer'; const transporter = createTransport({ host: 'smtp.your-email-provider.com', // Gmail: smtp.gmail.com; QQ: smtp.qq.com; 163: smtp.163.com port: 587, // 465(SSL) 或 587(TLS) secure: false, // 465 端口填 true,其它端口填 false auth: { user: 'your-email@example.com', pass: 'your-password-or-app-password' } }); transporter.sendMail({ from: 'your-email@example.com', to: 'recipient@example.com', subject: '测试邮件', text: '这是一封测试邮件(text)', html: '这是一封测试邮件(html)' // html 优先级高于 text }, (error, info) => { if (error) console.error('发送失败:', error); else console.log('发送成功:', info.response); }); ``` ### 配置验证 在创建传输器前验证配置的有效性,避免运行时错误; ```javascript import { validateConfig } from '@flun/mailer'; // 1. 验证URL格式配置 const urlConfig = 'smtps://user:pass@smtp.your-email-provider.com:465'; const validation1 = validateConfig(urlConfig); if (!validation1.valid) { console.error('配置错误:', validation1.errors); } else if (validation1.warnings) { console.warn('配置警告:', validation1.warnings); } // 2. 验证对象配置 const objectConfig = { host: 'smtp.your-email-provider.com', port: 587, secure: false, auth: { user: 'your-email@example.com', pass: 'password' } }; const validation2 = validateConfig(objectConfig); if (validation2.valid) { const transporter = createTransport(objectConfig); console.log('传输器创建成功'); } else { console.error('配置无效,无法创建传输器:', validation2.errors); } // 3. 验证无效配置 const invalidConfig = { host: 'smtp.your-email-provider.com', port: 70000, // 无效端口 auth: { user: 'your-email@example.com' // 缺少密码 } }; const validation3 = validateConfig(invalidConfig); console.log('无效配置验证结果:', validation3); ``` --- ## 参考配置 以下为常见邮箱服务商的简写配置,使用 `service` 字段代替 `host` / `port`: ### Gmail ```javascript const transporter = createTransport({ service: 'Gmail', auth: { user: 'your-email@gmail.com', pass: 'your-app-password' // 需启用两步验证并使用应用专用密码 } }); ``` ### QQ 邮箱 ```javascript const transporter = createTransport({ service: 'QQ', auth: { user: 'your-email@qq.com', pass: 'your-authorization-code' // 授权码,非登录密码 } }); ``` ### 163 邮箱 ```javascript const transporter = createTransport({ service: '163', auth: { user: 'your-email@163.com', pass: 'your-authorization-code' // 授权码 } }); ``` --- ### 高级用法 #### 发送带附件的邮件 ```javascript transporter.sendMail({ from: 'your-email@example.com', to: 'recipient@example.com', subject: '带附件的测试邮件', text: '这是一封带附件的测试邮件', html: '这是一封带附件的测试邮件', attachments: [ { filename: 'document.pdf', path: './documents/document.pdf' }, { filename: 'image.png', content: 'base64 encoded string', // 或使用 path 参数 encoding: 'base64' } ] }, (error, info) => { if (error) console.error('发送失败:', error); else console.log('发送成功:', info.response); }); ``` #### 使用 Promise 语法 ```javascript // 使用 async/await async function sendEmail() { try { const info = await transporter.sendMail({ from: 'your-email@example.com', to: 'recipient@example.com', subject: '测试邮件', text: '这是一封测试邮件' }); console.log('邮件发送成功:', info.messageId); } catch (error) { console.error('邮件发送失败:', error); } } sendEmail(); ``` #### 1. SMTP 连接池(高并发场景) ```javascript import { createTransport } from '@flun/mailer'; // 1. 创建连接池传输器 const transporter = createTransport({ pool: true, // 启用连接池 host: 'smtp.gmail.com', port: 465, secure: true, auth: { user: 'your-email@gmail.com', pass: 'your-app-password' }, maxConnections: 5, // 最大连接数 maxMessages: 100, // 每个连接最大邮件数 rateDelta: 1000, // 速率限制时间间隔 rateLimit: 5 // 每秒最多发送5封 }); // 2. 发送多封邮件的示例 const emails = [ { to: 'user1@example.com', name: '用户1' }, { to: 'user2@example.com', name: '用户2' }, { to: 'user3@example.com', name: '用户3' } ]; async function sendBulkEmails() { for (const email of emails) { const mailOptions = { from: '"系统通知" ', to: email.to, subject: `您好 ${email.name}`, html: `

亲爱的 ${email.name},这是一封测试邮件

` }; try { const info = await transporter.sendMail(mailOptions); console.log(`发送给 ${email.name} 成功:`, info.messageId); } catch (error) { console.log(`发送给 ${email.name} 失败:`, error); } } // 关闭连接池 transporter.close(); } sendBulkEmails(); ``` #### 2. Sendmail 传输(Linux/Unix 系统) ```javascript import { createTransport } from '@flun/mailer'; // 1. 创建Sendmail传输器 const transporter = createTransport({ sendmail: true, path: '/usr/sbin/sendmail' // 默认路径,通常不需要指定 }); // 2. 配置邮件内容 const mailOptions = { from: '"系统" ', to: 'admin@example.com', subject: '服务器报警', text: 'CPU使用率超过90%,请及时处理!', html: '

服务器报警

CPU使用率超过90%,请及时处理!

' }; // 3. 发送邮件 transporter.sendMail(mailOptions, (error, info) => { if (error) { console.log('发送失败:', error); } else { console.log('发送成功!'); console.log('响应:', info.response); } }); ``` #### 3. 流传输(用于测试和开发) ```javascript import { createTransport } from '@flun/mailer'; import fs from 'fs'; // 1. 创建流传输器 const transporter = createTransport({ streamTransport: true, buffer: true, // 将邮件内容缓冲到内存 newline: 'unix' // 使用Unix换行符 }); // 2. 配置邮件内容 const mailOptions = { from: '"测试" ', to: 'developer@example.com', subject: '测试邮件 - 不实际发送', text: '这封邮件不会实际发送,只会输出到控制台或文件', html: 'HTML内容', attachments: [ { filename: 'test.txt', content: '这是附件内容' } ] }; // 3. 发送邮件(实际上只是生成邮件源码) transporter.sendMail(mailOptions, (error, info) => { if (error) { console.log('生成邮件失败:', error); } else { console.log('邮件源码:'); console.log(info.message.toString()); // 可选:保存到文件 fs.writeFileSync('debug-email.eml', info.message.toString()); console.log('邮件已保存到 debug-email.eml'); } }); ``` #### 4. JSON 传输(用于调试) ```javascript import { createTransport } from '@flun/mailer'; // 1. 创建JSON传输器 const transporter = createTransport({ jsonTransport: true }); // 2. 配置邮件内容 const mailOptions = { from: '"调试" ', to: 'test@example.com, test2@example.com', subject: '调试邮件', text: '这封邮件会返回JSON格式的信息', html: '调试内容' }; // 3. 发送邮件 transporter.sendMail(mailOptions, (error, info) => { if (error) { console.log('错误:', error); } else { console.log('邮件信息(JSON格式):'); console.log(JSON.stringify(info.message, null, 2)); // info.message 包含: // - envelope: 信封信息(发件人、收件人) // - messageId: 邮件ID // - response: 响应信息 } }); ``` #### 5. SES 传输(AWS 亚马逊服务) ```javascript import { createTransport } from '@flun/mailer'; import { SESClient } from '@aws-sdk/client-ses'; // 1. 配置 AWS SES const sesClient = new SESClient({ region: 'us-east-1', // 你的AWS区域 credentials: { accessKeyId: '你的AccessKey', secretAccessKey: '你的SecretKey' } }); // 2. 创建SES传输器 const transporter = createTransport({ SES: { ses: sesClient, aws: {} } }); // 3. 配置邮件内容 const mailOptions = { from: '"AWS SES" ', // 必须是验证过的邮箱 to: 'recipient@example.com', subject: '来自AWS SES的测试邮件', text: '这封邮件通过Amazon SES发送', html: '

AWS SES测试

这封邮件通过Amazon SES发送

' }; // 4. 发送邮件 async function sendWithSES() { try { const info = await transporter.sendMail(mailOptions); console.log('SES发送成功!'); console.log('Message ID:', info.messageId); console.log('响应:', info.response); } catch (error) { console.log('SES发送失败:', error); } } sendWithSES(); ``` #### 6. 使用连接字符串的简便方式 ```javascript import { createTransport } from '@flun/mailer'; // 1. 使用连接字符串创建传输器 const transporter = createTransport( 'smtps://username:password@smtp.gmail.com:465' ); // 2. 配置邮件内容 const mailOptions = { from: '"测试" ', to: 'friend@example.com', subject: '连接字符串示例', text: '使用连接字符串配置SMTP' }; // 3. 发送邮件 transporter.sendMail(mailOptions) .then(info => { console.log('发送成功:', info.messageId); }) .catch(error => { console.log('发送失败:', error); }); ``` 每个示例都包含了: 1. **配置传输器** - 创建特定类型的邮件传输器 2. **设置邮件内容** - 定义发件人、收件人、主题、内容等 3. **发送邮件** - 执行发送操作并处理结果 对于生产环境,推荐使用 SMTP 或 SES;对于开发和测试,可以使用流传输或 JSON 传输; --- ## 常见问题 ### 错误提示覆盖哪些类型? 库提供了详细的错误信息,帮助快速定位问题: - **配置错误**:如缺少必要参数、无效的端口号等 - **连接错误**:如无法连接到 SMTP 服务器 - **认证错误**:如用户名或密码错误 - **发送错误**:如收件人地址无效、邮件被拒绝等 ### 使用前需要注意什么? 1. 确保您的邮箱已开启 SMTP 服务 2. 部分邮箱服务商需要使用授权码而非登录密码 3. 建议在生产环境中使用环境变量存储敏感信息 4. 发送频率过高可能被邮箱服务商限制 ## 许可证 ISC --- ## 贡献 - 源码:[GitHub](https://github.com/OpenFlun/mailer) - 中国镜像:[gitee](https://gitee.com/OpenFlun/mailer) - 问题反馈:[Issues](https://github.com/OpenFlun/mailer/issues) - 主页:[npm 包页面](https://www.npmjs.com/package/@flun/mailer#readme)