@@ -30,10 +30,14 @@ const reserveMonthlyMailSlot = async (projectId, limit) => {
3030 const ttlSeconds = getEndOfMonthTtlSeconds ( now ) ;
3131 const key = getMailCountKey ( projectId , monthKey ) ;
3232
33- const count = await redis . incr ( key ) ;
34- if ( count === 1 ) {
35- await redis . expire ( key , ttlSeconds ) ;
36- }
33+ const luaScript = `
34+ local current = redis.call("INCR", KEYS[1])
35+ if current == 1 then
36+ redis.call("EXPIRE", KEYS[1], ARGV[1])
37+ end
38+ return current
39+ ` ;
40+ const count = await redis . eval ( luaScript , 1 , key , ttlSeconds ) ;
3741
3842 if ( count > limit ) {
3943 await redis . decr ( key ) ;
@@ -51,20 +55,22 @@ module.exports.sendMail = async (req, res) => {
5155 try {
5256 if ( req . keyRole !== "secret" ) {
5357 return res . status ( 403 ) . json ( {
54- error : "Forbidden. This action requires a Secret Key (sk_live_...)." ,
58+ success : false ,
59+ data : { } ,
60+ message : "Forbidden. This action requires a Secret Key (sk_live_...)." ,
5561 } ) ;
5662 }
5763
5864 const { to, subject, html, text } = sendMailSchema . parse ( req . body || { } ) ;
5965 const projectId = req . project ?. _id ;
6066
6167 if ( ! projectId ) {
62- return res . status ( 401 ) . json ( { error : "Project context missing." } ) ;
68+ return res . status ( 401 ) . json ( { success : false , data : { } , message : "Project context missing." } ) ;
6369 }
6470
6571 const project = await loadProjectMailConfig ( projectId ) ;
6672 if ( ! project ) {
67- return res . status ( 404 ) . json ( { error : "Project not found." } ) ;
73+ return res . status ( 404 ) . json ( { success : false , data : { } , message : "Project not found." } ) ;
6874 }
6975
7076 const encryptedByokKey =
@@ -79,7 +85,7 @@ module.exports.sendMail = async (req, res) => {
7985 : process . env . RESEND_API_KEY_2 || process . env . RESEND_API_KEY ;
8086
8187 if ( ! clientKey ) {
82- return res . status ( 500 ) . json ( { error : "Resend API key is not configured." } ) ;
88+ return res . status ( 500 ) . json ( { success : false , data : { } , message : "Resend API key is not configured." } ) ;
8389 }
8490
8591 const limit = getMonthlyMailLimit ( req . project ) ;
@@ -125,12 +131,16 @@ module.exports.sendMail = async (req, res) => {
125131
126132 if ( err instanceof z . ZodError ) {
127133 return res . status ( 400 ) . json ( {
128- error : err . issues ?. [ 0 ] ?. message || "Invalid mail payload." ,
134+ success : false ,
135+ data : { } ,
136+ message : err . issues ?. [ 0 ] ?. message || "Invalid mail payload." ,
129137 } ) ;
130138 }
131139
132140 return res . status ( err . statusCode || 500 ) . json ( {
133- error : err . message || "Failed to send mail." ,
141+ success : false ,
142+ data : { } ,
143+ message : err . message || "Failed to send mail." ,
134144 ...( typeof err . limit === "number" ? { limit : err . limit } : { } ) ,
135145 } ) ;
136146 }
0 commit comments