-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* SLSCMN-8 email service * SLSCMN-8 email service tests * SLSCMN-8 docs
- Loading branch information
Showing
6 changed files
with
201 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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 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,98 @@ | ||
:house: [Home](/README.md) | :books: [Docs](../DOCS.md) | ||
|
||
# Email Service | ||
|
||
This document describes how to use the Email service component, `EmailService`, to send email messages. | ||
|
||
## How it works | ||
|
||
There is an Email microservice within the LeanStacks ecosystem. This microservice encapsulates all of the logic to actually send transactional emails. The email microservice receives requests to create and send emails from a AWS SQS Queue. | ||
|
||
When another component needs to send an email, it simply needs to send a message to that Queue. | ||
|
||
## Using `EmailService` | ||
|
||
The `EmailService` uses the `SQSService` to send a message to the email queue. The message bodies must contain all of the information needed by the Email microservice to create the email message. | ||
|
||
To send an email message you will need: | ||
|
||
- The SQS Queue URL for the LeanStacks Email Microservice | ||
- An AWS SES email template | ||
- The `EmailService` from `@leanstacks/serverless-common` | ||
|
||
### The email queue | ||
|
||
The LeanStacks email microservice publishes a CloudFormation output variable containing the URL of the AWS SQS queue to which it listens for requests. In Serverless Framework specifications, that CloudFormation variable is referenced as illustrated below. | ||
|
||
```yaml | ||
params: | ||
default: | ||
emailResourcesStack: ls-service-email-resources-${sls:stage} | ||
|
||
...omitted for brevity... | ||
|
||
provider: | ||
environment: | ||
EMAIL_QUEUE_URL: ${cf:${param:emailResourcesStack}.BulkTemplatedEmailQueueUrl} | ||
``` | ||
First, the email microservice CloudFormation stack name is referenced in the parameters. Then an environment variable is created which references the stack output variable. | ||
### The SES email template | ||
The LeanStacks email microservice sends email messages using [AWS SES email templates](https://docs.aws.amazon.com/ses/latest/dg/send-personalized-email-api.html). A SES email template may be created in the console or, better yet, in the resources CloudFormation template for your component. | ||
An example CloudFormation SES email template resource is illustrated below. The `{{variable}}` notations are variables which may be used in the subject or body of the template. Template data will be merged with the template replacing the `{{variable}}` in the template. | ||
|
||
_Example: CloudFormation SES Template_ | ||
|
||
```yaml | ||
Resources: | ||
MyEmailTemplate: | ||
Type: AWS::SES::Template | ||
Properties: | ||
Template: | ||
TemplateName: MyEmailTemplate | ||
SubjectPart: 'How to use SES email templates' | ||
TextPart: 'This is an AWS SES email template. It has a variable: {{variable}}.' | ||
HtmlPart: '<p>This is an AWS SES email template. It has a variable:</p><p>{{variable}}</p>' | ||
Outputs: | ||
MyEmailTemplateName: | ||
Description: My SES Template Name | ||
Value: MyEmailTemplate | ||
``` | ||
|
||
### Sending an email | ||
|
||
To send a message, first import the Email service and related types. | ||
|
||
```ts | ||
import EmailService, { Email } from '@leanstacks/serverless-common'; | ||
``` | ||
|
||
Next, use the `EmailService.send` function to send an asynchronous request to the Email microservice. | ||
|
||
```ts | ||
const queueUrl = config.EMAIL_QUEUE_URL; | ||
const email: Email = { | ||
destinations: [ | ||
{ | ||
to: ['[email protected]', '[email protected]'], | ||
cc: ['[email protected]'], | ||
bcc: ['[email protected]'], | ||
}, | ||
], | ||
templateName: 'MyEmailTemplate', | ||
templateData: { | ||
variable: 'I go in the email template', | ||
}, | ||
}; | ||
await EmailService.send(email, queueUrl); | ||
``` | ||
|
||
That's it! The `EmailService` sends a formatted SQS message to the LeanStacks email microservice. | ||
|
||
> **NOTE:** The LeanStacks email microservice sends messages in near real time. There is no delay, batching, or scheduling. |
This file contains 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,7 @@ | ||
import { Email } from '../services'; | ||
|
||
export const emailFixture: Email = { | ||
destinations: [{ to: ['[email protected]'] }], | ||
templateName: 'template-name', | ||
templateData: { foo: 'bar' }, | ||
}; |
This file contains 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,32 @@ | ||
import EmailService from '../email-service'; | ||
|
||
import SQSService from '../sqs-service'; | ||
import { emailFixture } from '../../__fixtures__/email-service.fixture'; | ||
|
||
describe('EmailService', () => { | ||
const QUEUE_URL = 'queue-url'; | ||
const sendSpy = jest.spyOn(SQSService, 'sendMessage'); | ||
|
||
beforeEach(() => { | ||
sendSpy.mockResolvedValue({ $metadata: {} }); | ||
}); | ||
|
||
it('should be defined', () => { | ||
expect(EmailService).toBeDefined(); | ||
expect(EmailService.send).toBeDefined(); | ||
}); | ||
|
||
it('should send email', async () => { | ||
await EmailService.send(emailFixture, QUEUE_URL); | ||
|
||
expect(sendSpy).toHaveBeenCalledTimes(1); | ||
expect(sendSpy).toHaveBeenCalledWith({ | ||
QueueUrl: QUEUE_URL, | ||
MessageBody: JSON.stringify({ | ||
data: emailFixture.templateData, | ||
destinations: emailFixture.destinations, | ||
template: emailFixture.templateName, | ||
}), | ||
}); | ||
}); | ||
}); |
This file contains 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,60 @@ | ||
import SQSService from './sqs-service'; | ||
|
||
/** | ||
* The addresses to which the email should be sent. | ||
*/ | ||
export type EmailDestination = { | ||
to: string[]; | ||
cc?: string[]; | ||
bcc?: string[]; | ||
}; | ||
|
||
/** | ||
* An object containing data to populate the email template. The object keys | ||
* are strings and the values may be strings, numbers, or booleans. | ||
* | ||
* _Example:_ | ||
* ``` | ||
* { | ||
* name: 'Joe Smith', | ||
* age: 39, | ||
* isEnabled: true | ||
* } | ||
* ``` | ||
*/ | ||
export type EmailTemplateData = Record<string, string | number | boolean>; | ||
|
||
/** | ||
* The `Email` type describes the request to send an email to one or more | ||
* recipients (i.e. destinations). | ||
*/ | ||
export type Email = { | ||
destinations: EmailDestination[]; | ||
templateName: string; | ||
templateData?: EmailTemplateData; | ||
}; | ||
|
||
/** | ||
* Sends an email message asynchronously. Provide the `email` and the AWS SQS | ||
* `queueUrl`. The `queueURL` is the LeanStacks Email microservice SQS Queue. | ||
* @param email - The `Email` object describing the email message. | ||
* @param queueUrl - The AWS SQS queue URL for the Email microservice. | ||
*/ | ||
const send = async (email: Email, queueUrl: string): Promise<void> => { | ||
await SQSService.sendMessage({ | ||
QueueUrl: queueUrl, | ||
MessageBody: JSON.stringify({ | ||
data: email.templateData, | ||
destinations: email.destinations, | ||
template: email.templateName, | ||
}), | ||
}); | ||
}; | ||
|
||
/** | ||
* Use the `EmailService` to send an email message. Messages are sent | ||
* asynchronously. | ||
*/ | ||
const EmailService = { send }; | ||
|
||
export default EmailService; |
This file contains 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