MailDev REST API 完全指南:邮件查看、过滤、分页与实时推送实战

发布时间:2026/10/10 1:41:03
MailDev REST API 完全指南:邮件查看、过滤、分页与实时推送实战 后端开发工具测试【免费下载链接】maildev:mailbox: SMTP Server Web Interface for viewing and testing emails during development.项目地址https://gitcode.com/gh_mirrors/ma/maildev点击查看免费下载MailDev 是一款面向开发场景的 SMTP 服务器与 Web 邮件查看工具它在收下开发邮件的同时通过http://localhost:1080暴露了一组易于消费的 REST API供脚本、CI 流水线和自定义前端直接读写邮件数据。本文以 docs/rest.md 为骨架结合 packages/api/src/server.ts 的路由实现与 packages/api/src/tests/summary.test.ts 等测试用例带你完整掌握 MailDev REST API 的端点用法、分页/过滤规则、大规模收件箱的摘要式读取方案以及 Socket.IO 实时推送机制读完即可用它搭建自己的邮件测试仪表盘或自动化校验脚本。一、访问约定Base URL、路径前缀与 basePathname所有 API 路由统一挂在/api前缀之下默认服务地址为http://localhost:1080GET http://localhost:1080/api/email两个可配置项会影响访问路径若通过 CLI 设置了--base-pathname或以编程方式传入basePathname/basePath配置项它会被拼在/api前缀之前。例如配置为/maildev后端点地址变成http://localhost:1080/maildev/api/email。除特别说明的二进制内容如 HTML 源码、附件流、.eml下载外所有数据都以 JSON 返回。在实现层面路由注册时正是通过const apiPath ${basePath}/api 来拼接前缀的见 packages/api/src/server.ts。默认端口为1080、默认绑定主机为0.0.0.0DEFAULT_PORT/DEFAULT_HOST常量监听成功后控制台会打印形如MailDev API running at http://localhost:1080的日志若传入port: 0操作系统会分配一个临时端口可通过getAddress()/getPort()获取实际绑定的端口。二、邮件数据结构一次完整响应示例先看最常用的GET /api/email——它返回收件箱中的全部邮件含正文。单封邮件 JSON 结构如下[{ id: XwgKAxto, time: 2026-01-05T19:02:09.156Z, read: false, subject: The ex-presidents are surfers, from: [{ address: angelo.pappasfbi.gov, name: Angelo Pappas }], to: [{ address: johnny.utahfbi.gov, name: Johnny Utah }], cc: [], date: 2026-01-05T19:02:09.000Z, text: The wax at the bank was surfer wax!!!, html: !DOCTYPE htmlhtmlhead/headbodypThe wax at the bank was surfer wax!!!/p/body/html, headers: { content-type: multipart/mixed; boundary\--_boundary\, from: Angelo Pappas angelo.pappasfbi.gov, to: Johnny Utah johnny.utahfbi.gov, subject: The ex-presidents are surfers, message-id: 1412535729142-cc4cb0f1fbi.gov, date: Sun, 05 Jan 2026 19:02:09 0000, mime-version: 1.0 }, priority: normal, attachments: [{ filename: attachment-1.txt, generatedFileName: attachment-1.txt, contentType: text/plain, contentDisposition: attachment, contentId: 0958713110a99ea2afc3b117c9d5feb3maildev, size: 24 }], envelope: { from: { address: angelo.pappasfbi.gov }, to: [{ address: johnny.utahfbi.gov }], host: djf-3.local, remoteAddress: 127.0.0.1 }, size: 1024, sizeHuman: 1 KB, relayedAt: 2026-01-05T19:05:11.482Z, relayedTo: [johnny.utahfbi.gov] }]各字段含义对应核心类型定义 packages/core/src/types/email.ts 中的Email接口字段说明id8 位字母数字组成的唯一标识time邮件被接收的时间戳read是否已读subject邮件主题from/to/cc解析后的地址列表每项含address与可选namedate邮件头中的 Date 时间text/html纯文本 / HTML 正文HTML 已被清洗headers原始邮件头键值对priority优先级normal/high/lowattachments附件元数据含原始文件名、MD5 生成的generatedFileName、MIME 类型、contentDispositioninline内嵌或attachment下载、contentId与大小envelopeSMTP 协议层信息发件人、收件人、来源主机名host与发送方远程地址remoteAddresssize/sizeHuman字节数与人类可读大小relayedAt/relayedTo最近一次成功转发到外部服务器的时间戳与送达收件人要点relayedAt和relayedTo只有在邮件被成功转发到出站服务器后才会出现从未被转发过的邮件不会携带这两个字段。邮件 ID 与字段投影逻辑均可在核心包源码中验证。三、端点速查表以下路径均相对/api前缀/api之前可叠加 basePathname方法路径说明GET/api/email/summary获取一页邮件摘要新邮件在前适合大型收件箱见后文GET/api/email获取全部邮件支持过滤与分页GET/api/email/:id按 ID 获取单封邮件会将其标记为已读DELETE/api/email/:id按 ID 删除单封邮件POST/api/email/delete按 ID 数组批量删除DELETE/api/email/all删除全部邮件PATCH/api/email/read-all将所有邮件标记为已读返回被标记的数量GET/api/email/:id/html获取某封邮件的 HTML 正文内嵌附件资源GET/api/email/:id/source获取原始邮件源RFC 822 格式GET/api/email/:id/download将邮件下载为.eml文件GET/api/email/:id/attachment/:filename获取某封邮件的文件附件POST/api/email/:id/relay/:relayTo?若配置了出站转发将邮件转发到其真实收件地址或覆盖为可选的relayTo收件人GET/api/reloadMailsFromDirectory从配置的邮件目录重新加载邮件GET/api/config获取应用配置GET/api/healthz健康检查四、核心操作详解4.1 读取单封邮件GET /api/email/:idcurl http://localhost:1080/api/email/XwgKAxto返回完整邮件 JSON。两个值得注意的实现细节见 packages/api/src/server.ts读取即置为已读若该邮件尚未被读过服务端会先将其read置为true并持久化再通过 Socket.IO 广播readMail事件让其他打开的标签页同步更新未读角标。404 语义ID 不存在时返回{ error: Email was not found }状态码 404。4.2 删除邮件DELETE /api/email/:id 与 DELETE /api/email/allcurl -X DELETE http://localhost:1080/api/email/XwgKAxto curl -X DELETE http://localhost:1080/api/email/all单封删除成功返回true未找到返回 404。实现上deleteEmail()会优先走 SMTP 服务的删除路径以便触发删除事件、保持附件与源文件一致仅当没有 SMTP 实例时才直接操作存储层。清空收件箱时有 SMTP 实例会调用smtp.deleteAllEmails()否则调用storage.deleteAll()。4.3 批量删除POST /api/email/delete一次请求删除指定的一组邮件请求体必须包含ids数组{ ids: [XwgKAxto, 29wQJq2q] }响应同时返回已删除与未找到的 ID{ deleted: [XwgKAxto], notFound: [29wQJq2q] }实现上的健壮性保障server.tsids非数组、或包含非字符串/空白字符串时返回400与错误信息Request body must include an ids array of email IDs。重复 ID 会经new Set(ids)去重后再逐个删除因此同一 ID 只会出现一次。逐个删除过程中遇到异常会返回500。4.4 全部标为已读PATCH /api/email/read-allcurl -X PATCH http://localhost:1080/api/email/read-all返回本次被标记为已读的邮件数量数字。仅当计数大于 0 时才会向各客户端广播readAllMail事件。对应测试 summary.test.ts 验证了 1 万封邮件的收件箱可在单次请求内完成标记。4.5 HTML、源文件、下载与附件这些端点专门面向「在浏览器里渲染邮件」与「取证/归档」两类场景# 返回渲染好的 HTML 正文text/html内嵌附件已按 Content-ID 嵌入 curl http://localhost:1080/api/email/XwgKAxto/html # 返回原始 RFC 822 邮件源 curl http://localhost:1080/api/email/XwgKAxto/source # 下载为 .eml 文件响应带 Content-Disposition: attachment curl -O http://localhost:1080/api/email/XwgKAxto/download # 下载某附件 curl -O http://localhost:1080/api/email/XwgKAxto/attachment/attachment-1.txt实现说明HTML 端点优先调用 SMTP 服务的getEmailHtml(id, { basePath })以text/html返回若邮件没有 HTML 正文则返回404Email has no HTML content。没有 SMTP 实例时退化为直接从存储读取email.html。source、download、attachment三个端点依赖 SMTP 服务提供原始邮件流与附件流在仅有存储层storage-only的模式下会返回 404提示对应数据不可用。4.6 转发到真实收件人POST /api/email/:id/relay/:relayTo?当 MailDev 配置了出站 SMTP 转发relay后可用该端点把某封开发邮件真正发送出去# 转发给邮件的原始 to 收件人 curl -X POST http://localhost:1080/api/email/XwgKAxto/relay # 覆盖收件人 curl -X POST http://localhost:1080/api/email/XwgKAxto/relay/qa-teamexample.com成功时返回true并做两件事在邮件上记录relayedAt最近一次成功转发的时间戳与relayedTo实际送达的收件人列表之后通过/api/email等端点读取时会看到这两个字段若配置了邮件目录文件存储该状态会持久化到磁盘、重启后仍然保留而使用内存存储时状态只存活于进程生命周期内。前置条件与校验server.ts未配置 SMTP 实例时返回500SMTP server not configured未启用出站转发时返回500Outgoing mail not configured提供的relayTo不符合邮箱正则时返回400Incorrect email address provided: ...且relayTo会同时改写邮件头to与信封envelope.to。4.7 目录重载与运行信息# 重新从配置的 mail 目录加载邮件用于外部往目录里灌 .eml 文件的场景 curl http://localhost:1080/api/reloadMailsFromDirectory # 应用配置供前端展示与开关联动 curl http://localhost:1080/api/config # 健康检查始终可用即使开启了 Basic Auth 也无需认证 curl http://localhost:1080/api/healthz/api/config返回结构见 types.ts 的ConfigResponseversion版本号、smtpPortSMTP 端口无 SMTP 实例时为undefined、isOutgoingEnabled出站转发是否启用、outgoingHost转发主机未配置时为null。/api/healthz的实现就是async () true因此响应体为 JSONtrue。五、分页与排序GET /api/email支持简单的 skip/limit 分页GET /api/email?skip10limit25规则不传limit时返回从skip起的所有邮件——注意该端点没有隐式上限这是为了兼容旧调用方「一次拿全收件箱」的习惯server.ts。默认按到达顺序arrival order返回传入sort后改为按接收时间排序——sortdesc新邮件在前、sortasc旧邮件在前。sort只在显式提供时生效。与limit组合可只取最近 N 封GET /api/email?limit25sortdesc分页参数解析使用parsePositiveInt非数字或负数会被静默忽略并回退为默认值。对应的测试用例覆盖了「保留字不泄漏为过滤字段」「无sort保持到达顺序」「sortdesc返回最新邮件」等行为summary.test.ts。六、过滤任意字段精确匹配 点号嵌套GET /api/email的另一大能力是简单过滤。规则如下任何不是保留关键字skip、limit以及排序用的sort的查询参数都被当作对返回邮件某个字段的精确匹配过滤器。嵌套字段可用点号语法寻址例如from.addressvalue。多个过滤参数之间是「与」关系全部满足才返回。目标字段为数组时如from本身是数组只要数组中存在一个元素匹配即视为通过。示例GET /api/email?subjectBig wave coming # 只返回主题精确等于 Big wave coming 的邮件 GET /api/email?from.addressangelo.pappasfbi.gov # 只返回发件地址精确匹配该值的邮件 GET /api/email?readfalsesubjecttest # 只返回未读且主题精确等于 test 的邮件实现层面过滤发生在服务端server.ts 的filterEmails查询参数中剔除skip、limit、sort后逐字段比对核心包 packages/core/src/utils/filter.ts 提供了同样的点号取值工具getNestedValues支持形如from.0.address的数组下标寻址并处理数组元素映射取值。七、大型收件箱的正确打开方式GET /api/email/summary7.1 为什么需要摘要端点GET /api/email会完整返回每一封邮件的正文。邮件只有几封时很省事但收件箱累积到数千封时序列化整批数据会非常昂贵——一个 10,000 封邮件的收件箱序列化后体积轻松超过 100 MBWeb 界面如果每几秒轮询一次这种接口带宽与解析成本都不可接受。GET /api/email/summary正是为此设计它返回有界的一页摘要——没有html、text、headers这些体积大户——同时附带分页所需的计数。这正是 Web 界面列表页实际使用的接口。7.2 查询参数GET /api/email/summary?skip0limit50searchwelcomesortdescunreadtrue参数默认说明skip0跳过的匹配邮件数limit50每页大小上限被钳制为 200search—对主题、参与人、正文进行不区分大小写的全文搜索sortdescdesc新邮件在前asc旧邮件在前unread—true时只返回未读邮件分页上限的硬性约束来自源码常量MAX_PAGE_SIZE 200与DEFAULT_PAGE_SIZE 50server.ts即便客户端请求limit100000响应仍会被钳制到 200 条limit0或缺失时按一页 50 条处理存储层将 0 视为无界必须在此拦截。测试 summary.test.ts 专门覆盖了默认页大小、超大 limit 钳制、非法分页参数忽略与limit0语义。7.3 响应结构{ items: [ { id: abc123, time: 2026-07-27T09:12:44.000Z, read: false, subject: The ex-presidents are surfers, size: 3072, sizeHuman: 3 KB, from: [{ address: angelo.pappasfbi.gov, name: Angelo Pappas }], to: [{ address: johnny.utahfbi.gov, name: Johnny Utah }], attachmentCount: 1, preview: The wax at the bank was surfer wax!!! } ], total: 1024, storeTotal: 1024, unread: 17, skip: 0, limit: 50 }计数语义要区分清楚total匹配search条件的邮件总数忽略 skip/limitstoreTotal整个存储中的邮件总数忽略搜索与分页unread整个存储中的未读邮件数忽略搜索与分页。三个数字组合起来前端无需再发额外请求即可渲染「筛选结果 / 总量 / 未读角标」。摘要投影由核心包 packages/core/src/utils/summary.ts 的toSummary完成只保留 ID、时间、已读状态、主题、大小、收发件人、附件数与正文预览preview取自纯文本正文的前 140 个字符PREVIEW_LENGTH 140空白被压缩为单空格仅当存在cc时才附带该字段。测试验证了同样的收件箱下完整接口响应超过 5 MB 而摘要接口不到 50 KB——这正是列表页坚持使用摘要接口的原因summary.test.ts。7.4 服务端搜索search参数在服务端执行命中范围为主题、发件人/收件人/抄送地址及其显示名、纯文本正文全部不区分大小写matchesSearchTerm实现于 filter.ts。测试?searchsurf同时命中主题含 surfers 与正文含 surfer wax 的邮件且storeTotal不受搜索影响。八、实时更新Socket.IO除了 REST APIWeb 服务器还在/socket.io挂载了一个 Socket.IO 端点路径同样受 basePathname 前缀影响用于实时通知事件触发时机载荷newMail新邮件到达一封邮件的摘要与/api/email/summary的条目同构并非完整邮件deleteMail邮件被删除含id及index的对象readMail某封邮件被读取{ id }readAllMail全部标为已读无载荷实现要点server.tsSocket.IO 服务器直接挂载在底层 HTTP server 上CORS 默认放开origin: *。服务端只在 SMTP 实例上挂一次事件监听再统一广播给所有连接避免「每开一个标签页就加一对监听器」导致 EventEmitter max-listeners 告警。newMail只推送摘要而非完整邮件新邮件到来时每个标签页都要刷新列表和通知若把完整正文推给所有客户端一次邮件洪峰就会让带宽与序列化成本失控。需要正文时客户端再按需请求GET /api/email/:id。九、补充认证、CORS、HTTPS 与 MCPHTTP Basic Auth配置auth.type basic后除/api/healthz外的所有路由都需要Authorization: Basic ...头未认证或凭据错误会返回 401 并携带WWW-Authenticate: Basic realmMailDev响应头。健康检查始终放行便于负载均衡器探活。CORS默认允许任意来源并携带凭据可通过cors.origin/cors.credentials收紧。HTTPS传入https: true并指向 PEM 格式的httpsCert/httpsKey文件后整个 API/UI 以 HTTPS 提供服务证书文件读取失败会直接抛出错误拒绝启动。MCP 端点启用mcp.enabled后服务还会在basePath/mcp提供 Model Context Protocol 端点JSON-RPC over Streamable HTTP SSE供 AI Agent 程序化读取、删除邮件与获取附件详见 docs/mcp.md。它默认以本服务器自身的 Web 地址生成邮件深链反向代理场景下可用mcp.webUrl覆盖。十、实践建议组合 REST WebSocket 的典型场景把上述能力串起来一个典型的邮件测试仪表盘可以这样设计页面加载后先请求GET /api/email/summary?limit50sortdesc渲染列表用返回的total/storeTotal/unread渲染统计条与未读角标订阅 Socket.IO 的newMail/deleteMail/readMail/readAllMail事件做增量刷新而不再整页轮询点击某封邮件时请求GET /api/email/:id获取完整正文该请求会顺带把它置为已读预览时用/html端点渲染带内嵌附件图文的正文CI 断言环节用GET /api/email/summary?search关键字unreadtrue做服务端搜索式校验用POST /api/email/delete批量清理测试邮件用GET /api/healthz做就绪探针。如需继续深入建议直接阅读 REST 路由实现的完整源码 packages/api/src/server.ts、API 配置类型 packages/api/src/types.ts、核心存储与摘要投影 packages/core/src/utils/summary.ts以及覆盖以上全部行为的测试 packages/api/src/tests/server.test.ts 与 packages/api/src/tests/summary.test.ts。赞分享后端开发工具测试【免费下载链接】maildev:mailbox: SMTP Server Web Interface for viewing and testing emails during development.项目地址https://gitcode.com/gh_mirrors/ma/maildev点击查看免费下载相关推荐MainsailOS多摄像头实时流媒体指南CrowsnestNginx反代配置一次看懂MainsailOS多摄像头实时流媒体指南CrowsnestNginx反代配置一次看懂 MainsailOS 是面向 Klipper 3D 打印机的树莓派Prisma API 查询Queries完全指南对象查询、Connection 分页与过滤排序实战Prisma API 查询Queries完全指南对象查询、Connection 分页与过滤排序实战 本指南以 Prisma 1.x 服务端 API 为对象后端数据库GraphQLBepInEx 插件注入与加载机制解析从 Doorstop 到 Chainloader 的启动链路BepInEx 插件注入与加载机制解析从 Doorstop 到 Chainloader 的启动链路 给 Unity 游戏加装第三方功能最常见的卡点不是写代码游戏开发插件系统上一篇Naabu与NMAP集成终极服务发现与漏洞探测组合指南下一篇LINQ to GameObject源码解读ComponentCache实现原理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询