Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 24 additions & 24 deletions worklenz-backend/src/shared/email.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import {SendEmailCommand, SESClient} from "@aws-sdk/client-ses";
import {Validator} from "jsonschema";
import {QueryResult} from "pg";
import {log_error, isValidateEmail} from "./utils";
import nodemailer from "nodemailer";
import { Validator } from "jsonschema";
import { QueryResult } from "pg";
import { log_error, isValidateEmail } from "./utils";
import emailRequestSchema from "../json_schemas/email-request-schema";
import db from "../config/db";

const sesClient = new SESClient({region: process.env.AWS_REGION});
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT || 587),
secure: false,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
Comment on lines +8 to +16

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Hardcoded secure: false may break port 465 (SMTPS) configurations.

Port 587 uses STARTTLS (where secure: false is correct), but port 465 requires secure: true for implicit TLS. Users configuring SMTP_PORT=465 will experience connection failures.

🔧 Proposed fix to auto-detect secure mode
 const transporter = nodemailer.createTransport({
   host: process.env.SMTP_HOST,
   port: Number(process.env.SMTP_PORT || 587),
-  secure: false,
+  secure: Number(process.env.SMTP_PORT || 587) === 465,
   auth: {
     user: process.env.SMTP_USER,
     pass: process.env.SMTP_PASS,
   },
 });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT || 587),
secure: false,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT || 587),
secure: Number(process.env.SMTP_PORT || 587) === 465,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@worklenz-backend/src/shared/email.ts` around lines 8 - 16, The nodemailer
transporter configuration in the email.ts file has `secure: false` hardcoded,
which only works correctly for port 587 (STARTTLS) but fails for port 465
(SMTPS) which requires `secure: true`. Make the `secure` property dynamic by
checking the SMTP_PORT value: if the port is 465, set `secure: true`; otherwise
set it to `false`. This ensures the transporter configuration works correctly
regardless of which SMTP port is configured.


export interface IEmail {
to?: string[];
Expand Down Expand Up @@ -50,6 +58,11 @@ async function filterBouncedEmails(emails: string[]): Promise<void> {
}

export async function sendEmail(email: IEmail): Promise<string | null> {
if (process.env.ENABLE_EMAIL !== "true") {
console.log("EMAIL DESACTIVADO (ENABLE_EMAIL=false)");
return null;
}

try {
const options = {...email} as IEmail;
options.to = Array.isArray(options.to) ? Array.from(new Set(options.to)) : [];
Expand All @@ -72,27 +85,14 @@ export async function sendEmail(email: IEmail): Promise<string | null> {

const charset = "UTF-8";

const command = new SendEmailCommand({
Destination: {
ToAddresses: options.to
},
Message: {
Subject: {
Charset: charset,
Data: options.subject
},
Body: {
Html: {
Charset: charset,
Data: options.html
}
}
},
Source: "Worklenz <noreply@worklenz.com>"
await transporter.sendMail({
from: process.env.FROM_EMAIL || "Worklenz <no-reply@worklenz.com>",
to: options.to.join(","),
subject: options.subject,
html: options.html,
});

const res = await sesClient.send(command);
return res.MessageId || null;
return "SMTP_OK";
} catch (e) {
log_error(e);
}
Expand Down