{"id":28440978,"url":"https://github.com/seeebiii/ses-email-forwarding","last_synced_at":"2025-07-05T02:32:12.897Z","repository":{"id":37276894,"uuid":"329582739","full_name":"seeebiii/ses-email-forwarding","owner":"seeebiii","description":"AWS CDK constructs to receive emails with SES and forward them to any other email address.","archived":false,"fork":false,"pushed_at":"2024-09-02T01:05:37.000Z","size":908,"stargazers_count":26,"open_issues_count":2,"forks_count":9,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-06-06T04:08:40.803Z","etag":null,"topics":["aws","aws-cdk","aws-cdk-constructs","aws-lambda","aws-ses","email","email-forwarding"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seeebiii.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2021-01-14T10:35:54.000Z","updated_at":"2025-01-10T10:04:52.000Z","dependencies_parsed_at":"2024-04-13T01:46:54.098Z","dependency_job_id":null,"html_url":"https://github.com/seeebiii/ses-email-forwarding","commit_stats":{"total_commits":117,"total_committers":4,"mean_commits":29.25,"dds":0.5213675213675213,"last_synced_commit":"0971f77e8e14f7887d0553db52dbeb4a9dc15ce4"},"previous_names":[],"tags_count":43,"template":false,"template_full_name":null,"purl":"pkg:github/seeebiii/ses-email-forwarding","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seeebiii%2Fses-email-forwarding","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seeebiii%2Fses-email-forwarding/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seeebiii%2Fses-email-forwarding/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seeebiii%2Fses-email-forwarding/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seeebiii","download_url":"https://codeload.github.com/seeebiii/ses-email-forwarding/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seeebiii%2Fses-email-forwarding/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263671746,"owners_count":23494027,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","aws-cdk","aws-cdk-constructs","aws-lambda","aws-ses","email","email-forwarding"],"created_at":"2025-06-06T04:08:40.693Z","updated_at":"2025-07-05T02:32:12.891Z","avatar_url":"https://github.com/seeebiii.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @seeebiii/ses-email-forwarding\n\nThis [AWS CDK](https://aws.amazon.com/cdk/) construct allows you to setup email forwarding mappings in [AWS SES](https://aws.amazon.com/ses/) to receive emails from your domain and forward them to another email address.\nAll of this is possible without hosting your own email server, you just need a domain.\n\nFor example, if you own a domain `example.org` and want to receive emails for `hello@example.org` and `privacy@example.org`, you can forward emails to `whatever@provider.com`.\nThis is achieved by using a Lambda function that forwards the emails using [aws-lambda-ses-forwarder](https://github.com/arithmetric/aws-lambda-ses-forwarder).\n\nThis construct is creating quite a few resources under the hood and can also automatically verify your domain and email addresses in SES.\nConsider reading the [Architecture](#architecture) section below if you want to know more about the details.\n\n## Examples\n\nForward all emails received under `hello@example.org` to `whatever+hello@provider.com`:\n\n```javascript\nnew EmailForwardingRuleSet(this, 'EmailForwardingRuleSet', {\n  // make the underlying rule set the active one\n  enableRuleSet: true,\n  // define how emails are being forwarded\n  emailForwardingProps: [{\n    // your domain name you want to use for receiving and sending emails\n    domainName: 'example.org',\n    // a prefix that is used for the From email address to forward your mails\n    fromPrefix: 'noreply',\n    // a list of mappings between a prefix and target email address\n    emailMappings: [{\n      // the prefix matching the receiver address as \u003cprefix\u003e@\u003cdomainName\u003e\n      receivePrefix: 'hello',\n      // the target email address(es) that you want to forward emails to\n      targetEmails: ['whatever+hello@provider.com']\n    }]\n  }]\n});\n```\n\nForward all emails for a domain `example.org` to `whatever+hello@provider.com`:\n\n```javascript\nnew EmailForwardingRuleSet(this, 'EmailForwardingRuleSet', {\n  // make the underlying rule set the active one\n  enableRuleSet: true,\n  // define how emails are being forwarded\n  emailForwardingProps: [{\n    // your domain name you want to use for receiving and sending emails\n    domainName: 'example.org',\n    // a prefix that is used for the From email address to forward your mails\n    fromPrefix: 'noreply',\n    // a list of mappings between a prefix and target email address\n    emailMappings: [{\n      // matches all email addresses for 'example.org'\n      receiveEmail: '@example.org',\n      // the target email address(es) that you want to forward emails to\n      targetEmails: ['whatever+hello@provider.com']\n    }]\n  }]\n});\n```\n\nForward all emails to `hello@example.org` to `whatever+hello@provider.com` and verify the domain `example.org` in SES:\n\n```javascript\nnew EmailForwardingRuleSet(this, 'EmailForwardingRuleSet', {\n  emailForwardingProps: [{\n    domainName: 'example.org',\n    // let the construct automatically verify your domain\n    verifyDomain: true,\n    fromPrefix: 'noreply',\n    emailMappings: [{\n      receivePrefix: 'hello',\n      targetEmails: ['whatever+hello@provider.com']\n    }]\n  }]\n});\n```\n\nIf you don't want to verify your domain in SES or you are in the SES sandbox, you can still send emails to verified email addresses.\nUse the property `verifyTargetEmailAddresses` in this case and set it to `true`.\n\nFor a full \u0026 up-to-date reference of the available options, please look at the source code of  [`EmailForwardingRuleSet`](lib/email-forwarding-rule-set.ts) and [`EmailForwardingRule`](lib/email-forwarding-rule.ts).\n\n#### Note\n\nSince the verification of domains requires to lookup the Route53 domains in your account, you need to define your AWS account and region.\nYou can do it like this in your CDK stack:\n\n```typescript\nconst app = new cdk.App();\n\nclass EmailForwardingSetupStack extends cdk.Stack {\n  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {\n    super(scope, id, props);\n\n    new EmailForwardingRuleSet(this, 'EmailForwardingRuleSet', {\n      // define your config here\n    });\n  }\n}\n\nnew EmailForwardingSetupStack(app, 'EmailForwardingSetupStack', {\n  env: {\n    account: '\u003caccount-id\u003e',\n    region: '\u003cregion\u003e'\n  }\n});\n```\n\n## Use Cases\n\n- Build a landing page on AWS and offer an email address to contact you.\n- Use various aliases to register for different services and forward all mails to the same target email address.\n\nThere are probably more - happy to hear them :)\n\n## Install\n\n### npm\n\n```shell\nnpm i -D @seeebiii/ses-email-forwarding\n```\n\nTake a look at [package.json](./package.json) to make sure you're installing the correct version compatible with your current AWS CDK version.\nSee more details on npmjs.com: https://www.npmjs.com/package/@seeebiii/ses-email-forwarding\n\n### Maven\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ede.sebastianhesse.cdk-constructs\u003c/groupId\u003e\n  \u003cartifactId\u003eses-email-forwarding\u003c/artifactId\u003e\n  \u003cversion\u003e4.0.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nSee more details on mvnrepository.com: https://mvnrepository.com/artifact/de.sebastianhesse.cdk-constructs/ses-email-forwarding/\n\n#### Example Code\n\n```java\npackage com.example;\n\nimport de.sebastianhesse.cdk.ses.email.forwarding.EmailForwardingProps;\nimport de.sebastianhesse.cdk.ses.email.forwarding.EmailForwardingRuleSet;\nimport de.sebastianhesse.cdk.ses.email.forwarding.EmailMapping;\nimport java.util.Arrays;\nimport software.amazon.awscdk.core.App;\n\nimport software.amazon.awscdk.core.Construct;\nimport software.amazon.awscdk.core.Environment;\nimport software.amazon.awscdk.core.Stack;\nimport software.amazon.awscdk.core.StackProps;\n\npublic class SesEmailForwardingJavaTestApp {\n    public static void main(final String[] args) {\n        App app = new App();\n\n        new SesEmailForwardingJavaTestStack(app, \"CdkEmailForwardingJavaTestStack\", StackProps.builder()\n                .env(Environment.builder()\n                        .account(\"123456789\") // TODO: replace with your account id\n                        .region(\"us-east-1\") // TODO: replace with your region\n                        .build()\n                )\n                .build());\n\n        app.synth();\n    }\n\n    static class SesEmailForwardingJavaTestStack extends Stack {\n        public SesEmailForwardingJavaTestStack(final Construct scope, final String id) {\n            this(scope, id, null);\n        }\n\n        public SesEmailForwardingJavaTestStack(final Construct scope, final String id, final StackProps props) {\n            super(scope, id, props);\n\n            EmailForwardingProps exampleProperties = EmailForwardingProps.builder()\n                    .domainName(\"example.org\")\n                    // true if you own the domain in Route53, false if you need to manually verify it\n                    .verifyDomain(true)\n                    .fromPrefix(\"noreply\")\n                    .emailMappings(Arrays.asList(\n                            EmailMapping.builder()\n                                    .receiveEmail(\"hello@example.org\")\n                                    .targetEmails(Arrays.asList(\"email+hello@provider.com\"))\n                                    .build(),\n                            EmailMapping.builder()\n                                    .receiveEmail(\"privacy@example.org\")\n                                    .targetEmails(Arrays.asList(\"email+privacy@provider.com\"))\n                                    .build()\n                            )\n                    )\n                    .build();\n\n            EmailForwardingRuleSet.Builder.create(this, \"example-rule-set\")\n                    .ruleSetName(\"example-rule-set\")\n                    .emailForwardingProps(Arrays.asList(exampleProperties))\n                    .build();\n        }\n    }\n}\n```\n\n### Python\n\n```shell\npip install ses-email-forwarding\n```\n\nSee more details on PyPi: https://pypi.org/project/ses-email-forwarding/\n\n### .NET / C#\n\nAn artifact is pushed up to NuGet.org: https://www.nuget.org/packages/Ses.Email.Forwarding/\n\n#### Project Scaffolding \u0026 Installation\n\n```bash\n# Create a new directory\nmkdir ExampleApplication \u0026\u0026 cd ExampleApplication\n\n# Scaffold a C# CDK project\ncdk init --language csharp\n\n# Add dependencies\ncd src/ExampleApplication\ndotnet add package Ses.Email.Forwarding\ndotnet add package Amazon.CDK.AWS.SNS.Subscriptions\n\n# Remove example stack and global suppressions (silenced by way of using discards)\nrm ExampleApplicationStack.cs GlobalSuppressions.cs\n```\n\n#### Example Usage\n\n```csharp\nusing Amazon.CDK;\nusing Amazon.CDK.AWS.SNS;\nusing Amazon.CDK.AWS.SNS.Subscriptions;\nusing SebastianHesse.CdkConstructs;\nusing Construct = Constructs.Construct;\n\nnamespace ExampleApplication\n{\n    public sealed class Program\n    {\n        public static void Main()\n        {\n            var app = new App();\n            \n            _ = new MailboxStack(app, nameof(MailboxStack), new StackProps\n            {\n                Env = new Environment\n                {\n                    // Replace with desired account\n                    Account = \"000000000000\",\n\n                    // Replace with desired region\n                    Region = \"us-east-1\"\n                }\n            });\n\n            app.Synth();\n        }\n    }\n    \n    public sealed class MailboxStack : Stack\n    {\n        public MailboxStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)\n        {\n            var notificationTopic = new Topic(this, nameof(EmailForwardingProps.NotificationTopic));\n            \n            // 'Bounce' and 'Complaint' notification types, in association with the domain being verified, will be sent\n            // to this email address\n            notificationTopic.AddSubscription(new EmailSubscription(\"admin@provider.com\"));\n            \n            _ = new EmailForwardingRuleSet(this, nameof(EmailForwardingRuleSet), new EmailForwardingRuleSetProps\n            {\n                EmailForwardingProps = new IEmailForwardingProps[]\n                {\n                    new EmailForwardingProps\n                    {\n                        // If your domain name has already been verified as a domain identity in SES, this does not\n                        // need to be toggled on\n                        VerifyDomain = true,\n                        \n                        // This is the prefix that will be used in the email address used to forward emails\n                        FromPrefix = \"noreply\",\n                        \n                        // This domain name will be used to send and receive emails\n                        DomainName = \"example.org\",\n                        \n                        // A list of mappings between a prefix and target email addresses\n                        EmailMappings = new IEmailMapping[]\n                        {\n                            new EmailMapping\n                            {\n                                // Emails received by hello@example.org will be forwarded\n                                ReceivePrefix = \"hello\",\n                                \n                                // Emails will be forwarded to admin+hello@provider.com\n                                TargetEmails = new []\n                                {\n                                    \"admin+hello@provider.com\"\n                                }\n                            }\n                        },\n                        \n                        // This notification topic be published to when events in association with 'Bounce' and\n                        // 'Complaint' notification types occur\n                        NotificationTopic = notificationTopic\n                    }\n                }\n            });\n        }\n    }\n}\n```\n\n## Usage\n\nThis package provides two constructs: [`EmailForwardingRuleSet`](lib/email-forwarding-rule-set.ts) and [`EmailForwardingRule`](lib/email-forwarding-rule.ts).\nThe `EmailForwardingRuleSet` is a wrapper around `ReceiptRuleSet` but adds a bit more magic to e.g. verify a domain or target email address.\nSimilarly, `EmailForwardingRule` is a wrapper around `ReceiptRule` but adds two SES rule actions to forward the email addresses appropriately.\n\nThis means if you want the full flexibility, you can use the `EmailForwardingRule` construct in your stack.\n\n### Sending E-Mails over SMTP\n\nYou can also send emails over SES using this construct because it provides the basics for sending emails: a verified SES domain or email address identity.\nYou need to do the following if you're using the `EmailForwardingRuleSetConstruct`:\n\n1. Set the `verifyDomain` or `verifyTargetEmailAddresses` to `true`.\n2. [Create SMTP credentials in AWS SES](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-credentials.html?icmpid=docs_ses_console) and save them somewhere.\n3. Setup your email program or application to use the SMTP settings.\n\n## Architecture\n\nThe `EmailForwardingRuleSet` creates a `EmailForwardingRule` for each forward mapping.\nEach rule contains an `S3Action` to store the incoming emails and a Lambda Function to forward the emails to the target email addresses.\nThe Lambda function is just a thin wrapper around the [aws-lambda-ses-forwarder](https://github.com/arithmetric/aws-lambda-ses-forwarder) library.\nSince this library expects a JSON config with the email mappings, the `EmailForwardingRule` will create an SSM parameter to store the config.\n(Note: this is not ideal because an SSM parameter is limited in the size and hence, this might be changed later)\nThe Lambda function receives a reference to this parameter as an environment variable (and a bit more) and forwards everything to the library.\n\nIn order to verify a domain or email address, the `EmailForwardingRuleSet` construct is using the package [@seeebiii/ses-verify-identities](https://www.npmjs.com/package/@seeebiii/ses-verify-identities).\nIt provides constructs to verify the SES identities.\nFor domains, it creates appropriate Route53 records like MX, TXT and Cname (for DKIM).\nFor email addresses, it calls the AWS API to initiate email address verification.\n\n## TODO\n\n- Encrypt email files on S3 bucket by either using S3 bucket encryption (server side) or enable client encryption using SES actions\n\n## Contributing\n\nI'm happy to receive any contributions!\nJust open an issue or pull request :)\n\nThese commands should help you while developing:\n\n * `npx projen`          init [projen](https://github.com/projen/projen) and synthesize changes in [.projenrc.js](.projenrc.js) to the project\n * `yarn build`          compile typescript to js\n * `yarn watch`          watch for changes and compile\n * `yarn test`           perform the jest unit tests\n * `yarn eslint`         validate code against best practices\n\n## Thanks\n\nThanks a lot to [arithmetric](https://github.com/arithmetric) for providing the NPM package [aws-lambda-ses-forwarder](https://github.com/arithmetric/aws-lambda-ses-forwarder).\nThis CDK construct is using it in the Lambda function to forward the emails.\n\n## Author\n\n[Sebastian Hesse](https://www.sebastianhesse.de) - Freelancer for serverless cloud projects on AWS.\n\n## License\n\nMIT License\n\nCopyright (c) 2022 [Sebastian Hesse](https://www.sebastianhesse.de)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseeebiii%2Fses-email-forwarding","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseeebiii%2Fses-email-forwarding","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseeebiii%2Fses-email-forwarding/lists"}