-
Notifications
You must be signed in to change notification settings - Fork 4k
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
feat(ses): add constructs for email receiving #1971
Merged
Merged
Changes from 4 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
23e6b04
feat(ses): add constructs for email receiving
jogold 3c7613c
Merge branch 'master' into ses
jogold a0c175d
Do not export Imported classes
jogold 926bb92
Fix tests with AWS::URLSuffix
jogold 3a017df
Improve README and JSDoc
jogold 198a3d0
Merge branch 'master' into ses
jogold 72dc416
Use CfnOutput
jogold b0b37b1
Add JSDoc
jogold b7d495d
Add JSDoc
jogold 90886b4
Merge branch 'master' into ses
jogold 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 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 |
---|---|---|
@@ -1,2 +1,123 @@ | ||
## The CDK Construct Library for AWS Simple Email Service | ||
This module is part of the [AWS Cloud Development Kit](https://github.com/awslabs/aws-cdk) project. | ||
|
||
### Email receiving | ||
Create a receipt rule set with rules and actions: | ||
```ts | ||
const bucket = new s3.Bucket(this, 'Bucket'); | ||
|
||
const topic = new sns.Topic(this, 'Topic'); | ||
|
||
const ruleSet = new ses.ReceiptRuleSet(this, 'RuleSet', { | ||
rules: [ | ||
{ | ||
actions: [ | ||
new ses.ReceiptRuleAddHeaderAction({ | ||
name: 'X-Special-Header', | ||
value: 'aws' | ||
}) | ||
new ses.ReceiptRuleS3Action({ | ||
bucket, | ||
objectKeyPrefix: 'emails/', | ||
topic | ||
}) | ||
], | ||
recipients: ['[email protected]'], | ||
}, | ||
{ | ||
actions: [ | ||
new ses.ReceiptRuleSnsAction({ | ||
topic | ||
}) | ||
] | ||
recipients: ['aws.com'], | ||
} | ||
] | ||
}); | ||
``` | ||
|
||
Alternatively, rules can be added to a rule set: | ||
```ts | ||
const ruleSet = new ses.ReceiptRuleSet(this, 'RuleSet'): | ||
|
||
const awsRule = ruleSet.addRule('Aws', { | ||
recipients: ['aws.com'] | ||
}); | ||
``` | ||
|
||
And actions to rules: | ||
```ts | ||
awsRule.addAction( | ||
new ses.ReceiptRuleSnsAction({ | ||
topic | ||
}); | ||
); | ||
``` | ||
When using `addRule`, the new rule is added after the last added rule unless `after` is specified. | ||
|
||
[More actions](test/integ.receipt.ts) | ||
|
||
#### Drop spams | ||
A rule to drop spam can be added by setting `dropSpam` to `true`: | ||
|
||
```ts | ||
new ses.ReceiptRuleSet(this, 'RuleSet', { | ||
dropSpam: true | ||
}); | ||
``` | ||
|
||
This will add a rule at the top of the rule set with a Lambda action that stops processing messages that have at least one spam indicator. See [Lambda Function Examples](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-action-lambda-example-functions.html). | ||
|
||
### Import and export receipt rule set and receipt rules | ||
Receipt rule sets and receipt rules can be exported: | ||
|
||
```ts | ||
const ruleSet = new ReceiptRuleSet(this, 'RuleSet'); | ||
const rule = ruleSet.addRule(this, 'Rule', { | ||
recipients: ['[email protected]'] | ||
}); | ||
|
||
const ruleSetRef = ruleSet.export(); | ||
const ruleRef = rule.export(); | ||
``` | ||
|
||
And imported: | ||
```ts | ||
const importedRuleSet = ses.ReceiptRuleSet.import(this, 'ImportedRuleSet', ruleSetRef); | ||
|
||
const importedRule = ses.ReceiptRule.import(this, 'ImportedRule', ruleRef); | ||
|
||
const otherRule = ses.ReceiptRule.import(this, 'OtherRule', { | ||
name: 'other-rule' | ||
}); | ||
|
||
importedRuleSet.addRule('New', { // This rule as added after the imported rule | ||
after: importedRule, | ||
recipients: ['mydomain.com'] | ||
}); | ||
|
||
importedRuleSet.addRule('Extra', { // Added after the 'New' rule | ||
recipients: ['extra.com'] | ||
}); | ||
``` | ||
|
||
### Receipt filter | ||
Create a receipt filter: | ||
```ts | ||
new ses.ReceiptFilter(this, 'Filter', { | ||
ip: '1.2.3.4/16' // Will be blocked | ||
}) | ||
``` | ||
|
||
Without props, a block all (0.0.0.0/0) filter is created. | ||
|
||
A white list filter is also available: | ||
```ts | ||
new ses.WhiteListReceiptFilter(this, 'WhiteList', { | ||
ips: [ | ||
'10.0.0.0/16', | ||
'1.2.3.4/16', | ||
] | ||
}); | ||
``` | ||
This will first create a block all filter and then create allow filters for the listed ip addresses. |
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 |
---|---|---|
@@ -1,2 +1,7 @@ | ||
export * from './receipt-rule-set'; | ||
export * from './receipt-rule'; | ||
export * from './receipt-rule-action'; | ||
export * from './receipt-filter'; | ||
|
||
// AWS::SES CloudFormation Resources: | ||
export * from './ses.generated'; |
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,82 @@ | ||
import cdk = require('@aws-cdk/cdk'); | ||
import { CfnReceiptFilter } from './ses.generated'; | ||
|
||
export enum ReceiptFilterPolicy { | ||
jogold marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/** | ||
* Allow the ip address or range. | ||
*/ | ||
Allow = 'Allow', | ||
|
||
/** | ||
* Block the ip address or range. | ||
*/ | ||
Block = 'Block' | ||
} | ||
|
||
export interface ReceiptFilterProps { | ||
jogold marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/** | ||
* The name for the receipt filter. | ||
* | ||
* @default a CloudFormation generated name | ||
*/ | ||
name?: string; | ||
|
||
/** | ||
* The ip address or range to filter. | ||
* | ||
* @default 0.0.0.0/0 | ||
*/ | ||
ip?: string; | ||
|
||
/** | ||
* The policy for the filter. | ||
* | ||
* @default Block | ||
*/ | ||
policy?: ReceiptFilterPolicy; | ||
} | ||
|
||
/** | ||
* A receipt filter. When instantiated without props, it creates a | ||
* block all receipt filter. | ||
*/ | ||
export class ReceiptFilter extends cdk.Construct { | ||
constructor(scope: cdk.Construct, id: string, props?: ReceiptFilterProps) { | ||
super(scope, id); | ||
|
||
new CfnReceiptFilter(this, 'Resource', { | ||
filter: { | ||
ipFilter: { | ||
cidr: (props && props.ip) || '0.0.0.0/0', | ||
policy: (props && props.policy) || ReceiptFilterPolicy.Block | ||
}, | ||
name: props ? props.name : undefined | ||
} | ||
}); | ||
} | ||
} | ||
|
||
export interface WhiteListReceiptFilterProps { | ||
jogold marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/** | ||
* A list of ip addresses or ranges to white list. | ||
*/ | ||
ips: string[]; | ||
} | ||
|
||
/** | ||
* A white list receipt filter. | ||
*/ | ||
export class WhiteListReceiptFilter extends cdk.Construct { | ||
constructor(scope: cdk.Construct, id: string, props: WhiteListReceiptFilterProps) { | ||
super(scope, id); | ||
|
||
new ReceiptFilter(this, 'BlockAll'); | ||
|
||
props.ips.forEach(ip => { | ||
new ReceiptFilter(this, `Allow${ip.replace(/[^\d]/g, '')}`, { | ||
ip, | ||
policy: ReceiptFilterPolicy.Allow | ||
}); | ||
}); | ||
} | ||
} |
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.
Could you please move this into a file named:
And add the requirement imports and
Stack
declaration around it?You can mark the piece of code that is relevant for the example with:
And at this location in the README add:
This will make sure that the example actually compiles, and if we make breaking API changes, the compiler failure will force us to update the example code.