跳转到内容

$mail - Mail API

更新: 2026/9/23 字数: 0 字 时长: 0 分钟

$mail.open(options[, callback])

  • options {Object} 连接配置
    • account {string} 邮箱地址
    • password {string} 授权码(不是登录密码)
    • smtp {Object} SMTP 服务器配置(可选,自动识别可省略)
      • host {string} SMTP 服务器地址
      • port {number} SMTP 端口
    • imap {Object} IMAP 服务器配置(仅发信模式请勿传;可选,自动识别可省略)
      • host {string} IMAP 服务器地址
      • port {number} IMAP 端口
    • ssl {boolean} 是否启用 SSL,默认 true
    • startTls {boolean} 是否启用 STARTTLS,默认 false
    • folder {Object} 自定义文件夹名称(可选,仅发信模式无效
      • sent {string} 已发送文件夹名称
      • drafts {string} 草稿箱文件夹名称
      • deleted {string} 已删除文件夹名称
      • junk {string} 垃圾邮件文件夹名称
  • callback {Object} 连接回调
    • onOpen(mail) 连接成功时回调,mailMail
  • 返回 Mail,失败抛出异常

连接邮件服务器,连接失败会抛出异常。

SSL 与 STARTTLS 区别

两者都是邮件传输加密方式。

  • SSL:建立连接时立即加密(通常使用 465 端口)
  • STARTTLS:先建立普通连接,再升级为 TLS(通常使用 587 端口)

推荐优先使用邮箱官方推荐的配置。

常见邮箱默认文件夹

不同邮箱服务商的系统文件夹名称可能不同,如果自动识别失败,可以通过 folder 参数手动指定。

类型常见邮箱收件箱已发送草稿箱已删除垃圾邮件
QQ 系QQ、Foxmail、腾讯企业邮、腾讯云邮箱INBOXSent MessagesDraftsDeleted MessagesJunk
网易系163、126、网易企业邮、网易免费企业邮、阿里企业邮、阿里云邮箱、钉钉邮箱、139、189、沃邮箱、新浪、搜狐INBOX已发送草稿箱已删除垃圾邮件
Gmail(中文)Gmail 中文界面INBOX[Gmail]/已发邮件[Gmail]/草稿[Gmail]/已删除邮件[Gmail]/垃圾邮件
Gmail(英文)Gmail EnglishINBOX[Gmail]/Sent Mail[Gmail]/Drafts[Gmail]/Trash[Gmail]/Spam
Outlook 系Outlook、Office365INBOXSent ItemsDraftsDeleted ItemsJunk Email
YahooYahooINBOXSentDraftTrashBulk Mail
Apple 系iCloudINBOXSentDraftsTrashJunk
AOLAOLINBOXSentDraftsTrashSpam
ZohoZohoINBOXSentDraftsTrashSpam
Mail.comMail.comINBOXSentDraftsTrashSpam
GMXGMXINBOXSentDraftsTrashSpam
YandexYandexINBOXSentDraftsTrashSpam
FastMailFastMailINBOXSentDraftsTrashSpam
ProtonMail BridgeProtonMail BridgeINBOXSentDraftsTrashSpam

例如:

js
folder: {
    sent: "Sent Messages",
    drafts: "Drafts",
    deleted: "Deleted Messages",
    junk: "Junk"
}
js
folder: {
    sent: "已发送",
    drafts: "草稿箱",
    deleted: "已删除",
    junk: "垃圾邮件"
}
js
folder: {
    sent: "[Gmail]/Sent Mail",
    drafts: "[Gmail]/Drafts",
    deleted: "[Gmail]/Trash",
    junk: "[Gmail]/Spam"
}
js
folder: {
    sent: "Sent Items",
    drafts: "Drafts",
    deleted: "Deleted Items",
    junk: "Junk Email"
}

示例

js
// 使用自动识别(根据邮箱域名自动配置)
// 注意:password 填写的是授权码,不是登录密码

var mail = $mail.open({
    account: "[email protected]",
    password: "your_auth_code",  // 授权码
}, {
    onOpen: function (mail) {
        console.log("✅ 连接成功");
        console.log("📧 账号:", mail.account());


    }
});
var folderNames = mail.folderNames()
console.log("📁 文件夹列表:", folderNames);
var inbox = mail.inbox();
console.log("📥 收件箱:", inbox.size(), "封邮件");
console.log("📥 未读:", inbox.unreadCount(), "封");

mail.close();
js
// 手动配置(适用于自定义邮箱或自动识别失败的场景)
var mail = $mail.open(

    {
        account: "[email protected]",
        password: "your_auth_code",  // 授权码

        smtp: {
            host: "smtp.company.com",
            port: 465
        },
        imap: {
            host: "imap.company.com",
            port: 993
        },
        ssl: true,
        startTls: false,

        // 自定义文件夹名称
        folder: {
            sent: "Sent Messages",
            drafts: "Drafts",
            deleted: "Deleted Messages",
            junk: "Junk"
        }
    },
    {
        onOpen: function (mail) {
            console.log("✅ 连接成功");
            console.log("📧 账号:", mail.account());
        }
    });
var folderNames = mail.folderNames()
console.log("📁 文件夹列表:", folderNames);
var inbox = mail.inbox();
console.log("📥 收件箱:", inbox.size(), "封邮件");
console.log("📥 未读:", inbox.unreadCount(), "封");

mail.close();
js

var mail = $mail.open({
    account: "[email protected]",
    password: "your_auth_code",  // 授权码
    ssl: false,
    startTls: false
}, {
    onOpen: function (mail) {
        console.log("✅ 连接成功");
        console.log("📧 账号:", mail.account());


    }
});
var folderNames = mail.folderNames()
console.log("📁 文件夹列表:", folderNames);
var inbox = mail.inbox();
console.log("📥 收件箱:", inbox.size(), "封邮件");
console.log("📥 未读:", inbox.unreadCount(), "封");

mail.close();
js
// 适用于只提供 SMTP 的服务商(如腾讯云邮件推送、SendGrid 等)
// 不传 imap 参数,只发不收

var mail = $mail.open({
    account: "[email protected]",
    password: "your_smtp_password",
    smtp: {
        host: "smtp.example.com",
        port: 465
    },
    ssl: true,
    startTls: false
}, {
    onOpen: function (mail) {
        console.log("✅ 连接成功");
        console.log("📧 账号:", mail.account());
    }
});

// ⚠️ 仅发信模式下,以下方法不可用:
// mail.inbox() / mail.sent() / mail.drafts() / mail.deleted() / mail.junk()
// mail.folders() / mail.folderNames() / mail.reply(uid) / mail.forward(uid)

mail.compose()
    .to("[email protected]")
    .subject("仅发信模式测试")
    .text("这封邮件通过 SMTP Only 发送。")
    .send();

console.log("✅ 已发送");
mail.close();

连接失败排查

如果无法连接邮件服务器,请检查以下内容:

可能原因

  • 邮箱账号或授权码错误
  • 授权码已失效
  • 未开启 IMAP / SMTP 服务
  • SMTP 或 IMAP 地址、端口填写错误

建议排查

  • 使用邮箱授权码,而不是登录密码
  • 确认已开启 IMAP / SMTP
  • 核对服务器地址和端口
  • 常见邮箱可先尝试自动识别配置
  • 自动识别失败时,请手动填写 SMTP、IMAP 参数

Mail

$mail.open() 返回,代表一个邮件会话。

Mail.account()

  • 返回 {string} 邮箱账号

获取当前登录的邮箱账号。

js
console.log("当前账号:", mail.account());
// 输出: [email protected]

Mail.folderNames()

  • 返回 {Array<string>}

获取所有文件夹名称数组(用于 JS 遍历)。

js
var names = mail.folderNames();
for (var i = 0; i < names.length; i++) {
    console.log("📁", names[i]);
}

Mail.folder(name)

获取指定名称的文件夹对象。

js
var customFolder = mail.folder("已发送");
console.log("📁 已发送:", customFolder.size(), "封");

Mail.folders()

获取所有文件夹列表。

js
var allFolders = mail.folders();
console.log("📁 共", allFolders.size(), "个文件夹:");
for (var i = 0; i < allFolders.size(); i++) {
    var folder = allFolders.get(i);
    console.log("   " + (i + 1) + ".", folder.name(), ":", folder.size(), "封邮件");
}
// 过滤出有邮件的文件夹(非空)
var nonEmptyFolders = allFolders.filter(function(folder) {
    return folder.size() > 0;
});
console.log("📁 有邮件的文件夹(", nonEmptyFolders.size(), "个):");

Mail.inbox()

获取收件箱文件夹。

js
var inbox = mail.inbox();
console.log("📥 收件箱:", inbox.size(), "封邮件");
console.log("📥 未读:", inbox.unreadCount(), "封");

Mail.sent()

获取已发送文件夹。

js
var sent = mail.sent();
console.log("📤 已发送:", sent.size(), "封邮件");

Mail.drafts()

获取草稿箱文件夹。

js
var drafts = mail.drafts();
console.log("📝 草稿箱:", drafts.size(), "封邮件");

// 保存草稿
drafts.compose()
    .to("[email protected]")
    .subject("草稿邮件")
    .text("未完成的内容")
    .save();

Mail.deleted()

获取已删除文件夹。

js
var deleted = mail.deleted();
console.log("🗑️ 已删除:", deleted.size(), "封邮件");

Mail.junk()

获取垃圾邮件文件夹。

js
var junk = mail.junk();
console.log("🚫 垃圾邮件:", junk.size(), "封邮件");

Mail.createFolder(folderName)

  • folderName {string} 文件夹名称
  • 返回 {boolean} 是否创建成功

创建新文件夹。

js
var success = mail.createFolder("工作邮件");
console.log(success ? "✅ 创建成功" : "❌ 创建失败(可能已存在)");

Mail.folderExists(folderName)

  • folderName {string} 文件夹名称
  • 返回 {boolean} 是否存在

检查文件夹是否存在。

js
if (mail.folderExists("工作邮件")) {
    console.log("✅ 文件夹存在");
} else {
    console.log("❌ 文件夹不存在");
}

Mail.renameFolder(oldName, newName)

  • oldName {string} 旧文件夹名称
  • newName {string} 新文件夹名称
  • 返回 {boolean} 是否重命名成功

重命名文件夹。

js
var success = mail.renameFolder("工作邮件", "重要邮件");
console.log(success ? "✅ 重命名成功" : "❌ 重命名失败");

Mail.deleteFolder(folderName)

  • folderName {string} 文件夹名称
  • 返回 {boolean} 是否删除成功

删除文件夹。

js
var success = mail.deleteFolder("重要邮件");
console.log(success ? "✅ 删除成功" : "❌ 删除失败(可能不存在)");

Mail.compose()

创建新邮件构建器。

js
var builder = mail.compose();
builder.to("[email protected]")
       .subject("测试邮件")
       .text("Hello World!")
       .send();

Mail.reply(uid)

创建回复邮件构建器。底层会自动解析原邮件的 Reply-To 头(若无则用 From),作为默认收件人。

js
// 获取收件箱最新一封邮件
var inbox = mail.inbox();
var messages = inbox.load({
    limit: 1,
    loadBody: false
});

if (messages.size() > 0) {
    var msg = messages.get(0);
    console.log("📧 回复邮件:");
    console.log("   UID:", msg.uid());
    console.log("   主题:", msg.subject());
    console.log("   发件人:", msg.from().name());
    console.log("   时间:", new Date(msg.sentDate()).toLocaleString());


    // 回复这封邮件(文本 格式)
    // mail.reply(msg.uid())
    //     .text("收到,谢谢!")
    //     .send();

    // 回复这封邮件(HTML 格式)
    mail.reply(msg.uid())
        .html(
            '<div style="font-family: \'Microsoft YaHei\', Arial, sans-serif; padding: 20px; max-width: 600px;">' +
            '  <p style="font-size: 16px; color: #333; line-height: 1.8;">' +
            '    收到,谢谢!<br>' +
            '    祝工作顺利!' +
            '  </p>' +
            '  <br>' +
            '  <div style="color: #999; font-size: 12px; border-top: 1px solid #eee; padding-top: 10px;">' +
            '    — 此邮件由 Bot.js Pro 自动发送' +
            '  </div>' +
            '</div>'
        )
        .send();


    console.log("✅ 回复已发送");
} else {
    console.log("📭 收件箱为空");
}


mail.close();

Mail.forward(uid)

创建转发邮件构建器。底层会自动在邮件末尾引用原始邮件内容

js
// 获取收件箱最新一封邮件
var inbox = mail.inbox();
var messages = inbox.load({
    limit: 1,
    loadBody: true
});

if (messages.size() > 0) {
    var msg = messages.get(0);
    console.log("📧 转发邮件:");
    console.log("   UID:", msg.uid());
    console.log("   主题:", msg.subject());
    console.log("   发件人:", msg.from().name());
    console.log("   时间:", new Date(msg.sentDate()).toLocaleString());

    // 转发这封邮件指定联系人
    mail.forward(msg.uid())
        .to("[email protected]")
        .html("转发给您参考,请查收。")
        .send();

    console.log("✅ 转发已发送");
} else {
    console.log("📭 收件箱为空");
}

mail.close();

Mail.send(options)

  • options {Object} 邮件配置
    • from {string | Object} 发件人(可选,覆盖登录账号;仅发信模式下常用)
      • string 形式:"[email protected]"
      • Object 形式:
        • address {string} 发件人地址
        • name {string} 发件人显示名(可选)
    • headers {Object} 自定义邮件头(可选)。每个键值对等价于一次 MailBuilder.header(name, value) 调用,详见该章节(支持的头、多值、Message-ID 特殊处理、服务商支持度差异等)。
    • to {string | string[] | Array} 收件人地址
    • cc {string | string[] | Array} 抄送地址
    • bcc {string | string[] | Array} 密送地址
    • subject {string} 邮件主题
    • text {string} 纯文本内容
    • html {string} HTML 内容
    • attachments {string | string[] | Array} 附件路径
    • images {Object} 内嵌图片,键为 CID,值为图片路径
  • 异常 {MalformedURLException | MessagingException} 发送失败时抛出异常
  • ⚠️ 不抛异常 ≠ 对方已收到,详见 发送结果语义

发送邮件。

js
// 1. 基础发送
mail.send({
    to: "[email protected]",
    subject: "测试邮件",
    text: "这是一封测试邮件"
});

// 2. 多个收件人
mail.send({
    to: ["[email protected]", "[email protected]"],
    subject: "群发通知",
    text: "各位好!"
});

// 3. 带抄送
mail.send({
    to: "[email protected]",
    cc: "[email protected]",
    subject: "抄送通知",
    text: "请知悉。"
});

// 4. 带密送
mail.send({
    to: "[email protected]",
    bcc: ["[email protected]", "[email protected]"],
    subject: "密送通知",
    text: "密送收件人不会显示在邮件中。"
});

// 5. 同时带抄送和密送
mail.send({
    to: "[email protected]",
    cc: "[email protected]",
    bcc: "[email protected]",
    subject: "完整收件人",
    text: "各位好!"
});

// 6. HTML 内容(带样式)
mail.send({
    to: "[email protected]",
    subject: "HTML 邮件",
    html: '<div style="font-family: Arial, sans-serif; padding: 20px;">' +
          '  <h1 style="color: #333;">标题</h1>' +
          '  <p style="color: #666; font-size: 14px;">这是 HTML 内容</p>' +
          '</div>'
});

// 7. 带附件
mail.send({
    to: "[email protected]",
    subject: "带附件的邮件",
    text: "请查收附件",
    attachments: "/sdcard/document.pdf"
});

// 8. 多个附件
mail.send({
    to: "[email protected]",
    subject: "多个附件",
    text: "请查收",
    attachments: ["/sdcard/a.pdf", "/sdcard/b.png", "/sdcard/c.xlsx"]
});

// 9. 内嵌图片(指定宽高)
mail.send({
    to: "[email protected]",
    subject: "带图片的邮件",
    html: '<div style="font-family: Arial, sans-serif; padding: 20px;">' +
          '  <p>正文内容</p>' +
          '  <img src="cid:logo" style="width: 200px; height: auto; border: 1px solid #ddd; border-radius: 4px;">' +
          '  <p style="color: #999; font-size: 12px;">Logo 图片</p>' +
          '</div>',
    images: { logo: "/sdcard/logo.png" }
});

// 10. 多张内嵌图片(不同布局)
mail.send({
    to: "[email protected]",
    subject: "多图邮件",
    html: '<div style="font-family: Arial, sans-serif; padding: 20px;">' +
          '  <h2 style="color: #333;">产品展示</h2>' +
          '  <div style="display: flex; gap: 20px; flex-wrap: wrap;">' +
          '    <div style="text-align: center;">' +
          '      <img src="cid:image1" style="width: 150px; height: 150px; object-fit: cover; border-radius: 8px;">' +
          '      <p style="font-size: 12px; color: #666;">产品一</p>' +
          '    </div>' +
          '    <div style="text-align: center;">' +
          '      <img src="cid:image2" style="width: 150px; height: 150px; object-fit: cover; border-radius: 8px;">' +
          '      <p style="font-size: 12px; color: #666;">产品二</p>' +
          '    </div>' +
          '  </div>' +
          '</div>',
    images: {
        image1: "/sdcard/image1.png",
        image2: "/sdcard/image2.png"
    }
});

// 11. 内嵌图片 + 附件
mail.send({
    to: "[email protected]",
    subject: "图片+附件",
    html: '<div style="font-family: Arial, sans-serif; padding: 20px;">' +
          '  <p>请查看下图:</p>' +
          '  <img src="cid:chart" style="width: 100%; max-width: 600px; border: 1px solid #eee;">' +
          '  <p style="color: #999; font-size: 12px;">数据图表</p>' +
          '</div>',
    attachments: "/sdcard/report.pdf",
    images: { chart: "/sdcard/chart.png" }
});

// 12. 完整示例(带所有参数)
var uuid = java.util.UUID.randomUUID().toString();

mail.send({
    from: { address: "[email protected]", name: "服务通知" },   // 自定义发件人
    headers: {
        // ===== 标准头(几乎所有服务商都保留) =====
        "Message-ID": "<" + uuid + "@example.com>",                 // 邮件唯一标识
        "Reply-To": "[email protected]",                          // 回复地址(单值)

        // ===== 邮件列表类(普遍支持,但有的走控制台配置) =====
        "List-Unsubscribe": "<mailto:[email protected]>",           // 退订

        // ===== 会话关联类(部分服务商支持) =====
        "In-Reply-To": "<[email protected]>",             // 回复链
        "References": "<[email protected]> <[email protected]>",    // 会话链

        // ===== 优先级类(部分服务商支持) =====
        "X-Priority": "1",                                          // 1=最高
        "X-MSMail-Priority": "High",                                // Outlook 用
        "Importance": "High",                                       // RFC 2156

        // ===== 自定义追踪头(部分服务商支持) =====
        "X-Mailer": "Bot.js Pro Mail v1.0",                         // 客户端标识
        "X-Campaign-Id": "campaign-2026",                           // 营销活动 ID
        "X-Request-Id": "req-" + Date.now(),                        // 请求追踪
        "X-Tenant": "passport"                                      // 租户标识
    },
    to: "[email protected]",
    cc: "[email protected]",
    bcc: ["[email protected]", "[email protected]"],
    subject: "完整邮件示例",
    text: "这是纯文本内容(兼容纯文本客户端)",
    html: '<div style="font-family: "Microsoft YaHei", Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; background: #f9f9f9;">' +
          '  <div style="background: #fff; border-radius: 8px; padding: 30px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">' +
          '    <h1 style="color: #333; font-size: 22px; margin-top: 0;">📊 月度报告</h1>' +
          '    <p style="color: #555; font-size: 14px; line-height: 1.8;">' +
          '      您好,这是本月的数据报告,请查收附件。' +
          '    </p>' +
          '    <div style="text-align: center; margin: 20px 0;">' +
          '      <img src="cid:chart" style="width: 100%; max-width: 500px; border-radius: 4px;">' +
          '    </div>' +
          '    <p style="color: #666; font-size: 13px; line-height: 1.6;">' +
          '      <strong>主要数据:</strong><br>' +
          '      • 总用户:1,284 人<br>' +
          '      • 活跃用户:892 人<br>' +
          '      • 增长率:+12.5%' +
          '    </p>' +
          '    <hr style="border: none; border-top: 1px solid #eee; margin: 20px 0;">' +
          '    <p style="color: #999; font-size: 12px; margin-bottom: 0;">' +
          '      — 此邮件由 Bot.js Pro 自动发送' +
          '    </p>' +
          '  </div>' +
          '</div>',
    attachments: ["/sdcard/report.pdf", "/sdcard/data.xlsx"],
    images: { chart: "/sdcard/chart.png" }
});

Mail.reply(options)

  • options {Object} 邮件配置
    • uid {number} 要回复的邮件 UID。
    • markRead {boolean} 回复后是否将原邮件标记为已读,默认 false
    • from {string | Object} 发件人(可选,覆盖登录账号;仅发信模式下常用)
      • string 形式:"[email protected]"
      • Object 形式:
        • address {string} 发件人地址
        • name {string} 发件人显示名(可选)
    • headers {Object} 自定义邮件头(可选)。每个键值对等价于一次 MailBuilder.header(name, value) 调用,详见该章节(支持的头、多值、Message-ID 特殊处理、服务商支持度差异等)。
    • to {string | string[] | Array} 追加收件人地址。
      • 不传时,优先使用原邮件的 Reply-To,若无则回退到 From(原邮件发件人)。
      • 传了则追加到自动解析的地址之后。
    • cc {string | string[] | Array} 抄送地址。
    • bcc {string | string[] | Array} 密送地址。
    • subject {string} 邮件主题,默认在原主题前添加 回复:
    • text {string} 纯文本内容。发送时会自动在邮件末尾引用原邮件内容。
    • html {string} HTML 内容。发送时会自动在邮件末尾引用原邮件内容。
    • attachments {string | string[] | Array} 附件文件路径。
    • images {Object} 内嵌图片,键为 CID,值为图片文件路径。
  • 异常 {MalformedURLException | MessagingException} 发送失败时抛出异常
  • ⚠️ 不抛异常 ≠ 对方已收到,详见 发送结果语义

回复指定邮件。

js

// 获取收件箱最新一封邮件
var inbox = mail.inbox();
var messages = inbox.load({
    limit: 1,
    loadBody: true
});

if (messages.size() > 0) {
    var msg = messages.get(0);
    console.log("📧 回复邮件:");
    console.log("   UID:", msg.uid());
    console.log("   主题:", msg.subject());
    console.log("   发件人:", msg.from().name());
    console.log("   时间:", new Date(msg.sentDate()).toLocaleString());

    mail.reply({
        uid: msg.uid(),
        markRead: true,
        subject: "回复: " + msg.subject(),
        text: "收到,谢谢!\n\n祝工作顺利!",
        headers: {
            "Message-ID": "<reply-" + Date.now() + "@example.com>"
        }
    });

    console.log("✅ 回复已发送");
} else {
    console.log("📭 收件箱为空");
}

mail.close();
js

// 收件人合并为抄送,将原始邮件的所有收件人(除了自己)和抄送人合并为新的抄送人,自己作为唯一的收件人,比如163邮箱。

// 获取收件箱最新一封邮件
var inbox = mail.inbox();
var messages = inbox.load({
    limit: 1,
    loadBody: true
});

if (messages.size() > 0) {
    var msg = messages.get(0);
    console.log("📧 回复全部(收件人→抄送):");
    console.log("   UID:", msg.uid());
    console.log("   主题:", msg.subject());
    console.log("   发件人:", msg.from().name());

    // 获取所有收件人(to + cc)
    var allRecipients = [];
    
    // 收集 to 中的地址(排除自己)
    var toList = msg.to();
    for (var i = 0; i < toList.size(); i++) {
        var addr = toList.get(i);
        if (addr.address !== mail.account()) {
            allRecipients.push(addr.address);
        }
    }
    
    // 收集 cc 中的地址(排除自己)
    var ccList = msg.cc();
    for (var i = 0; i < ccList.size(); i++) {
        var addr = ccList.get(i);
        if (addr.address !== mail.account()) {
            allRecipients.push(addr.address);
        }
    }

    // 回复全部:自己为收件人,其他人为抄送
    mail.reply({
        uid: msg.uid(),
        markRead: true,
        subject: "回复全部: " + msg.subject(),
        to: msg.from().address,  // 发件人作为收件人
        cc: allRecipients,       // 其他所有人作为抄送
        text: "收到,谢谢!\n\n祝工作顺利!"
    });

    console.log("✅ 回复全部已发送");
    console.log("   收件人:", msg.from().address);
    console.log("   抄送:", allRecipients.join(", "));
}
mail.close();
js

// 保持原收件人结构,原始邮件的 to 保持为 to,cc 保持为 cc,但排除自己,比如qq邮箱。

var inbox = mail.inbox();
var messages = inbox.load({
    limit: 1,
    loadBody: true
});

if (messages.size() > 0) {
    var msg = messages.get(0);
    console.log("📧 回复全部(保持原结构):");
    console.log("   UID:", msg.uid());
    console.log("   主题:", msg.subject());
    console.log("   发件人:", msg.from().name());

    // 收集 to(排除自己)
    var newTo = [];
    var toList = msg.to();
    for (var i = 0; i < toList.size(); i++) {
        var addr = toList.get(i);
        if (addr.address !== mail.account()) {
            newTo.push(addr.address);
        }
    }

    // 收集 cc(排除自己)
    var newCc = [];
    var ccList = msg.cc();
    for (var i = 0; i < ccList.size(); i++) {
        var addr = ccList.get(i);
        if (addr.address !== mail.account()) {
            newCc.push(addr.address);
        }
    }

    // 如果发件人不在 to 中,添加到 to,正常来说不需要此步骤,因为内部底层会自动将发件人添加到 to 中
    var fromAddr = msg.from().address;
    if (newTo.indexOf(fromAddr) === -1) {
        newTo.push(fromAddr);
    }

    // 回复全部:保持原 to/cc 结构
    mail.reply({
        uid: msg.uid(),
        markRead: true,
        subject: "回复全部: " + msg.subject(),
        to: newTo,      // 原收件人(排除自己 + 发件人)
        cc: newCc,      // 原抄送(排除自己)
        text: "收到,谢谢!\n\n祝工作顺利!"
    });

    console.log("✅ 回复全部已发送");
    console.log("   收件人:", newTo.join(", "));
    console.log("   抄送:", newCc.join(", "));
}

mail.close();

Mail.forward(options)

  • options {Object} 邮件配置
    • uid {number} 要转发的邮件 UID
    • markRead {boolean} 是否标记为已读,默认 false
    • from {string | Object} 发件人(可选,覆盖登录账号;仅发信模式下常用)
      • string 形式:"[email protected]"
      • Object 形式:
        • address {string} 发件人地址
        • name {string} 发件人显示名(可选)
    • headers {Object} 自定义邮件头(可选)。每个键值对等价于一次 MailBuilder.header(name, value) 调用,详见该章节(支持的头、多值、Message-ID 特殊处理、服务商支持度差异等)。
    • to {string | string[] | Array} 收件人地址。
    • cc {string | string[] | Array} 抄送地址。
    • bcc {string | string[] | Array} 密送地址。
    • subject {string} 邮件主题,默认在原主题前添加 转发:
    • text {string} 纯文本内容。发送时会自动在邮件末尾引用原邮件内容。
    • html {string} HTML 内容。发送时会自动在邮件末尾引用原邮件内容。
    • attachments {string | string[] | Array} 附件文件路径。
    • images {Object} 内嵌图片,键为 CID,值为图片文件路径。
  • 异常 {MalformedURLException | MessagingException} 发送失败时抛出异常
  • ⚠️ 不抛异常 ≠ 对方已收到,详见 发送结果语义

转发指定邮件。

js
// 获取收件箱最新一封邮件
var inbox = mail.inbox();
var messages = inbox.load({
    limit: 1,
    loadBody: true
});

if (messages.size() > 0) {
    var msg = messages.get(0);

    console.log("📧 转发邮件:");
    console.log("   UID:", msg.uid());
    console.log("   主题:", msg.subject());
    console.log("   发件人:", msg.from().name());
    console.log("   时间:", new Date(msg.sentDate()).toLocaleString());

    mail.forward({
        uid: msg.uid(),
        markRead: true,
        to: "[email protected]",
        subject: "转发:" + msg.subject(),
        text: "您好!\n\n转发一封邮件给您,请查收。\n\n—— Bot.js Pro",
        // html: "<h2>您好!</h2><p>转发一封邮件给您,请查收。</p>",
        // 测试新增附件
        attachments: [
            "/sdcard/results.html",
            "/sdcard/imgDraw.png"
        ],
        headers: {
            "Message-ID": "<forward-" + Date.now() + "@example.com>"
        }

    });

    console.log("✅ 转发已发送");
} else {
    console.log("📭 收件箱为空");
}

mail.close();

Mail.close()

断开与邮件服务器的连接。

js
// 使用完毕后断开连接
mail.close();

发送结果语义

"发送成功" ≠ "对方收到"

send() / reply() / forward() 不抛异常,只表示邮件服务商已接收邮件不代表对方邮箱已收到

为什么会有这个差异:

SMTP 协议允许两种投递行为,不同服务商策略不同

行为校验时机无效收件人典型服务商
同步校验SMTP 发送阶段实时验证当场抛异常(如 559 Invalid rcptto阿里云邮件推送
异步投递先接收,后台投递SMTP 层不抛异常,通过退信通知腾讯云邮件推送

同一个不存在的收件人,两家表现:

js
// 阿里云邮件推送 → 抛异常
失败: SMTPSendFailedException: 559 Invalid rcptto ... invaddr reject

// 腾讯云邮件推送 → "成功"
✓ 发送成功   // 但实际未投递,稍后会收到退信

所以:

  • 抛异常 → 说明发送阶段就被拒了(收件人无效、被反垃圾拦截、发件人未验证等)
  • 不抛异常 → 只说明服务商已接收,最终投递结果需要看退信 / 控制台发送记录 / 投递回调

如何确认"对方是否真的收到":

  • 查看服务商控制台的"发送记录"(腾讯云邮件推送、阿里云邮件推送都提供)
  • 检查发件人邮箱的退信(投递失败会退回到 From 地址)
  • 配置服务商的"投递结果回调"(腾讯云邮件推送支持事件回调,阿里云邮件推送支持投递通知)

MailBuilder

Mail.compose()Mail.reply(uid)Mail.forward(uid)MailFolder.compose() 创建,用于构建邮件。

js
var builder = mail.compose();

MailBuilder.from(address[, name])

  • address {string} 发件人地址(可选,覆盖登录账号)
  • name {string} 发件人显示名(可选)
  • 返回 MailBuilder

设置本次邮件的发件人(覆盖登录账号)。

注意事项

  • 普通邮箱(QQ / 163 / Gmail 等)from 通常需要与 SMTP 登录账号一致,不能随意填写其他发件地址。
  • 邮件推送服务 — 域名级验证(如腾讯云邮件推送):只要发信域名验证通过,from 的后缀域名属于已验证域名即可,@ 前面的前缀可以随意填写,无需在控制台逐个创建发信地址。
  • 邮件推送服务 — 地址级验证(如阿里云邮件推送):from 必须使用控制台中已创建并验证的发信地址,不能随意修改 @ 前面的地址部分。阿里云同时还要求对应的发信域名完成验证。
js
// 只设地址
builder.from("[email protected]");

// 地址 + 显示名
builder.from("[email protected]", "发件人显示名");

MailBuilder.header(name, value)

  • name {string} 头名(如 "Message-ID""Reply-To""X-Mailer"
  • value {string | string[] | Array} 头值,支持单值或多值
  • 返回 MailBuilder

设置自定义邮件头。除 From / To / Cc / Bcc / Subject / Date 由框架管理外,其他任意头都能设置(包括 Message-IDReply-ToX-* 等)。

js
// 单值
builder.header("X-Mailer", "Bot.js Pro Mail v1.0");

// 多值
builder.header("Reply-To", ["[email protected]", "[email protected]"]);

// 自定义 Message-ID
var uuid = java.util.UUID.randomUUID().toString();
builder.header("Message-ID", "<" + uuid + "@example.com>");

Message-ID 特殊说明

Message-ID 由框架特殊处理:

  • 用户设了 → 保留用户值(格式必须为 <xxx@yyy>
  • 用户没设 → 自动生成

自定义头支持度取决于邮件服务商

MailBuilder.header(name, value)开放接口,任何合法的邮件头都能设置。但邮件服务商在转发时可能剥离或改写部分头

支持度分三档:

  • 保留:原样传递
  • ⚠️ 改写:值被改成服务商指定的内容(如登录账号)
  • 剥离:直接丢弃

常见服务商对比:

腾讯云邮件推送阿里云邮件推送
Message-ID✅ 保留用户值✅ 保留用户值
Reply-To(单值)
Reply-To(多值)❌ 合并为一个✅ 保留多值
In-Reply-To❌ 剥离✅ 保留
References(多值)❌ 剥离✅ 保留
Sender❌ 剥离⚠️ 改写成登录账号
X-Priority❌ 剥离✅ 保留
X-MSMail-Priority❌ 剥离✅ 保留
Importance❌ 剥离✅ 保留
Disposition-Notification-To❌ 剥离⚠️ 改写成登录账号
List-Unsubscribe✅(由控制台控制)✅ 可手动设
List-Id❌ 剥离✅ 保留
List-Help❌ 剥离✅ 保留
Auto-Submitted❌ 剥离✅ 保留
Precedence❌ 剥离✅ 保留
X-Mailer❌ 剥离✅ 保留
X-* 自定义头(任意)❌ 剥离✅ 保留
X-Tag(多值)❌ 剥离✅ 保留多值
空值头(""❌ 剥离✅ 保留
X-AliDM-Settings✅ 官方专用配置头

结论:

  • 只发标准头From / To / Subject / Message-ID / 单值 Reply-To / List-Unsubscribe)→ 两家都行
  • 需要自定义头X-* / In-Reply-To / 多值 Reply-To / 优先级 / 回执请求)→ 必须用阿里云邮件推送
  • 需要官方退订配置阿里云邮件推送X-AliDM-Settings 头;腾讯云邮件推送 只能通过控制台配置
阿里云邮件推送 可设置的自定义头(示例)
js
mail.compose()
    .from("[email protected]", "服务通知")

    // ---- 标准头 ----
    .header("Message-ID", "<[email protected]>")
    .header("Reply-To", ["[email protected]", "[email protected]"])           // 多值 OK
    .header("In-Reply-To", "<[email protected]>")
    .header("References", ["<[email protected]>", "<[email protected]>"])

    // ---- 优先级 ----
    .header("X-Priority", "1")
    .header("X-MSMail-Priority", "High")
    .header("Importance", "High")

    // ---- 邮件列表 ----
    .header("List-Unsubscribe", "<mailto:[email protected]>")
    .header("List-Id", "Bot.js Test <test.example.com>")
    .header("List-Help", "<mailto:[email protected]>")

    // ---- 自动回复 / 批量 ----
    .header("Auto-Submitted", "auto-generated")
    .header("Precedence", "bulk")

    // ---- 自定义追踪头 ----
    .header("X-Mailer", "Bot.js Pro Mail v1.0")
    .header("X-Campaign-Id", "campaign-2026")
    .header("X-Request-Id", "req-" + Date.now())
    .header("X-Tenant", "passport")
    .header("X-Tag", ["test", "batch", "notice"])                     // 多值 OK

    .to("[email protected]")
    .subject("测试自定义头")
    .text("这封邮件带了自定义头,收件方可在【查看邮件原文】里核对。")
    .send();

阿里云的官方退订配置头(Base64 编码的 JSON):

js
.header("X-AliDM-Settings",
    "eyJWZXJzaW9uIjoiMS4wIiwiVW5zdWJzY3JpYmUiOnsiRmlsdGVyTGV2ZWwiOiJtYWlsZnJvbV9kb21haW4iLCJMaW5rVHlwZSI6InpoLWNuIn19")

原始 JSON 是 {"Version":"1.0","Unsubscribe":{"FilterLevel":"mailfrom_domain","LinkType":"zh-cn"}}

腾讯云邮件推送 只支持标准头(示例)
js
mail.compose()
    .from("[email protected]", "服务通知")

    // ---- 标准头(保留) ----
    .header("Message-ID", "<[email protected]>")
    .header("Reply-To", "[email protected]")                              // 只保留第一个
    // .header("List-Unsubscribe", "...")                             // 由控制台控制

    // ---- 下面这些会被剥离,设了也没用 ----
    // .header("X-Priority", "1")
    // .header("X-Mailer", "Bot.js Pro")
    // .header("X-Campaign-Id", "...")
    // .header("In-Reply-To", "...")
    // .header("References", "...")

    .to("[email protected]")
    .subject("测试标准头")
    .text("这封邮件只带标准头,自定义头会被腾讯云邮件推送剥离。")
    .send();

腾讯云邮件推送 的现实:

  • 只保留 From / To / Subject / Date / Message-ID / Content-Type / MIME-Version / 单值 Reply-To
  • 所有 X-*In-Reply-ToReferences、优先级、回执请求全部剥离
  • List-Unsubscribe 通过控制台配置,不是走 header()

如果你需要 X-* 追踪头、多值 Reply-ToIn-Reply-To,腾讯云邮件推送 不适合,建议换阿里云邮件推送。

MailBuilder.headers(headers)

  • headers {Object} 头对象,键为头名,值为头值(stringArray
  • 返回 MailBuilder

批量设置邮件头。每个键值对等价于一次 header(name, value) 调用。

js
builder.headers({
    "X-Mailer": "Bot.js Pro Mail v1.0",
    "X-Campaign-Id": "campaign-2026",
    "Reply-To": ["[email protected]", "[email protected]"]
});

// 等价于:
builder
    .header("X-Mailer", "Bot.js Pro Mail v1.0")
    .header("X-Campaign-Id", "campaign-2026")
    .header("Reply-To", ["[email protected]", "[email protected]"]);

用法场景

mail.send({ headers: {...} })mail.compose().headers({...}) 效果一致——前者是"一次性传对象",后者是"链式批量设置"。

MailBuilder.to(addresses)

  • addresses {string | string[] | Array} 收件人
  • 返回 MailBuilder

设置收件人。

js
// 单个收件人
builder.to("[email protected]");

// 多个收件人
builder.to(["[email protected]", "[email protected]"]);

builder.to("[email protected]").to("[email protected]");

MailBuilder.cc(addresses)

  • addresses {string | string[] | Array} 抄送
  • 返回 MailBuilder

设置抄送。

js
builder.cc("[email protected]");

MailBuilder.bcc(addresses)

  • addresses {string | string[] | Array} 密送
  • 返回 MailBuilder

设置密送。

js
builder.bcc("[email protected]");

MailBuilder.subject(subject)

设置邮件主题。

js
builder.subject("重要通知");

MailBuilder.text(text)

设置邮件纯文本内容。

js
builder.text("这是邮件的纯文本内容");

MailBuilder.html(html)

设置邮件 HTML 内容。

js
builder.html("<h1>标题</h1><p>这是HTML内容</p>");

MailBuilder.attach(path)

  • path {string} 文件路径,文件不存在或没有文件读取权限时抛出异常。
  • 返回 MailBuilder

添加附件。

js
builder.attach("/sdcard/document.pdf");

MailBuilder.image(cid, path)

  • cid {string} 图片 Content-ID(用于 HTML 中引用)
  • path {string} 图片文件路径,文件不存在或没有文件读取权限时抛出异常。
  • 返回 MailBuilder

添加内嵌图片。

js
// HTML 中引用 <img src="cid:logo">
builder.html('<img src="cid:logo" width="200" height="100" style="width:200px;height:100px;">')

builder.image("logo", "/sdcard/logo.png");

MailBuilder.send()

  • 异常 {MalformedURLException | MessagingException} 发送失败时抛出异常
  • ⚠️ 不抛异常 ≠ 对方已收到,详见 发送结果语义

发送邮件。

js
mail.compose()
    .to("[email protected]")
    .subject("测试邮件")
    .text("Hello World!")
    .send();

MailBuilder.save([folder])

  • folder {MailFolder} 目标文件夹,默认草稿箱
  • 返回

保存为草稿。

js

mail.compose()
    .to("[email protected]")
    .subject("草稿邮件")
    .text("未完成的内容")
    .save();
js
// 保存到草稿箱
var drafts = mail.drafts();
mail.compose()
    .to("[email protected]")
    .subject("草稿邮件")
    .text("未完成的内容")
    .save(drafts);

// 保存到收件箱
var inbox = mail.inbox();
mail.compose()
    .to("[email protected]")
    .subject("草稿邮件")
    .text("未完成的内容")
    .save(inbox);
js

var drafts = mail.drafts();
drafts.compose()
    .to("[email protected]")
    .subject("草稿邮件")
    .text("未完成的内容")
    .save();

MailBuilder.clear()

清空所有已设置的内容(复用构建器)。

js
// 清空后发送新邮件
builder.clear()
       .to("[email protected]")
       .subject("新邮件")
       .send();

MailFolder

代表一个邮件文件夹。 Mail.folder(name)Mail.inbox()Mail.sent()Mail.drafts()Mail.deleted()Mail.junk() 创建,用于邮件文件夹操作。

js
var inbox = mail.inbox();

MailFolder.name()

  • 返回 {string}

获取文件夹名称。

js
console.log("当前文件夹:", inbox.name());

MailFolder.size()

  • 返回 {number}

获取文件夹中的邮件总数。

js
console.log("收件箱共有", inbox.size(), "封邮件");

MailFolder.unreadCount()

  • 返回 {number}

获取文件夹中的未读邮件数。

js
console.log("收件箱有", inbox.unreadCount(), "封未读邮件");

MailFolder.load(options)

  • options {Object} 加载选项
    • beforeUid {number} 截止 UID,-1 表示不限制(从最新开始)
    • limit {number} 最多加载数量,默认 20
    • loadBody {boolean} 是否加载正文,默认 false
    • markRead {boolean} 是否标记为已读,默认 false
  • 返回 MailMessageCollection

加载邮件列表(按 UID 倒序)。

js
// 加载收件箱中最新 10 封邮件(含正文,不标记已读)
var messages = inbox.load({
    beforeUid: -1,
    limit: 10,
    loadBody: true,
    markRead: false
});

console.log("共加载 " + messages.size() + " 封邮件");

for (var i = 0; i < messages.size(); i++) {
    var msg = messages.get(i);
    var sentDate = new Date(msg.sentDate()); // 转为 Date 对象

    console.log("--- 邮件 #" + (i+1) + " ---");
    console.log("uid: ", msg.uid());
    console.log("主题: " + msg.subject());
    console.log("发件人: " + msg.from());
    console.log("日期: " + sentDate.toLocaleString('zh-CN')); // 格式化为中文日期时间
    console.log("是否已读: " + msg.seen());
    console.log("正文预览: " + msg.plainBody().substring(0, 100) + "...");
}

MailFolder.getMessage(uid[, markRead])

  • uid {number} 邮件 UID
  • markRead {boolean} 是否标记为已读,默认 false
  • 返回 MailMessage

获取单封邮件。

js
var uid = 12345
var msg = inbox.getMessage(uid, true);  // 获取并标记已读
console.log("主题:", msg.subject());
console.log("内容:", msg.body());

MailFolder.setSeen(uids, value)

  • uids {number[] | Array} 邮件 UID 数组,当包含不存在的 UID 时抛出异常。
  • value {boolean} 是否标记为已读,true表示标记为已读,false表示标记为未读,
  • 返回 {boolean}

批量设置已读状态。

js
var uids = [12345, 12346, 12347];
var success = inbox.setSeen(uids, true);
console.log(success ? "标记成功" : "标记失败");

MailFolder.setFlagged(uids, value)

  • uids {number[] | Array} 邮件 UID 数组,当包含不存在的 UID 时抛出异常。
  • value {boolean} 是否加星标,true表示标记为已读,false表示标记为未读,
  • 返回 {boolean}

批量设置星标状态。

js
var success = inbox.setFlagged([12345, 12346], true);
console.log(success ? "标记成功" : "标记失败");

MailFolder.setAnswered(uids, value)

  • uids {number[] | Array} 邮件 UID 数组,当包含不存在的 UID 时抛出异常。
  • value {boolean} 是否标记为已回复,true表示标记为已读,false表示标记为未读(部分邮箱服务商可能不支持取消已回复标记,因此可能无效)
  • 返回 {boolean}

批量设置已回复标记。部分邮箱无此功能所以无效。

js
var success = inbox.setAnswered([12345], true);
console.log(success ? "标记成功" : "标记失败");

MailFolder.setDeleted(uids, value)

  • uids {number[] | Array} 邮件 UID 数组,当包含不存在的 UID 时抛出异常。
  • value {boolean} 是否标记为已删除,true表示标记为已读,false表示标记为未读
  • 返回 {boolean}

批量设置删除标记。有的邮箱会直接删除,有的会移动到已删除文件夹

js
var success = inbox.setDeleted([12345], true);
console.log(success ? "标记成功" : "标记失败");

MailFolder.setDraft(uids, value)

  • uids {number[] | Array} 邮件 UID 数组,当包含不存在的 UID 时抛出异常。
  • value {boolean} 是否标记为草稿
  • 返回 {boolean}

批量设置草稿标记。

注意事项

此方法仅设置邮件的草稿(Draft)标记,不会将邮件移动到草稿箱(Drafts)文件夹。

js
var success = inbox.setDraft([12345], true);
console.log(success ? "标记成功" : "标记失败");

MailFolder.setRecent(uids, value)

  • uids {number[] | Array} 邮件 UID 数组,当包含不存在的 UID 时抛出异常。
  • value {boolean} 是否标记为新邮件
  • 返回 {boolean}

批量设置新邮件标记。

注意事项

Recent 标记通常由 IMAP 服务器自动维护,用于表示邮件是否为当前会话中新到达的邮件。绝大多数 IMAP 服务器不允许客户端修改该标记,因此此方法可能无效。

js
inbox.setRecent([12345], true);

MailFolder.setUserFlag(uids, flag, value)

  • uids {number[] | Array} 邮件 UID 数组,当包含不存在的 UID 时抛出异常。
  • flag {string} 自定义标记名称
  • value {boolean} 是否添加标记
  • 返回 {boolean}

批量设置自定义标记。

注意事项

是否支持自定义标记取决于 IMAP 服务器。多数邮箱服务商不支持或会忽略客户端设置的自定义标记,因此此方法可能无效。

js
inbox.setUserFlag([12345], "重要", true);

MailFolder.delete(uids)

  • uids {number[] | Array} 邮件 UID 数组,当包含不存在的 UID 时抛出异常。
  • 返回 {boolean}

永久删除邮件。

js
var uid = 123456
var success = inbox.delete([uid]);
console.log(success ? "✅ 删除成功" : "❌ 删除失败");

MailFolder.move(uids, target)

  • uids {number[] | Array} 邮件 UID 数组,当包含不存在的 UID 时抛出异常。
  • target {string} 目标文件夹名称,不存在时抛出异常。
  • 返回 {boolean}

移动邮件到目标文件夹。

js
var success = inbox.move([12345], "工作邮件");
console.log(success ? "✅ 移动成功" : "❌ 移动失败");

MailFolder.copy(uids, target)

  • uids {number[] | Array} 邮件 UID 数组,当包含不存在的 UID 时抛出异常。
  • target {string} 目标文件夹名称,不存在时抛出异常。
  • 返回 {boolean}

复制邮件到目标文件夹。

js
var success = inbox.copy([12345], "存档");
console.log(success ? "✅ 复制成功" : "❌ 复制失败");

MailFolder.search(options)

  • options {Object} 搜索条件
    • subject {string} 主题关键词
    • from {string} 发件人关键词
    • to {string} 收件人关键词
    • cc {string} 抄送关键词
    • bcc {string} 密送关键词
    • body {string} 正文关键词
    • loadBody {boolean} 是否加载正文,默认 false
    • markRead {boolean} 是否标记为已读,默认 false
  • 返回 MailMessageCollection

搜索邮件。

注意事项

搜索功能依赖 IMAP 服务器实现,不同邮箱服务商支持的搜索条件可能不同。部分邮箱可能不支持正文搜索或某些字段搜索,因此搜索结果可能为空或与预期不一致。

js
var results = inbox.search({
    subject: "报告",
    from: "[email protected]",
    body: "季度",
    loadBody: true
});

console.log("找到", results.size(), "封邮件");

MailFolder.compose()

创建邮件构建器(自动关联当前文件夹,用于保存草稿)。

js
var drafts = mail.drafts();
drafts.compose()
    .to("[email protected]")
    .subject("草稿")
    .text("内容")
    .save();  // 自动保存到草稿箱

MailFolder.save(options)

  • options {Object} 邮件配置

保存邮件到当前文件夹(通常用于保存草稿)。

js
var drafts = mail.drafts();
// 使用 Object
drafts.save({
    to: "[email protected]",
    subject: "草稿邮件",
    text: "这是草稿内容"
});

// 使用 MailBuilder
drafts.compose()
    .to("[email protected]")
    .subject("草稿邮件")
    .text("这是草稿内容")
    .save();

MailFolder.toString()

  • 返回 {string}

获取文件夹的字符串表示。

js
console.log(inbox.toString());
// 输出: MailFolder{name="INBOX", account="[email protected]"}

MailFolderCollection

文件夹集合,支持数组风格操作。

MailFolderCollection.size()

  • 返回 {number}

获取文件夹数量。

js
var folders = mail.folders();
console.log("总文件夹数:", folders.size());

MailFolderCollection.get(index)

获取指定索引的文件夹。

js
var firstFolder = folders.get(0);
console.log("第一个文件夹:", firstFolder.name());

MailFolderCollection.forEach(callback)

  • callback {Function} 回调函数 (folder, index) => void
    • folder {MailFolder} 当前文件夹对象
    • index {number} 当前文件夹索引
  • 返回 {MailFolderCollection}

遍历所有文件夹。

js
folders.forEach(function(folder) {
    console.log("📁", folder.name(), ":", folder.size(), "封邮件");
});

MailFolderCollection.filter(filter)

过滤文件夹。

js
var largeFolders = folders.filter(function(folder) {
    return folder.size() > 100;
});
console.log("大文件夹:", largeFolders.size(), "个");

MailFolderCollection.find(filter)

  • filter {Function} 过滤函数 (folder) => boolean
  • 返回 MailFolder

查找第一个匹配的文件夹。

js
var inbox = folders.find(function(folder) {
    return folder.name() === "INBOX";
});

MailFolderCollection.names()

  • 返回 {Array<string>}

获取所有文件夹名称数组。

js
var names = folders.names();
for (var i = 0; i < names.length; i++) {
    console.log(names[i]);
}

MailFolderCollection.sizes()

  • 返回 {Array<number>}

获取所有文件夹的邮件数量数组。

js
var sizes = folders.sizes();
console.log("各文件夹邮件数:", sizes);

MailFolderCollection.unreadCounts()

  • 返回 {Array<number>}

获取所有文件夹的未读邮件数量数组。

js
var unreads = folders.unreadCounts();
console.log("各文件夹未读数:", unreads);

MailMessage

代表一封邮件。

MailMessage.uid()

  • 返回 {number}

获取邮件 UID。

js
console.log("UID:", msg.uid());

MailMessage.subject()

  • 返回 {string}

获取邮件主题。

js
console.log("主题:", msg.subject());

MailMessage.from()

获取发件人。

js
var from = msg.from();
console.log("发件人:", from.name(), "<" + from.address + ">");

MailMessage.to()

获取收件人列表。

js
var toList = msg.to();

toList.forEach(function(address) {
    console.log("收件人:", address.name(), "<" + address.address() + ">");
});

MailMessage.cc()

获取抄送列表。

js
var ccList = msg.cc();
console.log("抄送:", ccList.size(), "人");

MailMessage.bcc()

获取密送列表。

js
var bccList = msg.bcc();
console.log("密送:", bccList.size(), "人");

MailMessage.sentDate()

  • 返回 {number}

获取发送时间戳(毫秒)。

js
var date = new Date(msg.sentDate());
console.log("发送时间:", date.toLocaleString());

MailMessage.receivedDate()

  • 返回 {number}

获取接收时间戳(毫秒)。

js
var date = new Date(msg.receivedDate());
console.log("接收时间:", date.toLocaleString());

MailMessage.body()

  • 返回 {string}

获取邮件正文(优先返回 HTML,若无则返回纯文本)。

js
console.log("正文:", msg.body());

MailMessage.textBody()

  • 返回 {string}

获取纯文本正文。

js
console.log("纯文本:", msg.textBody());

MailMessage.htmlBody()

  • 返回 {string}

获取 HTML 正文。

js
console.log("HTML:", msg.htmlBody());

MailMessage.plainBody()

  • 返回 {string}

获取纯文本正文(HTML 会自动去除标签)。

js
console.log("纯文本(去除HTML标签):", msg.plainBody());

MailMessage.size()

  • 返回 {number}

获取邮件大小(字节)。

js
console.log("邮件大小:", msg.size(), "bytes");

MailMessage.seen()

  • 返回 {boolean}

是否已读。

js
console.log("已读:", msg.seen() ? "✅" : "❌");

MailMessage.flagged()

  • 返回 {boolean}

是否已加星标。

js
console.log("星标:", msg.flagged() ? "⭐" : "☆");

MailMessage.answered()

  • 返回 {boolean}

是否已回复。

js
console.log("已回复:", msg.answered() ? "✅" : "❌");

MailMessage.deleted()

  • 返回 {boolean}

是否已标记删除。

js
console.log("已删除:", msg.deleted() ? "🗑️" : "✅");

MailMessage.draft()

  • 返回 {boolean}

是否为草稿。

js
console.log("草稿:", msg.draft() ? "📝" : "❌");

MailMessage.recent()

  • 返回 {boolean}

是否为新邮件。

js
console.log("新邮件:", msg.recent() ? "🆕" : "❌");

MailMessage.userFlags()

  • 返回 {Array<string>}

获取自定义标记列表。

js
var flags = msg.userFlags();
for (var i = 0; i < flags.length; i++) {
    console.log("标记:", flags[i]);
}

MailMessage.attachments()

获取附件列表。

js
var attachments = msg.attachments();
console.log("附件数:", attachments.size());

MailMessage.header(name)

  • name {string} 头名(大小写不敏感,如 "Reply-To""Message-ID""X-Mailer"
  • 返回 {Array<string>} 该头的所有值;不存在时返回空数组

获取指定邮件头的所有值。用于读取原始邮件头,不区分大小写。

  • 单值头 → 返回长度 1 的数组
  • 多值头 → 返回完整数组(如多个 Reply-To、多个 Received
  • 不存在 → 返回空数组
js
var inbox = mail.inbox();
var messages = inbox.load({ limit: 1, loadBody: false });

if (messages.size() > 0) {
    var msg = messages.get(0);

    // 读 Reply-To(可能有多个值)
    var replyTos = msg.header("Reply-To");
    console.log("Reply-To 共", replyTos.length, "个:");
    for (var i = 0; i < replyTos.length; i++) {
        console.log("  [" + i + "]", replyTos[i]);
    }

    // 读 Message-ID(单值)
    var msgIds = msg.header("Message-ID");
    if (msgIds.length > 0) {
        console.log("Message-ID:", msgIds[0]);
    }

    // 读任意自定义头
    var mailer = msg.header("X-Mailer");
    console.log("X-Mailer:", mailer.length > 0 ? mailer[0] : "(无)");

    // 大小写不敏感
    console.log(msg.header("message-id"));  // 和 "Message-ID" 等价
}

MailMessage.headers()

  • 返回 {Object} 所有邮件头(JS 对象)

获取邮件的所有头。返回值是普通 JS 对象,可以直接 for in 遍历。

  • 每个头的值都是数组Array<string>),即使只有一个值也是数组,方便统一处理
  • 头不存在时 → 对象里没有该 key,访问得到 undefined
js
var headerObj = msg.headers();

// 读单值头(判长度 > 0,再取第 0 个)
if (headerObj["Message-ID"] && headerObj["Message-ID"].length > 0) {
    console.log("Message-ID:", headerObj["Message-ID"][0]);
}
if (headerObj["Subject"] && headerObj["Subject"].length > 0) {
    console.log("Subject:", headerObj["Subject"][0]);
}
// 读多值头
var replyTos = headerObj["Reply-To"] || [];
for (var i = 0; i < replyTos.length; i++) {
    console.log("Reply-To [" + i + "]:", replyTos[i]);
}

// 遍历所有头(统一处理)
for (var name in headerObj) {
    var values = headerObj[name];
    for (var i = 0; i < values.length; i++) {
        console.log(name + ": " + values[i]);
    }
}

// 头不存在或数组为空时,都不取值
var mailer = headerObj["X-Mailer"];
if (mailer && mailer.length > 0) {
    console.log("X-Mailer:", mailer[0]);
} else {
    console.log("没有 X-Mailer 头");
}

为什么所有值都是数组

因为同一个头名可以有多个值(如多个 Reply-To、多个 Received),为了统一处理,所有头的值都返回数组

  • 单值头:长度 1 的数组 → headerObj["Message-ID"][0]
  • 多值头:长度 N 的数组 → 遍历
  • 头不存在headerObj["X-NotExist"]undefined

MailMessage.headerValue(name)

  • name {string} 头名(大小写不敏感)
  • 返回 {string} 该头的第一个值;头不存在时返回 null

获取指定邮件头的第一个值。适合确定是单值的头(如 Message-IDSubject)。

js
var msgId = msg.headerValue("Message-ID");
if (msgId !== null) {
    console.log("Message-ID:", msgId);
} else {
    console.log("没有 Message-ID");
}

var subject = msg.headerValue("Subject");
console.log("Subject:", subject);

和 MailMessage.header(name) 的区别

方法返回头不存在时
MailMessage.header(name)Array<string>(所有值)空数组 []
MailMessage.headerValue(name)string(第一个值)null
MailMessage.headers()Object(所有头)空对象 {}

MailMessage.setSeen(value)

  • value {boolean} 是否标记为已读
  • 返回 {boolean}

标记为已读/未读。

js
msg.setSeen(true);   // 标记已读
msg.setSeen(false);  // 标记未读

MailMessage.setFlagged(value)

  • value {boolean} 是否加星标
  • 返回 {boolean}

加星标/取消星标。

js
msg.setFlagged(true);   // 加星标
msg.setFlagged(false);  // 取消星标

MailMessage.setAnswered(value)

  • value {boolean} 是否标记为已回复
  • 返回 {boolean}

标记为已回复/取消标记。部分邮箱无此功能所以无效。

js
msg.setAnswered(true);

MailMessage.setDeleted(value)

  • value {boolean} 是否标记为已删除
  • 返回 {boolean}

标记为已删除/取消标记。有的邮箱会直接删除,有的会移动到已删除文件夹

js
msg.setDeleted(true);   // 标记删除

MailMessage.setDraft(value)

  • value {boolean} 是否标记为草稿
  • 返回 {boolean}

标记为草稿/取消标记。

注意事项

此方法仅设置邮件的草稿(Draft)标记,不会将邮件移动到草稿箱(Drafts)文件夹。

js
msg.setDraft(true);

MailMessage.setRecent(value)

  • value {boolean} 是否标记为新邮件
  • 返回 {boolean}

标记为新邮件/取消标记。

注意事项

Recent 标记通常由 IMAP 服务器自动维护,用于表示邮件是否为当前会话中新到达的邮件。绝大多数 IMAP 服务器不允许客户端修改该标记,因此此方法可能无效。

js
msg.setRecent(true);

MailMessage.setUserFlag(flag, value)

  • flag {string} 自定义标记名称
  • value {boolean} 是否添加标记
  • 返回 {boolean}

设置自定义标记。

注意事项

是否支持自定义标记取决于 IMAP 服务器。多数邮箱服务商不支持或会忽略客户端设置的自定义标记,因此此方法可能无效。

js
msg.setUserFlag("重要", true);

MailMessage.delete()

  • 返回 {boolean}

永久删除邮件。

js
var success = msg.delete();
console.log(success ? "🗑️ 已删除" : "❌ 删除失败");

MailMessage.move(target)

  • target {string} 目标文件夹名称
  • 返回 {boolean}

移动到目标文件夹。

js
msg.move("工作邮件");
console.log("📁 已移动");

MailMessage.copy(target)

  • target {string} 目标文件夹名称
  • 返回 {boolean}

复制到目标文件夹。

js
msg.copy("存档");
console.log("📁 已复制");

MailMessage.reload()

  • 返回 {boolean}

重新加载邮件(刷新状态和内容)。

js
msg.reload();
console.log("🔄 已刷新");

MailMessageCollection

邮件集合,支持数组风格操作。

MailMessageCollection.size()

  • 返回 {number}

获取邮件数量。

js
console.log("邮件数:", messages.size());

MailMessageCollection.get(index)

获取指定索引的邮件。

js
var first = messages.get(0);
console.log("第一封:", first.subject());

MailMessageCollection.forEach(callback)

  • callback {Function} 回调函数 (message, index) => void
    • message {MailMessage} 当前邮件对象
    • index {number} 当前邮件索引
  • 返回 {MailMessageCollection}

遍历所有邮件。

js
messages.forEach(function(message) {
    console.log("📧", message.subject());
});

MailMessageCollection.filter(filter)

过滤邮件。

js
var unread = messages.filter(function(msg) {
    return !msg.seen();
});
console.log("未读:", unread.size(), "封");

MailMessageCollection.find(filter)

  • filter {Function} 过滤函数 (message) => boolean
  • 返回 MailMessage

查找第一个匹配的邮件。

js
var important = messages.find(function(msg) {
    return msg.subject().includes("重要");
});

MailMessageCollection.uids()

  • 返回 {Array<number>}

获取所有邮件的 UID 数组。

js
var uids = messages.uids();
console.log("UIDs:", uids);

MailMessageCollection.subjects()

  • 返回 {Array<string>}

获取所有邮件的主题数组。

js
var subjects = messages.subjects();
for (var i = 0; i < subjects.length; i++) {
    console.log(subjects[i]);
}

MailMessageCollection.froms()

  • 返回 {Array<MailAddress>}

获取所有发件人数组。

js
var froms = messages.froms();

MailMessageCollection.sizes()

  • 返回 {Array<number>}

获取所有邮件大小数组。

js
var sizes = messages.sizes();

MailMessageCollection.setSeen(value)

  • value {boolean} 是否标记为已读
  • 返回 {boolean}

批量标记已读。

js
messages.setSeen(true);
console.log("✅ 全部标记已读");

MailMessageCollection.setFlagged(value)

  • value {boolean} 是否加星标
  • 返回 {boolean}

批量加星标。

js
messages.setFlagged(true);

MailMessageCollection.setAnswered(value)

  • value {boolean} 是否标记已回复
  • 返回 {boolean}

批量标记已回复。

js
messages.setAnswered(true);

MailMessageCollection.setDeleted(value)

  • value {boolean} 是否标记删除
  • 返回 {boolean}

批量标记删除。

js
messages.setDeleted(true);

MailMessageCollection.setDraft(value)

  • value {boolean} 是否标记草稿
  • 返回 {boolean}

批量标记草稿。

js
messages.setDraft(true);

MailMessageCollection.setRecent(value)

  • value {boolean} 是否标记新邮件
  • 返回 {boolean}

批量标记新邮件。

js
messages.setRecent(true);

MailMessageCollection.setUserFlag(flag, value)

  • flag {string} 自定义标记名称
  • value {boolean} 是否添加标记
  • 返回 {boolean}

批量设置自定义标记。

js
messages.setUserFlag("重要", true);

MailMessageCollection.delete()

  • 返回 {boolean}

批量删除。

js
messages.delete();
console.log("🗑️ 已批量删除");

MailMessageCollection.move(target)

  • target {string} 目标文件夹名称
  • 返回 {boolean}

批量移动到目标文件夹。

js
messages.move("存档");
console.log("📁 已批量移动");

MailMessageCollection.copy(target)

  • target {string} 目标文件夹名称
  • 返回 {boolean}

批量复制到目标文件夹。

js
messages.copy("存档");
console.log("📁 已批量复制");

MailAddress

代表一个邮件地址。

MailAddress.address

  • {string} 邮箱地址
js
console.log("地址:", msg.from().address);

MailAddress.personal

  • {string} 显示名称
js
console.log("名称:", msg.from().personal);

MailAddress.name()

  • 返回 {string}

获取显示名称(优先返回 personal,若无则返回 address)。

js
console.log("显示名:", msg.from().name());

MailAddressCollection

邮件地址集合。

MailAddressCollection.size()

  • 返回 {number}

获取地址数量。

js
console.log("地址数:", addresses.size());

MailAddressCollection.get(index)

获取指定索引的地址。

js
var first = addresses.get(0);
console.log("第一个:", first.name());

MailAddressCollection.forEach(callback)

  • callback {Function} 回调函数 (address, index) => void
    • address {MailAddress} 当前地址对象
    • index {number} 当前地址索引
  • 返回 {MailAddressCollection}

遍历所有地址。

js
addresses.forEach(function(address) {
    console.log("📧", address.name(), "<" + address.address() + ">");
});

MailAddressCollection.filter(filter)

过滤地址。

js
var qqAddresses = addresses.filter(function(addr) {
    return addr.address.endsWith("@qq.com");
});

MailAddressCollection.find(filter)

  • filter {Function} 过滤函数 (address) => boolean
  • 返回 MailAddress

查找第一个匹配的地址。

js
var found = addresses.find(function(addr) {
    return addr.address === "[email protected]";
});

MailAddressCollection.addresses()

  • 返回 {Array<string>}

获取所有邮箱地址。

js
var addrs = addresses.addresses();
console.log("地址:", addrs);

MailAddressCollection.names()

  • 返回 {Array<string>}

获取所有显示名称。

js
var names = addresses.names();
console.log("名称:", names);

MailAddressCollection.personals()

  • 返回 {Array<string>}

获取所有个人名称。

js
var personals = addresses.personals();

MailAttachment

代表一个附件。

MailAttachment.id

  • {number} 附件 ID
js
console.log("附件 ID:", att.id);

MailAttachment.fileName

  • {string} 文件名
js
console.log("文件名:", att.fileName);

MailAttachment.contentType

  • {string} MIME 类型
js
console.log("MIME类型:", att.contentType);

MailAttachment.size

  • {number} 文件大小(字节)
js
console.log("大小:", att.size, "bytes");

MailAttachment.inline

  • {boolean} 是否为内嵌图片
js
console.log("内嵌:", att.inline ? "✅" : "❌");

MailAttachment.cid

  • {string} Content-ID(内嵌图片专用)
js
console.log("CID:", att.cid);

MailAttachment.save(path)

  • path {string} 保存路径
  • 返回 {boolean}

保存附件到本地。

js
att.save("/sdcard/Download/" + att.fileName);
console.log("✅ 附件已保存");

MailAttachmentCollection

附件集合。

MailAttachmentCollection.size()

  • 返回 {number}

获取附件数量。

js
console.log("附件数:", attachments.size());

MailAttachmentCollection.get(index)

获取指定索引的附件。

js
var first = attachments.get(0);
console.log("第一个附件:", first.fileName);

MailAttachmentCollection.forEach(callback)

  • callback {Function} 回调函数 (attachment, index) => void
    • attachment {MailAttachment} 当前附件对象
    • index {number} 当前附件索引
  • 返回 {MailAttachmentCollection}

遍历所有附件。

js
attachments.forEach(function(attachment) {
    console.log("📎", attachment.fileName(), "(", attachment.size(), "bytes)");
});

MailAttachmentCollection.filter(filter)

过滤附件。

js
var images = attachments.filter(function(att) {
    return att.contentType.startsWith("image/");
});

MailAttachmentCollection.find(filter)

  • filter {Function} 过滤函数 (attachment) => boolean
  • 返回 MailAttachment

查找第一个匹配的附件。

js
var pdf = attachments.find(function(att) {
    return att.fileName.endsWith(".pdf");
});

MailAttachmentCollection.names()

  • 返回 {Array<string>}

获取所有附件文件名。

js
var names = attachments.names();
console.log("文件名:", names);

MailAttachmentCollection.sizes()

  • 返回 {Array<number>}

获取所有附件大小。

js
var sizes = attachments.sizes();

MailAttachmentCollection.nonInline()

获取所有非内嵌附件(即普通附件)。

js
var normalAtts = attachments.nonInline();

normalAtts.forEach(function(attachment) {
    console.log("📎", attachment.fileName());
});

MailAttachmentCollection.inline()

获取所有内嵌附件(图片)。

js
var inlineAtts = attachments.inline();
console.log("内嵌图片:", inlineAtts.size());

MailAttachmentCollection.totalSize()

  • 返回 {number}

获取所有附件的总大小(字节)。

js
console.log("总大小:", attachments.totalSize(), "bytes");

MailAttachmentCollection.save(dirPath)

  • dirPath {string} 保存目录路径
  • 返回 {boolean}

保存所有附件到指定目录。

js
var success = attachments.save("/sdcard/Download/");
console.log(success ? "✅ 全部保存成功" : "❌ 部分保存失败");

实战示例

读取收件箱邮件

js
var mail = $mail.open({
    account: "[email protected]",
    password: "xndxdclesakidhee"
}, {
    onOpen: function(mail) {
        console.log("✅ 连接成功");
    }
});

var inbox = mail.inbox();
var messages = inbox.load({
    limit: 10,
    loadBody: true
});

console.log("📧 收件箱共有", inbox.size(), "封邮件");
console.log("📧 未读", inbox.unreadCount(), "封");
console.log("📧 加载了", messages.size(), "封");

for (var i = 0; i < messages.size(); i++) {
    var msg = messages.get(i);
    console.log("---");
    console.log("主题:", msg.subject());
    console.log("发件人:", msg.from().name());
    console.log("时间:", new Date(msg.sentDate()).toLocaleString());
    console.log("正文:", msg.body().substring(0, 100) + "...");
    console.log("附件:", msg.attachments().size(), "个");
}

mail.close();

发送邮件

js
var mail = $mail.open({
    account: "[email protected]",
    password: "your_auth_code"
}, {
    onOpen: function(mail) {
        console.log("✅ 连接成功");
    }
});


// 构建包含多张内嵌图片的 HTML 内容
var htmlContent = "<html>" +
    "<body>" +
    "<h1>图片展示</h1>" +
    "<p>图片1(Logo):</p>" +
    "<img src=\"cid:logo\" alt=\"Logo\" style=\"width:200px; border:1px solid #ddd;\"/>" +
    "<p>图片2(图表):</p>" +
    "<img src=\"cid:chart\" alt=\"图表\" style=\"width:300px; border:1px solid #eee;\"/>" +
    "<p>图片3(二维码):</p>" +
    "<img src=\"cid:qrcode\" alt=\"二维码\" style=\"width:150px;\"/>" +
    "</body>" +
    "</html>";

mail.compose()
    .to("[email protected]")
    .subject("带附件和内嵌图片的测试邮件")
    .html(htmlContent)                         // 设置 HTML 内容
    .image("logo", "/sdcard/logo.png")         // 内嵌图片(CID: logo)
    .image("chart", "/sdcard/chart.png")       // 内嵌图片(CID: chart)
    .image("qrcode", "/sdcard/qrcode.png")     // 内嵌图片(CID: qrcode)
    .attach("/sdcard/document.pdf")            // 单个附件
    // .attach(["/sdcard/file1.pdf", "/sdcard/file2.xlsx"]) // 多个附件(注释示例)
    .send();

console.log("✅ 邮件已发送(含附件和内嵌图片)");
mail.close();

加载邮件并批量标记

js
var mail = $mail.open({
    account: "[email protected]",
    password: "your_auth_code"
}, {
    onOpen: function(mail) {
        console.log("✅ 连接成功");
    }
});

var inbox = mail.inbox();

// 加载收件箱最新 20 封邮件(不加载正文以提高速度)
var messages = inbox.load({
    limit: 20,
    loadBody: false,
    markRead: false
});

console.log("📧 加载了", messages.size(), "封邮件");

if (messages.size() > 0) {
    // 批量标记已读和星标
    messages.setSeen(true);
    messages.setFlagged(true);
    console.log("✅ 已全部标记为已读和星标");

    // 移动到工作邮件文件夹(请确保该文件夹存在)
    // messages.move("工作邮件");
    // console.log("✅ 已全部移动到工作邮件");
}

mail.close();

回复邮件

js
var mail = $mail.open({
    account: "[email protected]",
    password: "your_auth_code"
}, {
    onOpen: function(mail) {
        console.log("✅ 连接成功");
    }
});

var messages = mail.inbox().load({ limit: 1 });

if (messages.size() > 0) {
    var msg = messages.get(0);
    mail.reply(msg.uid())
        .text("收到,谢谢!")
        .send();
    console.log("✅ 已回复:", msg.subject());
}

mail.close();

下载附件

js
var mail = $mail.open({
    account: "[email protected]",
    password: "your_auth_code"
}, {
    onOpen: function(mail) {
        console.log("✅ 连接成功");
    }
});

var messages = mail.inbox().load({
    limit: 5,
    loadBody: true
});

for (var i = 0; i < messages.size(); i++) {
    var msg = messages.get(i);
    var attachments = msg.attachments();
    for (var j = 0; j < attachments.size(); j++) {
        var att = attachments.get(j);
        if (!att.inline) {
            var path = "/sdcard/Download/" + att.fileName;
            att.save(path);
            console.log("✅ 已保存:", att.fileName);
        }
    }
}

mail.close();

管理文件夹

js
var mail = $mail.open({
    account: "[email protected]",
    password: "your_auth_code"
}, {
    onOpen: function(mail) {
        console.log("✅ 连接成功");
    }
});

var folders = mail.folders();
console.log("📁 所有文件夹:");
for (var i = 0; i < folders.size(); i++) {
    var folder = folders.get(i);
    console.log("  ", folder.name(), ":", folder.size(), "封");
}

if (!mail.folderExists("工作邮件")) {
    mail.createFolder("工作邮件");
    console.log("✅ 已创建工作邮件文件夹");
}

var workFolder = mail.folder("工作邮件");
console.log("📁 工作邮件:", workFolder.size(), "封");

// 重命名示例(注释)
// mail.renameFolder("工作邮件", "重要邮件");
// console.log("✅ 已重命名");

mail.close();

群发不同收件人(自定义发件人 + 每封邮件间隔发送)

适用于批量通知、邮件推送等场景。每封邮件可以使用不同的发件人、收件人和内容,发送间隔可自定义。

注意事项

  • 每封邮件之间必须留出足够间隔,否则会被服务商判定为垃圾邮件
  • 建议同域名间隔 30 秒以上、切换域名间隔 90 秒以上
  • 发信域名必须已在控制台验证通过;发件地址的规则取决于服务商(域名级 / 地址级),详见 MailBuilder.from(address[, name])
js

// 腾讯云邮件推送(SES)
// SMTP 服务器:gz-smtp.qcloudmail.com(广州)

var mail = $mail.open({
    account: "[email protected]",
    password: "your_smtp_password",
    smtp: {
        host: "gz-smtp.qcloudmail.com",   // 腾讯云邮件推送 广州
        port: 465
    },
    ssl: true,
    startTls: false
}, {
    onOpen: function (m) {
        console.log("✅ 已连接:", m.account());
    }
});
if (!mail) {
    console.log("✗ open() 返回 null");
    exit();
}


// 发件人列表(腾讯云邮件推送 通常支持"域名级验证",前缀可自定义)
var senders = [
    { address: "[email protected]", name: "服务通知" },
    { address: "[email protected]", name: "账号安全" },
    { address: "[email protected]", name: "系统提醒" },
    { address: "[email protected]", name: "设备管理" },
    { address: "[email protected]", name: "运营消息" },
    { address: "[email protected]", name: "客服中心" }
];

// 收件人列表
var recipients = [
    "[email protected]",
    "[email protected]"
];

// 间隔配置(秒)
var INTERVAL        = 30;   // 同一发件人连续发信间隔
var SWITCH_INTERVAL = 90;   // 切换发件人时的间隔

var total = senders.length * recipients.length;
var idx = 0;

console.log("开始群发:" + senders.length + " 个发件人 × " + recipients.length + " 个收件人 = " + total + " 封");

for (var si = 0; si < senders.length; si++) {
    var sender = senders[si];

    // 切换发件人时等待
    if (si > 0) {
        console.log("\n>>> 切换发件人,等待 " + SWITCH_INTERVAL + " 秒...");
        sleep(SWITCH_INTERVAL * 1000);
    }

    for (var ri = 0; ri < recipients.length; ri++) {
        var recipient = recipients[ri];
        idx++;

        var subject = "日常通知 " + new Date().getTime();

        console.log("\n[" + idx + "/" + total + "] 发信: " + sender.address + " → " + recipient);

        try {
            mail.compose()
                .from(sender.address, sender.name)   // 🆕 自定义发件人
                .to(recipient)
                .subject(subject)
                .text("这是一封自动发送的邮件。\n时间: " + new Date())
                .send();

            console.log("         ✓ 发送成功");
        } catch (e) {
            console.log("         ✗ 失败: " + e);
        }

        // 同一发件人内,不是最后一封就等待
        var isLast = (si === senders.length - 1) && (ri === recipients.length - 1);
        if (!isLast && ri < recipients.length - 1) {
            console.log("         等待 " + INTERVAL + " 秒...");
            sleep(INTERVAL * 1000);
        }
    }
}

console.log("\n全部完成: 共 " + total + " 封");
mail.close();
js

// 阿里云邮件推送(Direct Mail)
// SMTP 服务器:smtpdm.aliyun.com(华东 1 / 杭州)

var mail = $mail.open({
    account: "[email protected]",
    password: "your_smtp_password",
    smtp: {
        host: "smtpdm.aliyun.com",   // 阿里云邮件推送
        port: 465
    },
    ssl: true,
    startTls: false
}, {
    onOpen: function (m) {
        console.log("✅ 已连接:", m.account());
    }
});
if (!mail) {
    console.log("✗ open() 返回 null");
    exit();
}


// 发件人列表(阿里云邮件推送 通常要求"地址级验证",必须用控制台已验证的地址)
var senders = [
    { address: "[email protected]", name: "服务通知" },
    { address: "[email protected]", name: "账号安全" },
    { address: "[email protected]", name: "系统提醒" },
    { address: "[email protected]", name: "设备管理" },
    { address: "[email protected]", name: "运营消息" },
    { address: "[email protected]", name: "客服中心" }
];

// 收件人列表
var recipients = [
    "[email protected]",
    "[email protected]"
];

// 间隔配置(秒)
var INTERVAL        = 30;   // 同一发件人连续发信间隔
var SWITCH_INTERVAL = 90;   // 切换发件人时的间隔

var total = senders.length * recipients.length;
var idx = 0;

console.log("开始群发:" + senders.length + " 个发件人 × " + recipients.length + " 个收件人 = " + total + " 封");

for (var si = 0; si < senders.length; si++) {
    var sender = senders[si];

    if (si > 0) {
        console.log("\n>>> 切换发件人,等待 " + SWITCH_INTERVAL + " 秒...");
        sleep(SWITCH_INTERVAL * 1000);
    }

    for (var ri = 0; ri < recipients.length; ri++) {
        var recipient = recipients[ri];
        idx++;

        var subject = "日常通知 " + new Date().getTime();

        console.log("\n[" + idx + "/" + total + "] 发信: " + sender.address + " → " + recipient);

        try {
            mail.compose()
                .from(sender.address, sender.name)
                .to(recipient)
                .subject(subject)
                .text("这是一封自动发送的邮件。\n时间: " + new Date())
                .send();

            console.log("         ✓ 发送成功");
        } catch (e) {
            console.log("         ✗ 失败: " + e);
        }

        var isLast = (si === senders.length - 1) && (ri === recipients.length - 1);
        if (!isLast && ri < recipients.length - 1) {
            console.log("         等待 " + INTERVAL + " 秒...");
            sleep(INTERVAL * 1000);
        }
    }
}

console.log("\n全部完成: 共 " + total + " 封");
mail.close();
js

// 任何支持 SMTP 的服务商(自建、SendGrid、Mailgun 等)
var mail = $mail.open({
    account: "[email protected]",
    password: "your_smtp_password",
    smtp: {
        host: "smtp.example.com",
        port: 465
    },
    ssl: true,
    startTls: false
}, {
    onOpen: function (m) {
        console.log("✅ 已连接:", m.account());
    }
});
if (!mail) {
    console.log("✗ open() 返回 null");
    exit();
}

// 发件人列表
var senders = [
    { address: "[email protected]", name: "服务通知" },
    { address: "[email protected]", name: "账号安全" },
    { address: "[email protected]", name: "系统提醒" }
];

var recipients = ["[email protected]", "[email protected]"];

var INTERVAL        = 30;
var SWITCH_INTERVAL = 90;

var total = senders.length * recipients.length;
var idx = 0;

for (var si = 0; si < senders.length; si++) {
    var sender = senders[si];
    if (si > 0) sleep(SWITCH_INTERVAL * 1000);

    for (var ri = 0; ri < recipients.length; ri++) {
        var recipient = recipients[ri];
        idx++;

        mail.compose()
            .from(sender.address, sender.name)
            .to(recipient)
            .subject("通知 " + new Date().getTime())
            .text("自动发送。\n时间: " + new Date())
            .send();

        console.log("[" + idx + "/" + total + "] ✓ " + sender.address + " → " + recipient);

        var isLast = (si === senders.length - 1) && (ri === recipients.length - 1);
        if (!isLast && ri < recipients.length - 1) {
            sleep(INTERVAL * 1000);
        }
    }
}

mail.close();

批量发送 + 自定义 Message-ID

如果你需要给每封邮件指定唯一的 Message-ID(方便后续追踪、去重、关联业务数据)。

js
var mail = $mail.open({
    account: "[email protected]",
    password: "your_smtp_password",
    smtp: { host: "smtp.example.com", port: 465 },
    ssl: true,
    startTls: false
}, {
    onOpen: function (m) {
        console.log("✅ 已连接:", m.account());
    }
});
if (!mail) {
    console.log("✗ open() 返回 null");
    exit();
}

var recipients = ["[email protected]", "[email protected]"];

for (var i = 0; i < recipients.length; i++) {
    // 生成符合 RFC5322 的唯一 ID
    var uuid = java.util.UUID.randomUUID().toString();
    var msgId = "<" + uuid + "@example.com>";

    mail.compose()
        .from("[email protected]", "服务通知")
        .header("Message-ID", msgId)               // 🆕 走 headers
        .to(recipients[i])
        .subject("带 Message-ID 的通知 " + new Date().getTime())
        .text("这封邮件的 Message-ID 是: " + msgId + "\n时间: " + new Date())
        .send();

    console.log("✓ 已发送到 " + recipients[i] + ",Message-ID: " + msgId);

    // 间隔发送
    if (i < recipients.length - 1) {
        console.log("等待 30 秒...");
        sleep(30000);
    }
}

mail.close();