forked from Code-4-Community/scaffolding
-
Notifications
You must be signed in to change notification settings - Fork 0
[SSF 109]: Email automation spike #84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dburkhart07
wants to merge
37
commits into
main
Choose a base branch
from
ddb/SSF-109-email-automation-spike
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,777
−2,482
Open
Changes from all commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
0174e6b
Completed initial implementation of an endpoint, awaiting access to API
dburkhart07 1751e95
prettier
dburkhart07 dd951da
Initial setup of email testing
dburkhart07 5729ebc
Added DTO
dburkhart07 9e78a8d
merged main
dburkhart07 51324d2
prettier
dburkhart07 01f5974
Fixed dependencies
dburkhart07 02b001b
Fixed tests
dburkhart07 9007244
prettier
dburkhart07 39a9c95
Merged main
dburkhart07 d7a43ec
Fixed dependencies
dburkhart07 c870fca
Updated dependencies
dburkhart07 091c3a6
Fixed dependencies
dburkhart07 d6fa280
Fixed dependencies
dburkhart07 84eab2b
Final dependency fix
dburkhart07 0be9d5b
Another attempt at fixing dependencies
dburkhart07 2726548
Deleted yarn.lock temporarily
dburkhart07 c2eb2e9
Readded dependency
dburkhart07 26a0c77
Fixed dependencies and merged main
dburkhart07 d885c47
prettier
dburkhart07 93e7fec
Fixed email service
dburkhart07 0369280
Fixed email service
dburkhart07 e3e576b
Fixed dependencies
dburkhart07 d166795
fixed dependencies
dburkhart07 97a679b
please fix the dependencies this time
dburkhart07 2428076
another attempt
dburkhart07 11837ac
another attempt at fixing dependencies
dburkhart07 570982e
pls work
dburkhart07 c52a4b5
another fix
dburkhart07 84dee62
updateed workflow
dburkhart07 d41cec7
updated workflow
dburkhart07 9b7604b
fixed dep
dburkhart07 8f09fdf
fixed dep
dburkhart07 d2cbc60
pls pls pls work
dburkhart07 4c51c7c
Changes and adjustments fro sendEmail to have multiple email addresse…
dburkhart07 257ed14
prettier
dburkhart07 eb05092
Merged main
dburkhart07 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| import { Inject, Injectable } from '@nestjs/common'; | ||
| import { SESv2Client, SendEmailCommand } from '@aws-sdk/client-sesv2'; | ||
| import MailComposer from 'nodemailer/lib/mail-composer'; | ||
| import * as dotenv from 'dotenv'; | ||
| import Mail from 'nodemailer/lib/mailer'; | ||
| import { AMAZON_SES_CLIENT } from './awsSesClient.factory'; | ||
| dotenv.config(); | ||
|
|
||
| export interface EmailAttachment { | ||
| filename: string; | ||
| content: Buffer; | ||
| } | ||
|
|
||
| @Injectable() | ||
| export class AmazonSESWrapper { | ||
| private client: SESv2Client; | ||
|
|
||
| /** | ||
| * @param client injected from `awsSesClient.factory.ts` | ||
| * builds our Amazon SES v2 client with credentials from environment variables | ||
| */ | ||
| constructor(@Inject(AMAZON_SES_CLIENT) client: SESv2Client) { | ||
| this.client = client; | ||
| } | ||
|
|
||
| /** | ||
| * Sends an email via Amazon SES. | ||
| * | ||
| * @param recipientEmails the email addresses of the recipients | ||
| * @param subject the subject of the email | ||
| * @param bodyHtml the HTML body of the email | ||
| * @param attachments any attachments to include in the email | ||
| * @resolves if the email was sent successfully | ||
| * @rejects if the email was not sent successfully | ||
| */ | ||
| async sendEmails( | ||
| recipientEmails: string[], | ||
| subject: string, | ||
| bodyHtml: string, | ||
| attachments?: EmailAttachment[], | ||
| ) { | ||
| const mailOptions: Mail.Options = { | ||
| from: process.env.AWS_SES_SENDER_EMAIL, | ||
| to: recipientEmails, | ||
| subject: subject, | ||
| html: bodyHtml, | ||
| }; | ||
|
|
||
| if (attachments) { | ||
| mailOptions.attachments = attachments.map((a) => ({ | ||
| filename: a.filename, | ||
| content: a.content, | ||
| encoding: 'base64', | ||
| })); | ||
| } | ||
|
|
||
| const messageData = await new MailComposer(mailOptions).compile().build(); | ||
|
|
||
| const command = new SendEmailCommand({ | ||
| Content: { | ||
| Raw: { | ||
| Data: messageData, | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| return await this.client.send(command); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| import { Provider } from '@nestjs/common'; | ||
| import { SESv2Client } from '@aws-sdk/client-sesv2'; | ||
| import { assert } from 'console'; | ||
| import * as dotenv from 'dotenv'; | ||
| dotenv.config(); | ||
|
|
||
| export const AMAZON_SES_CLIENT = 'AMAZON_SES_CLIENT'; | ||
|
|
||
| /** | ||
| * Factory that produces a new instance of the Amazon SES v2 client. | ||
| * Used to send emails via Amazon SES and actually set it up with credentials. | ||
| */ | ||
| export const AmazonSESClientFactory: Provider<SESv2Client> = { | ||
| provide: AMAZON_SES_CLIENT, | ||
| useFactory: () => { | ||
| assert( | ||
| process.env.AWS_ACCESS_KEY_ID !== undefined, | ||
| 'AWS_ACCESS_KEY_ID is not defined', | ||
| ); | ||
| assert( | ||
| process.env.AWS_SECRET_ACCESS_KEY !== undefined, | ||
| 'AWS_SECRET_ACCESS_KEY is not defined', | ||
| ); | ||
| assert(process.env.AWS_REGION !== undefined, 'AWS_REGION is not defined'); | ||
|
|
||
| return new SESv2Client({ region: process.env.AWS_REGION }); | ||
| }, | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import { Module } from '@nestjs/common'; | ||
| import { EmailsService } from './email.service'; | ||
| import { AmazonSESWrapper } from './awsSes.wrapper'; | ||
| import { AmazonSESClientFactory } from './awsSesClient.factory'; | ||
|
|
||
| @Module({ | ||
| providers: [AmazonSESWrapper, AmazonSESClientFactory, EmailsService], | ||
| exports: [EmailsService], | ||
| }) | ||
| export class EmailsModule {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import { Injectable, Logger } from '@nestjs/common'; | ||
| import Bottleneck from 'bottleneck'; | ||
| import { AmazonSESWrapper, EmailAttachment } from './awsSes.wrapper'; | ||
|
|
||
| @Injectable() | ||
| export class EmailsService { | ||
| private readonly EMAILS_SENT_PER_SECOND = 14; | ||
| private readonly logger = new Logger(EmailsService.name); | ||
| private readonly limiter: Bottleneck; | ||
|
|
||
| constructor(private amazonSESWrapper: AmazonSESWrapper) { | ||
| this.limiter = new Bottleneck({ | ||
| minTime: Math.ceil(1000 / this.EMAILS_SENT_PER_SECOND), | ||
| maxConcurrent: 1, | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Sends an email. | ||
| * | ||
| * @param recipientEmail the email address of the recipients | ||
| * @param subject the subject of the email | ||
| * @param bodyHtml the HTML body of the email | ||
| * @param attachments any base64 encoded attachments to inlude in the email | ||
| * @resolves if the email was sent successfully | ||
| * @rejects if the email was not sent successfully | ||
| */ | ||
| public async sendEmails( | ||
| recipientEmails: string[], | ||
| subject: string, | ||
| bodyHTML: string, | ||
| attachments?: EmailAttachment[], | ||
| ): Promise<unknown> { | ||
| return this.amazonSESWrapper.sendEmails( | ||
| recipientEmails, | ||
| subject, | ||
| bodyHTML, | ||
| attachments, | ||
| ); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import { | ||
| IsString, | ||
| IsOptional, | ||
| IsNotEmpty, | ||
| MaxLength, | ||
| IsEmail, | ||
| IsArray, | ||
| } from 'class-validator'; | ||
| import { EmailAttachment } from './awsSes.wrapper'; | ||
|
|
||
| export class SendEmailDTO { | ||
| @IsArray() | ||
| @IsEmail({}, { each: true }) | ||
| @MaxLength(255, { each: true }) | ||
| toEmails!: string[]; | ||
|
|
||
| @IsString() | ||
| @IsNotEmpty() | ||
| @MaxLength(255) | ||
| subject!: string; | ||
|
|
||
| @IsString() | ||
| @IsNotEmpty() | ||
| bodyHtml!: string; | ||
|
|
||
| @IsArray() | ||
| @IsOptional() | ||
| attachments?: EmailAttachment[]; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this shouldn't be a public route. right now this would mean that, once deployed, anyone who could access the api could send unlimited emails from our aws account. if you've finished role based auth, i would recommend adding a guard, otherwise commenting this out for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it was going to be changed after we merged in the role based auth. i can just comment it out and whoever tests this next can uncomment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
either way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gotcha, either way works