From 370467544593ba6bb8fe8c682ba4ec40e2557794 Mon Sep 17 00:00:00 2001 From: npmrun <1549469775@qq.com> Date: Mon, 20 Apr 2026 22:02:12 +0800 Subject: [PATCH] feat(email): add nodemailer type definitions and enhance comment email test logging - Added TypeScript definitions for nodemailer to improve type safety in email handling. - Refactored comment email test handler to utilize a dedicated logger for better error tracking and debugging. - Simplified email configuration retrieval by consolidating it into a single object for clarity and maintainability. This update enhances the email notification system's robustness and developer experience. --- bun.lock | 3 ++ package.json | 1 + packages/drizzle-pkg/db.sqlite | Bin 147456 -> 147456 bytes .../api/config/global/comment-email-test.post.ts | 33 +++++++++++++++------ server/service/comment-notify/index.ts | 8 +++++ 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/bun.lock b/bun.lock index 4885469..35569ac 100644 --- a/bun.lock +++ b/bun.lock @@ -37,6 +37,7 @@ "@types/better-sqlite3": "7.6.13", "@types/markdown-it": "14.1.2", "@types/multer": "2.1.0", + "@types/nodemailer": "^8.0.0", "@types/pg": "8.20.0", "bun-types": "1.3.12", "drizzle-kit": "0.31.10", @@ -857,6 +858,8 @@ "@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="], + "@types/nodemailer": ["@types/nodemailer@8.0.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-fyf8jWULsCo0d0BuoQ75i6IeoHs47qcqxWc7yUdUcV0pOZGjUTTOvwdG1PRXUDqN/8A64yQdQdnA2pZgcdi+cA=="], + "@types/pg": ["@types/pg@8.20.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow=="], "@types/qs": ["@types/qs@6.15.0", "", {}, "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow=="], diff --git a/package.json b/package.json index 9af8330..b3bc43a 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "@types/better-sqlite3": "7.6.13", "@types/markdown-it": "14.1.2", "@types/multer": "2.1.0", + "@types/nodemailer": "^8.0.0", "@types/pg": "8.20.0", "bun-types": "1.3.12", "drizzle-kit": "0.31.10", diff --git a/packages/drizzle-pkg/db.sqlite b/packages/drizzle-pkg/db.sqlite index df4dbd1ef024636b0885143bf66e9bfefa7dc99c..62e65044c0cc183cc6e9a8cf49f4d05d5b632144 100644 GIT binary patch delta 1222 zcma)5Ur19?7{BM<9re!L^C|wR)c$Dpcdj|zovx^5u-r>&#e#y$Ij^C)Ew{UeB5)-{ z6g1;P_aUU7da+uvVlUC^v0fIHguN66DXboXNT|rpG157q;=tuQ=X}54_x*n7ezBMs zi-{vuJU?@#W*7aAcipw}RvVC+R0%Svmbqo=je;!v7eEcT|xCX3VV?6vgx znp^&iOUB6{@ksZjVOqv74Kb)Qq}d^o6Cw}%)0rr=84;78q8V?uxp`HHVR$C5T4uV)l*waNI}8X7z|()LUw%fUP7hkdY}WMLDOk=dki@ zHBEVE?7fOB1Z!^IZ@-Lrnamq8?~Lg!S}w?c(DQG}v=pvdDY*XJELB&aUATTm!sH7F zwJ-ta;2=qsj$9+!tveoz85fB1f;WG$rNKR+)h29)u?BZqJD9jxNrR`%77S4iqVNPh zKpbwfKOCx77{vKr7ja@Oo{ka>A2|2{GZgX}vUG}G0yYRD!pUr=@)>C-+c#tH_(!4-JL)W03@21;YbEX*-Dk%Mdt|GscR3>X&xqZNTa7LeS_Ya zKy~_T8etO;(;Q60SGH0mkI)OKflnMRnkx_AIgtSf+s$c9&1R6XOXxHGOxBhR6{jw3 qxsPUO~*Sb-w`TVu1z# delta 499 zcmWkqOK1~O6n%H{hGx>qyAw%Tl~g)0bfF7Bq$_Fspf$Tx!S2Mi5L!Q^rM81}s5KaUm`gE7mug!?|$oIrm)0F&xLZv0a1e zbo_|I#lG?$X}3qQsgvrb3|;5_*(A>%d?~jaN+92B?dGSmQbtBTqx^m*+8#lN=&Vk# zhEFhx8CF-@?-;LN&(ZsDGQcx#%21@45R!`VZEhQmjgIFAhKDcY`txvSzLPJyNhLl0 zgV)@hF-007rPZ-O@C&}e87!cT%*`^Dz03>uE}0Z@ zdbQ;}vZF)~uMu`GyoNXNuxHIdifM$1?giMOCyg)>$4c-VnXBp#5mseG>=xEMs|-^N z48dQ(gfGVmyrmt16Cip@kPw>{&`ljz2!6vAT*VE~T7nN4rvU?kKIrO3gDPPD6!O8_ ztU{` UYrDkjE^UWbPit+U-ZAs@KP4rj4*&oF diff --git a/server/api/config/global/comment-email-test.post.ts b/server/api/config/global/comment-email-test.post.ts index 1ae2340..6c7950c 100644 --- a/server/api/config/global/comment-email-test.post.ts +++ b/server/api/config/global/comment-email-test.post.ts @@ -1,3 +1,4 @@ +import log4js from "logger"; import { dbGlobal } from "drizzle-pkg/lib/db"; import { users } from "drizzle-pkg/lib/schema/auth"; import { eq } from "drizzle-orm"; @@ -9,6 +10,8 @@ import { sendCommentEmailTestMail, } from "#server/service/comment-email/test-mail"; +const logger = log4js.getLogger("COMMENT_EMAIL_TEST"); + export default defineWrappedResponseHandler(async (event) => { const ip = getRequestIP(event, { xForwardedFor: true }) ?? "unknown"; assertUnderRateLimit(`admin-config-comment-email-test:${ip}`, 5, 60_000); @@ -21,19 +24,21 @@ export default defineWrappedResponseHandler(async (event) => { .where(eq(users.id, admin.id)) .limit(1); + const commentEmailConfig = { + enabled: await event.context.config.getGlobal("commentEmailNotifyEnabled"), + fromEmail: await event.context.config.getGlobal("commentMailFromEmail"), + smtpHost: await event.context.config.getGlobal("commentSmtpHost"), + smtpPort: await event.context.config.getGlobal("commentSmtpPort"), + smtpSecure: await event.context.config.getGlobal("commentSmtpSecure"), + smtpUser: await event.context.config.getGlobal("commentSmtpUser"), + smtpPass: await event.context.config.getGlobal("commentSmtpPass"), + }; + try { await sendCommentEmailTestMail({ toEmail: adminRow?.email ?? "", requestedBy: admin.username, - config: { - enabled: await event.context.config.getGlobal("commentEmailNotifyEnabled"), - fromEmail: await event.context.config.getGlobal("commentMailFromEmail"), - smtpHost: await event.context.config.getGlobal("commentSmtpHost"), - smtpPort: await event.context.config.getGlobal("commentSmtpPort"), - smtpSecure: await event.context.config.getGlobal("commentSmtpSecure"), - smtpUser: await event.context.config.getGlobal("commentSmtpUser"), - smtpPass: await event.context.config.getGlobal("commentSmtpPass"), - }, + config: commentEmailConfig, }); return R.success({ message: "测试邮件发送成功,请检查管理员邮箱", @@ -45,6 +50,16 @@ export default defineWrappedResponseHandler(async (event) => { statusMessage: error.message, }); } + logger.error( + "[send-test-mail-failed]", + `adminId=${admin.id}`, + `adminUsername=${admin.username}`, + `smtpHost=${commentEmailConfig.smtpHost}`, + `smtpPort=${commentEmailConfig.smtpPort}`, + `smtpSecure=${commentEmailConfig.smtpSecure}`, + error instanceof Error ? error.message : String(error), + error instanceof Error ? (error.stack ?? "") : "", + ); throw createError({ statusCode: 502, statusMessage: "测试邮件发送失败,请检查 SMTP 配置或稍后重试", diff --git a/server/service/comment-notify/index.ts b/server/service/comment-notify/index.ts index 6eb2978..daf75f1 100644 --- a/server/service/comment-notify/index.ts +++ b/server/service/comment-notify/index.ts @@ -42,6 +42,13 @@ function getReason(error: unknown): string { return "unknown"; } +function getStack(error: unknown): string { + if (error instanceof Error && hasValue(error.stack ?? "")) { + return error.stack ?? ""; + } + return ""; +} + function isValidEmail(value: string): boolean { return EMAIL_REGEX.test(value.trim()); } @@ -205,6 +212,7 @@ export async function notifyReplyCommentCreated( commentId: input.commentId, receiverUserId, reason: getReason(error), + stack: getStack(error), }); } }