Skip to content

Repository files navigation

Mailbox

Tests codecov Go Report Card PRs Welcome License: MIT

Versatile email infrastructure that operates on AWS.

Clients

Web

See mailbox-browser

Dark mode Light mode
Screenshot Dark Mode Screenshot Light Mode

CLI

go install github.com/harryzcy/mailbox-cli

For details, refer to mailbox-cli

Deploy

Deployment is managed with Terraform.

Prerequisites

Two S3 buckets are created outside Terraform, because one must exist before terraform init can run and the other holds mail that must outlive any stack:

  • A state bucket, for Terraform state. Enable versioning so a bad write can be rolled back.
  • An email bucket, where SES delivers raw messages.

A third bucket, for build artifacts, is created by Terraform, but you have to name it through aws_s3_artifacts_bucket_override: bucket names are global, so default reliably works. Lambda deployment packages are uploaded there to be signed, and its contents are rebuildable from a release.

Credentials

The provider sets only a region, so Terraform uses the standard AWS credential chain: environment variables, a named profile, or IAM Identity Center.

Deploying needs write access to IAM, Lambda, API Gateway, CloudWatch Logs, SQS, Signer, SES, the state and artifact buckets, and — unless aws_dynamodb_table_override is set — DynamoDB. Signing packages needs signer:StartSigningJob and read and write on the artifacts bucket. Creating the artifacts bucket also needs s3:CreateBucket and the s3:Get*/s3:Put* bucket-configuration actions behind versioning, encryption, public access block, ownership controls, policy and lifecycle. One more is easy to miss: iam:PassRole for the Lambda execution role, because the resulting error names CreateFunction instead.

Attach those permissions to a role and assume it, rather than granting them to a user directly:

# ~/.aws/config
[profile mailbox]
role_arn = arn:aws:iam::<account-id>:role/mailbox-deploy
source_profile = default
region = us-west-2
AWS_PROFILE=mailbox make apply

With IAM Identity Center, aws sso login --profile mailbox instead — no stored key at all.

CI does not use any of this. It assumes a short-lived, plan-only role through GitHub OIDC; see oidc.tf.

Configure

The two bucket names are required. Everything else has a working default, and the remaining variables are optional overrides that each turn a feature on. Set them as TF_VAR_ environment variables.

Variable Purpose
aws_s3_bucket_override Required. Names the email bucket. There is no default: bucket names are global, so nothing generated from the project name reliably works.
aws_s3_artifacts_bucket_override Required. Names the artifacts bucket Terraform creates for code signing. Global names again, so again no default.
aws_region Region to deploy into. Defaults to us-west-2.
project_name, environment Name resources. Default to mailbox-v2 and dev.
aws_dynamodb_table_override Use an existing table instead of creating one.
aws_dynamodb_point_in_time_recovery Continuous backups on the managed table. Defaults to true; incurs additional cost.
ses_receipt_rule_set_name, ses_receipt_rule_name Manage an existing SES receipt rule. Both required to enable; otherwise SES is left alone.
github_repository, github_oidc_provider_arn Create a CI role for that repo. Both required to enable.

Deploy

export TF_STATE_BUCKET=<your-state-bucket>
export TF_VAR_aws_s3_bucket_override=<your-email-bucket>
export TF_VAR_aws_s3_artifacts_bucket_override=<your-artifacts-bucket>
make init
make deploy

make plan previews what deploying the latest release would change, and make deploy deploys it. Use make apply to deploy binaries built from your working tree instead.

Configure email receiving

SES applies one active receipt rule set per region, and it may already hold rules unrelated to this project. Terraform therefore manages a single rule inside an existing set rather than the set itself.

Create a rule set and a rule with two actions, in this order:

  1. Deliver to S3, naming your email bucket.
  2. Invoke Lambda, selecting <project>-<env>-email_receive.

Then activate the rule set. To let Terraform manage the rule's Lambda action from then on, set ses_receipt_rule_set_name and ses_receipt_rule_name and import it:

terraform import 'aws_ses_receipt_rule.receive[0]' <rule-set-name>:<rule-name>

Finally, deploy mailbox-browser or use mailbox-cli.

API

See doc/API.md

Architecture

It runs on AWS services, including SES, Lambda, API Gateway, DynamoDB, and SQS.

Architecture

Contributing

Development environment

  • Go >= 1.27

Note that only the most recent minor versions of Go are officially supported.

About

Versatile email infrastructure on AWS serverless

Topics

Resources

Security policy

Stars

254 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages