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
33 changes: 33 additions & 0 deletions src/utils/email-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
interface EmailResult {
accepted: number;
}

export async function sendEmail(
to: string,
subject: string,
body: string,
): Promise<EmailResult> {
const sendgridKey = process.env.SENDGRID_API_KEY;
const fromAddress = process.env.EMAIL_FROM_ADDRESS;
if (!sendgridKey || !fromAddress) {
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

[major] No runtime validation of the input parameters is performed before passing them to the SendGrid API (e.g., to, subject, or body).

Suggestion: Add validation for parameters (to, subject, body) at the start of the function, rejecting improperly formed or empty values before proceeding.

throw new Error("SENDGRID_API_KEY and EMAIL_FROM_ADDRESS must be set");
}

const response = await fetch("https://api.sendgrid.com/v3/mail/send", {
method: "POST",
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

[minor] Raw string URL and email type are hardcoded as magic strings: "https://api.sendgrid.com/v3/mail/send", "text/plain".

Suggestion: Move URLs and fixed values to named constants, or, if configurable, into environment variables.

headers: {
Authorization: `Bearer ${sendgridKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
personalizations: [{ to: [{ email: to }] }],
from: { email: fromAddress },
subject,
content: [{ type: "text/plain", value: body }],
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

[major] No error handling is present for the fetch API call. Failures will throw uncaught exceptions.

Suggestion: Wrap the fetch call in try/catch and handle or propagate errors appropriately.

}),
});
if (!response.ok) {
throw new Error(`SendGrid send failed: ${response.status} ${response.statusText}`);
}
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

[major] The function promises an explicit EmailResult return type, but returns the parsed response.json() object, which is not guaranteed to match the EmailResult interface.

Suggestion: Explicitly shape and check the response JSON to match EmailResult before returning, or map/validate its structure before returning.

return response.json();
}
Loading