npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-daily-mail

v0.1.0

Published

Read-first mailbox access (search/read/thread + local reply drafts, never sends) for the DeepSeek Harness (developer preview)

Downloads

54

Readme

mail

dsh(DeepSeek Harness)插件:邮箱读取、分类浏览、摘要与回复草稿。首版明确只读 + 本地草稿——不调用任何发送、删除、改标 API。

状态:developer preview。尚未在真实 dsh 运行时中验证,手动验证步骤见下文。

工具

| 工具 | 说明 | 级别 | | --- | --- | --- | | mail_search | 按关键词/发件人/收件人/主题/时间范围/未读/标签搜索,返回摘要列表(发件人、主题、日期、snippet、标签、未读、有无附件),最新在前 | 只读 | | mail_read | 读取单封邮件完整正文(text/plain 优先,text/html 降级为纯文本);附件默认只返回元数据 | 只读(附件下载默认关) | | mail_thread | 展开会话线程,返回全部邮件正文,按时间正序 | 只读 | | mail_draft_reply | 生成回复草稿写入本地草稿目录(.eml/.md,含 In-Reply-To/References 线程头)。绝不发送 | L1 本地写入 |

Provider

首版实现 gmail(Gmail API v1,users.messages.list/getusers.threads.getusers.messages.attachments.get,全部 GET)。

IMAP 未做(v2 计划):Node 无内置 IMAP 客户端,零依赖自研 IMAP 协议不现实;v2 计划引入成熟纯 JS 库(如 imapflow,MIT、无 native 依赖)并锁版本实现 ImapProviderMailProvider 接口与配置 union 已为此预留位置。

安装与配置

# dsh 配置示例
- id: mail
  name: dsh-daily-mail
  config:
    enabled: true
    provider: gmail
    defaultMaxResults: 20        # mail_search 默认条数
    draftDir: ./mail-drafts      # mail_draft_reply 的草稿输出目录
    downloadAttachments: false   # 默认关:附件只有元数据
    attachmentDir: ./mail-attachments  # 附件下载目录(仅 downloadAttachments=true 时生效)
    timeoutMs: 10000
    retry: true                  # 网络错误/5xx 重试一次
    gmail:
      accessTokenEnv: GMAIL_ACCESS_TOKEN
      refreshTokenEnv: GMAIL_REFRESH_TOKEN   # 三件套可选:配齐后 401 自动刷新
      clientIdEnv: GMAIL_CLIENT_ID
      clientSecretEnv: GMAIL_CLIENT_SECRET

凭证务实方案(与 calendar 插件一致):无内置 OAuth 授权流程,访问令牌由用户经环境变量提供;配齐 refresh 三件套后,首个 401 会自动刷新一次(https://oauth2.googleapis.com/token),否则给出可读的"凭证过期"错误。

权限透明

  • 读写位置:仅写 draftDir(草稿,.eml/.md)和 attachmentDir(附件,默认关闭)。除此之外不读写任何本地文件。
  • 网络域名gmail.googleapis.com(邮件 API);仅当配齐 refresh 三件套且令牌过期时访问 oauth2.googleapis.com(刷新令牌)。无其他外联。
  • 凭证:从环境变量读取 OAuth2 令牌(变量名可配置,默认 GMAIL_ACCESS_TOKEN 等),配置中只存变量名不存值;刷新后的令牌只缓存在进程内存。
  • 确认点mail_draft_reply 是 L1 本地写操作(写草稿目录),描述已声明;无任何远端写操作,无 L2。
  • 日志内容:启动日志记录 provider、草稿/附件目录、已配置的凭证环境变量(不记录值);草稿落盘时记录文件路径。邮件正文、令牌值不进入日志。

已知限制

  • 不发送:草稿需要用户自行检查后用邮件客户端发送;.emlX-Unsent: 1 与正确的 In-Reply-To/References,导入支持该约定的客户端可直接入草稿箱。
  • 附件下载是全部或全无(配置级开关),粒度为单封邮件的全部附件。
  • MIME 解析为自研轻量实现:支持嵌套 multipart、base64/quoted-printable、RFC 2047 编码头(B/Q)、RFC 2231 filename*=;charset 支持 UTF-8 与 GBK/GB2312,其他字符集声明降级为 UTF-8(替换字符);不支持 PGP/MIME,message/rfc822 视为不透明附件。
  • mail_search 时间过滤按 Gmail after:/before: 语义以 UTC 日期(天)为粒度。
  • 回复草稿不携带自己的 Message-ID(由发送方在发送时分配);reply-all 因不知本机地址,仅简单合并原收件人/抄送,需用户自查。
  • 线程排序按 Date 头(缺失时回退 Gmail internalDate)。

手动验证

本仓库的 CI 只覆盖类型检查与纯函数单测(含 fetch 替身的 Gmail 流程)。接入真实 dsh 后请手动验证:

  1. 准备令牌:Google Cloud Console 建 OAuth 客户端(scope https://www.googleapis.com/auth/gmail.readonly 即可),用 OAuth playground 或脚本换 access token(需要自动刷新再记 refresh token),写入对应环境变量。
  2. 在 dsh 配置中启用本插件,确认启动日志出现 mail: loaded
  3. 让 agent 调用 mail_search(如"未读邮件"),确认返回摘要列表且 unread 标记正确。
  4. 用返回的 id 调 mail_read,确认正文解码正确(中文不乱码);HTML-only 邮件应提示降级。
  5. 用 threadId 调 mail_thread,确认按时间正序展开。
  6. mail_draft_reply,确认草稿文件出现在 draftDir、内容含 In-Reply-To/References,且邮箱中没有任何已发送邮件
  7. downloadAttachments 设为 true 后 mail_read 一封带附件邮件,确认附件写入 attachmentDir 且文件名无路径穿越。

许可

MIT