From bb8e6ee60f69372cd7d5e8436e1e8dd99c83c570 Mon Sep 17 00:00:00 2001 From: chamiakJ Date: Thu, 10 Jul 2025 12:28:52 +0530 Subject: [PATCH] refactor(email): enhance email validation and improve bounced email handling - Added isValidateEmail utility function to validate email addresses before sending. - Updated email filtering logic to remove empty, null, undefined, and invalid emails from the recipient list. - Reversed the iteration order in removeMails function to prevent index issues while splicing bounced emails. - Ensured that valid emails are present after filtering before proceeding with the email sending process. --- worklenz-backend/src/shared/email.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/worklenz-backend/src/shared/email.ts b/worklenz-backend/src/shared/email.ts index 83e93651..e0a0f679 100644 --- a/worklenz-backend/src/shared/email.ts +++ b/worklenz-backend/src/shared/email.ts @@ -1,7 +1,7 @@ import {SendEmailCommand, SESClient} from "@aws-sdk/client-ses"; import {Validator} from "jsonschema"; import {QueryResult} from "pg"; -import {log_error} from "./utils"; +import {log_error, isValidateEmail} from "./utils"; import emailRequestSchema from "../json_schemas/email-request-schema"; import db from "../config/db"; @@ -33,7 +33,7 @@ function isValidMailBody(body: IEmail) { async function removeMails(query: string, emails: string[]) { const result: QueryResult<{ email: string; }> = await db.query(query, []); const bouncedEmails = result.rows.map(e => e.email); - for (let i = 0; i < emails.length; i++) { + for (let i = emails.length - 1; i >= 0; i--) { const email = emails[i]; if (bouncedEmails.includes(email)) { emails.splice(i, 1); @@ -54,11 +54,20 @@ export async function sendEmail(email: IEmail): Promise { const options = {...email} as IEmail; options.to = Array.isArray(options.to) ? Array.from(new Set(options.to)) : []; + // Filter out empty, null, undefined, and invalid emails + options.to = options.to + .filter(email => email && typeof email === 'string' && email.trim().length > 0) + .map(email => email.trim()) + .filter(email => isValidateEmail(email)); + if (options.to.length) { await filterBouncedEmails(options.to); await filterSpamEmails(options.to); } + // Double-check that we still have valid emails after filtering + if (!options.to.length) return null; + if (!isValidMailBody(options)) return null; const charset = "UTF-8";