Logto 阿里云邮件推送(DirectMail)连接器实战指南:从控制台配置到签名发送的源码实现原理
Logto 阿里云邮件推送DirectMail连接器实战指南从控制台配置到签名发送的源码实现原理【免费下载链接】logto Authentication and authorization infrastructure for SaaS and AI apps, built on OIDC and OAuth 2.1 with multi-tenancy, SSO, and RBAC.项目地址: https://gitcode.com/GitHub_Trending/lo/logto本文以 Logto 仓库中的阿里云邮件推送官方连接器 connector-aliyun-dm 文档为核心完整还原在阿里云 DirectMail 控制台开通发信服务、编写连接器 JSON 配置含accessKeyId、templates、usageType等全部字段并测试验证的实战流程同时结合 源码实现 深入讲解地域与 Endpoint 映射、HMAC-SHA1 请求签名算法、模板 Handlebars 替换与配置校验的底层机制。读完本文你既能独立跑通「邮件验证码登录/注册」的接入配置也能理解 Logto 邮件连接器sendMessage从配置解析到调用阿里云SingleSendMailAPI 的完整调用链。什么是阿里云邮件推送连接器阿里云是亚洲地区重要的云服务厂商提供包括邮件服务在内的多种云服务。阿里云邮件推送DirectMail简称 DM连接器是 Logto 团队提供的官方插件用于调用阿里云 DM 服务的 API帮助 Logto 终端用户通过邮件验证码完成注册和登录即用户通过邮箱接收随机验证码来标识身份。从 元数据定义 可以看到该连接器的身份标识属性值说明idaliyun-direct-mail连接器唯一 ID用于 Logto 内部标识targetaliyun-dm平台目标标识类型ConnectorType.Email属于邮件类连接器名称Aliyun Direct Mail / 阿里云邮件推送支持 en、zh-CN、tr-TR、ko 多语言该连接器发布为 npm 包logto/connector-aliyun-dm当前版本 1.6.2要求 Node^22.14.0核心依赖为logto/connector-kit连接器开发套件、gotHTTP 客户端和zod配置校验。在阿里云邮件服务控制台中配置发信服务提示如果以下某些步骤你已完成可以跳过对应小节。注册阿里云账号前往阿里云官网并注册账号如无账号。开通并配置阿里云邮件推送服务进入阿里云 DirectMail 产品页并登录点击页面左上的「申请开通」按钮开通邮件服务开始配置流程。从 DirectMail 管理控制台开始需要完成两件事在侧边栏进入「发信域名」Email Domains点按「新建域名」并按指引完成域名添加含 DNS 验证分别配置「发信地址」Sender Addresses和「邮件标签」Email Tags。完成设置后阿里云提供了两种测试方法进入控制台概览页在页面底部找到「操作引导」Operation Guide点按「发送邮件」Send Emails页面列出了多种不同的测试方式在侧边栏按「发送邮件」→「邮件任务」的路径进入「新建发送任务」创建测试任务。创建 AccessKey完成发信域名与地址配置后即可为连接器准备访问凭证在 DirectMail 管理控制台鼠标悬停在右上角头像进入「AccessKey 管理」点按「创建 AccessKey」。通过安全验证后你会得到一对「AccessKey ID」和「AccessKey Secret」请妥善保管回到控制台的「发信地址」或「邮件标签」页签确认之前创建的发信地址和邮件标签后续配置需要用到。编写连接器的 JSON配置项说明在 Logto 管理控制台创建该邮件连接器时需要填写的配置项如下与文档中的 Config types 表一致并经 配置守卫 源码校验印证NameType说明accessKeyIdstring步骤 1 创建得到的 AccessKey IDaccessKeySecretstringAccessKey SecretregionIdstring (OPTIONAL)发信地址所在的 DirectMail 地域默认cn-hangzhouaccountNamestring发信地址fromAliasstring (OPTIONAL)邮件标签发件人别名所有模板共享该签名名templatesTemplate[]邮件模板数组Template PropertiesTypeEnum valuessubjectstring邮件标题contentstring任意字符串内容必须保留{{code}}占位符用于随机验证码usageTypeenum stringRegister \| SignIn \| ForgotPassword \| Generic关于usageType它是 Logto 侧的属性用于标识模板对应的使用场景注册、登录、忘记密码、通用。为了能使用完整的用户流程Register、SignIn、ForgotPassword和Generic四种模板缺一不可——这一点在源码的aliyunDmConfigGuard中有硬性校验见下文「配置校验」小节。从 表单默认值 还可以看到控制台创建该连接器时templates字段预填了 9 个场景的模板除上述 4 个必填项外还包括OrganizationInvitation组织邀请、UserPermissionValidation权限验证、BindNewIdentifier绑定新标识、MfaVerificationMFA 验证、BindMfa绑定 MFA。regionId与请求 Endpoint 的对应关系regionId可选值在 constant.ts 中枚举并映射到各区域 API 端点源码中共支持 5 个地域regionId地域Endpointcn-hangzhou默认China (Hangzhou)https://dm.aliyuncs.com/ap-southeast-1Singaporehttps://dm.ap-southeast-1.aliyuncs.com/ap-southeast-2United States (formerly Sydney)https://dm.ap-southeast-2.aliyuncs.com/eu-central-1Germany (Frankfurt)https://dm.eu-central-1.aliyuncs.com/us-east-1US (Virginia)https://dm.us-east-1.aliyuncs.com/regionId未填写时会回落到默认值cn-hangzhouconst { regionId defaultRegionId } config这一行为有 单测用例 验证不传RegionId时请求命中杭州端点传ap-southeast-1时端点切换为新加坡并同步携带RegionId参数。一份可复制的完整配置示例综合文档说明与 表单默认模板一个最小可用覆盖全部 4 个必填场景的连接器配置如下占位符需替换为你的真实值{ accessKeyId: access-key-id, accessKeySecret: access-key-secret, regionId: cn-hangzhou, accountName: 发信地址如 noreplyexample.com, fromAlias: 邮件标签可留空, templates: [ { usageType: SignIn, subject: Logto 登录验证码, content: Your Logto sign-in verification code is {{code}}. The code will remain active for 10 minutes. }, { usageType: Register, subject: Logto 注册验证码, content: Your Logto sign-up verification code is {{code}}. The code will remain active for 10 minutes. }, { usageType: ForgotPassword, subject: Logto 密码重置验证码, content: Your Logto password change verification code is {{code}}. The code will remain active for 10 minutes. }, { usageType: Generic, subject: Logto 验证码, content: Your Logto verification code is {{code}}. The code will remain active for 10 minutes. } ] }几点注意content为任意字符串类型内容支持 HTML{{code}}占位符在真实发送时会被替换为随机生成的验证码替换逻辑见下文「模板替换」小节可以添加多个模板应对不同场景usageType相同的模板只允许一条被优先匹配regionId只需与「发信地址」所在的地域一致即可默认cn-hangzhou。发送链路源码走读sendMessage是如何工作的理解源码有助于排查配置不生效、收不到邮件等问题。核心实现在 index.ts 的sendMessage闭包中整体调用链为sendMessage(data, inputConfig) ├─ validateConfig(config, aliyunDmConfigGuard) // zod 校验配置 ├─ 选取模板getI18nEmailTemplate可选 ?? getConfigTemplateByType ├─ replaceSendMessageHandlebars(subject/content) // {{code}} 等变量替换 ├─ singleSendMail(parameters, accessKeySecret) // 调用阿里云 SingleSendMail API └─ sendEmailResponseGuard 校验响应 / errorHandler 解析错误关键逻辑逐项说明配置校验每次发送前用aliyunDmConfigGuard校验配置。该 zod schema 除了对regionId做 5 个合法地域的枚举约束外还通过refine强制templates中必须同时包含Register、SignIn、ForgotPassword、Generic四种usageType缺失时直接报错指出缺哪几类模板——这就是文档中「需要配置四类模板」的技术依据。模板选取优先级发送时优先尝试getI18nEmailTemplate?.(type, payload.locale)获取国际化自定义模板只有获取失败时才回落到连接器配置中的getConfigTemplateByType(type, config)模板。若两者都没有抛出ConnectorError(ConnectorErrorCodes.TemplateNotFound, Cannot find template for type: ...)。固定的 API 参数singleSendMail调用时固定传入ReplyToAddress: false、AddressType: 1账号类型地址并将accountName、to、替换后的subject/HtmlBody组装为阿里云SingleSendMail接口的业务参数。发件人别名FromAlias若命中国际化自定义模板且其sendFrom字段非空则用replaceSendMessageHandlebars(customTemplate.sendFrom, payload)渲染后的结果作为FromAlias支持{{applicationName}}等变量否则使用连接器配置中的fromAlias。测试用例 验证了sendFrom: Foo {{applicationName}}会被渲染为FromAlias: Foo bar。模板替换Handlebars 语法subject与content中的{{code}}等占位符通过 connector-kit 提供的replaceSendMessageHandlebars完成替换替换数据来自调用方传入的payload。集成测试 展示了两种典型替换效果登录场景payload: { code: 1234 }contentYour sign-in code is {{code}}, {{code}} is your code与subjectSign-in code {{code}}分别被替换为Your sign-in code is 1234, 1234 is your code和Sign-in code 1234组织邀请场景payload: { code, link }{{link}}可被替换为完整的邀请 URL说明模板变量不限于验证码。请求签名HMAC-SHA1 算法实现连接器并未使用阿里云官方 SDK而是在 utils.ts 中手工实现了阿里云 RPC 风格 API 的请求签名SignatureVersion 1.0这是该连接器最有技术含量的部分阿里云专用转义规则先encodeURIComponent再将其默认保留的 8 个字符强制转义为%XX形式——!→%21、→%22、→%27、(→%28、)→%29、*→%2A、→%2B规范化查询串将所有参数按 key 排序拼成keyvalue...的规范串再整体转义一次待签名串StringToSign POST%2F{转义后的规范串}即METHOD escape(/) escape(canonicalizedQuery)计算签名以accessKeySecret 为密钥做 HMAC-SHA1输出 Base64发送request函数补充SignatureNoncerandomUUID()保证幂等防重放与TimestampYYYY-MM-DDThh:mm:ssZ格式截去毫秒最终用got.post以application/x-www-form-urlencoded表单形式提交Signature作为附加字段。签名单测 用固定参数与密钥testsecret断言出确定签名值llJfXJjBW3OacrVgxxsITgYaYm0可作为算法实现的回归基准请求组装测试则验证了Timestamp、SignatureNonce、Signature均被正确附加到 POST 表单。API 版本与静态参数singleSendMail在 single-send-mail.ts 中将业务参数与静态参数合并后发出静态参数定义于 constant.ts{ Action: SingleSendMail, Format: json, SignatureMethod: HMAC-SHA1, SignatureVersion: 1.0, Version: 2015-11-23, }即连接器固定调用阿里云 DM2015-11-23版本的SingleSendMail单封邮件发送接口。响应校验与错误处理发送结果经过两层防御成功路径响应体 JSON 用sendEmailResponseGuard校验要求包含EnvId与RequestId两个字段校验失败抛ConnectorError(ConnectorErrorCodes.InvalidResponse)HTTP 错误路径捕获got抛出的HTTPError后用sendMailErrorResponseGuard字段Code、Message、RequestId?、HostId?、Recommend?对应阿里云错误结构解析错误响应体提取Message作为errorDescription包装成ConnectorError(ConnectorErrorCodes.General, ...)抛出。这样 Logto 管理控制台在连接器测试页能展示阿里云返回的原始错误信息如发信地址未认证、域名未验证等。测试与验证在 Logto 控制台中测试按文档操作在「保存并完成」之前输入一个真实邮箱地址并点按「发送」即可验证配置是否可正常工作。测试通过后保存连接器。大功告成之后还有一步不能少在 Logto 的「体验」Sign-in Experience中启用该邮件连接器与邮箱验证码登录方式终端用户才能真正通过邮件验证码注册/登录。仓库中的单元/集成测试该连接器的质量保障由 Vitest 测试套件 承担pnpm test即vitest run src覆盖三层测试文件验证点index.test.tssendMessage按type选对模板并正确替换{{code}}regionId为ap-southeast-1时正确透传自定义国际化模板优先且sendFrom变量渲染为FromAliassingle-send-mail.test.ts默认/指定地域下 Endpoint 选择正确且请求参数携带Action: SingleSendMail与对应RegionIdutils.test.tsHMAC-SHA1 签名确定值断言request正确附加时间戳、Nonce 与签名types.test.ts配置守卫缺失必填usageType模板时的报错信息测试数据集中在 mock.ts其中mockedParameters使用a%b这类包含特殊字符的AccountName专门覆盖阿里云转义规则中容易出错的边界。小结阿里云邮件推送连接器以「官方文档的操作步骤 轻量级自签名 HTTP 实现」组合成为 Logto 邮件验证码场景下面向国内云用户的标准接入方案接入侧在阿里云控制台完成发信域名、发信地址、邮件标签与 AccessKey 准备后按accessKeyId/accessKeySecret/regionId/accountName/fromAlias/templates六项填写连接器配置四类usageType模板齐备即可支撑完整用户流程实现侧sendMessage链路完成了「zod 配置校验 → 国际化/配置模板选取 → Handlebars 变量替换 → 地域端点解析 → HMAC-SHA1 签名 →SingleSendMail调用 → 响应/错误双重 guard」的闭环任何一环失败都会以带错误码的ConnectorError暴露到管理控制台便于定位问题。【免费下载链接】logto Authentication and authorization infrastructure for SaaS and AI apps, built on OIDC and OAuth 2.1 with multi-tenancy, SSO, and RBAC.项目地址: https://gitcode.com/GitHub_Trending/lo/logto创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考