Skip to content

Created SES module#158

Open
dburkhart07 wants to merge 4 commits into
mainfrom
ddb/aws-ses-module
Open

Created SES module#158
dburkhart07 wants to merge 4 commits into
mainfrom
ddb/aws-ses-module

Conversation

@dburkhart07
Copy link
Copy Markdown

ℹ️ Issue

Closes #138

📝 Description

For this PR, I created the SES module. I did some research into good practices, and made a few changes to our practice in general. The PR follows SSF's SES creation for the most part, with a few modifications. The justification for each is below:

  1. The AWS SES Wrapper: This wrapper takes in multiple recipients at the start. Since we do not want recipients seeing all the other emails it was sent to, we loop through the actual client send to send them over one at a time. I also added a more specific typing, that has either a successful message (a sent status and the output), or a failed message (a failed status and the error).

  2. The AWS SES Factory: Rather than using an assert statement, I made sure to throw specific errors so that the user can know early on what the issue is with their emails sending or not, making debugging easier. I also made it so we pass in the specific AWS access key and secret into the credentials to do verification explicitly in the client.

  3. Email service: Beforehand, we were not using the rate limiter at all. In the instance of some malicious attack or accidental sending, we have implemented a strict rate limiting of 14 per second (likely will not go over these in most of our projects but still good to have). In the case where we do go over, rather than throwing an error, it will just put it into a queue to send afterwards.

  4. The dto: I added a DTO for specific input validation before emails are send. This dto makes sure all emails are formatted correctly and unique, the subject of the email does not contain any CR or or LF characters, sets a max limit to the html (5-10 KB of string memory), and validates that each attachment does not contain paths, and is a 10MB file at most (to avoid exceeding SES's raw-message cap of 40 MB).

I also updated the example env and wrote tests

✔️ Verification

Tested all the different cases in the email service using mocks and manually in Postman.

NOTE: Will need to remove the created endpoint before moving. It is just there now for whoever reviews this to test.

🏕️ (Optional) Future Work / Notes

Currently, all env variables are verified at injection time of the service. There is an option to make all env variables be verified at runtime using a Config module. Not sure if there is any interest in doing that.

@dburkhart07 dburkhart07 requested a review from maxn990 as a code owner May 12, 2026 23:45
Copy link
Copy Markdown
Member

@maxn990 maxn990 left a comment

Choose a reason for hiding this comment

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

looks great overall, especially the super thorough readme and dto!

Comment thread example.env Outdated
Comment thread apps/backend/src/users/users.controller.ts
Comment thread example.env Outdated
@maxn990 maxn990 requested a review from chnnick May 13, 2026 14:09
Copy link
Copy Markdown

@chnnick chnnick left a comment

Choose a reason for hiding this comment

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

LGTM! tbh not sure if third party wrappers typically get tests so can disregard comment.

Comment thread apps/backend/src/aws/ses/email.service.spec.ts Outdated
Comment thread apps/backend/src/aws/ses/sendEmail.dto.ts
Comment thread apps/backend/src/users/users.controller.ts
@dburkhart07 dburkhart07 requested a review from maxn990 May 15, 2026 07:37
Copy link
Copy Markdown
Member

@maxn990 maxn990 left a comment

Choose a reason for hiding this comment

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

Nice! One thing I didn't catch the first time, but the factory throws an error at startup if AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, or AWS_REGION are missing, which means the app won't boot without valid AWS credentials even when SEND_AUTOMATED_EMAILS is not 'true', which undermines the purpose of having the flag.

A fix might be to check SEND_AUTOMATED_EMAILS in the factory and skip credential validation when it's inactive, maybe returning a dummy client instead

@dburkhart07
Copy link
Copy Markdown
Author

Nice! One thing I didn't catch the first time, but the factory throws an error at startup if AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, or AWS_REGION are missing, which means the app won't boot without valid AWS credentials even when SEND_AUTOMATED_EMAILS is not 'true', which undermines the purpose of having the flag.

A fix might be to check SEND_AUTOMATED_EMAILS in the factory and skip credential validation when it's inactive, maybe returning a dummy client instead

Added a dummy client creation. Also made updates to include cc and bcc emails, as well as change email sending to only single (very likely that, should a user want to send multiple of the exact same email, then cc/bcc would be a better option for them).

@dburkhart07 dburkhart07 requested a review from maxn990 May 16, 2026 06:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SES Module

3 participants