Categorygithub.com/aaronland/go-mailinglist

# README

go-mailinglist

Minimalist and opinionated scaffolding for running a mailing list.

Documentation

Documentation is incomplete at this time.

Motivation (and caveats)

I needed "the simplest and dumbest thing" to manage delivering email messages to a list of subscribers which I could run locally and using "scale-to-zero" cloud services. This is the second version of that thing.

It does very little and all of it from the command line (or equivalent). For example it does not provide a web interface for people to subscribe or unsubscribe to the mailing list. Most of the code to run that web application has been written but it still needs more polish and has not been the priority yet.

Databases

This package defines a number of Go language interfaces for managing mailing list related database tables (subscribers, deliveries, event logs). Currently this one implementation of those interfaces that uses the gocloud.dev/docstore abstraction layer for storing and retrieving data from a document store.

These databases are currently designed only support a single mailing list.

So far this package has been tested with and enables support for DynamoDB by default.

Sending email

This package uses the aaronland/gomail-sender package for delivering email messages using a variety of "providers".

So far this package has been tested with and enables support for [Amazon Simple Email Service (SES)[https://github.com/aaronland/gomail-sender-ses] by default.

Attachments

Message attachments are loaded using the gocloud.dev/blob abstraction layer for reading files from a variety of local or remote document storage systems.

So far this package has been tested with and enables support for loading attachments from the local filesystem and the Amazon Simple Storage Service (S3).

Example

The following example assumes a local instance of DynamoDB running from a Docker container and the command line tools described below. For example:

$> docker run --rm -it -p 8000:8000 amazon/dynamodb-local
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
Initializing DynamoDB Local with the following configuration:
Port:	8000
InMemory:	true
DbPath:	null
SharedDb:	false
shouldDelayTransientStatuses:	false
CorsParams:	null

The first step is to create the database tables necessary for the mailing list. Use the local-tables Makefile target to do this:

$> make local-tables
go run -mod vendor -ldflags="-s -w" cmd/create-dynamodb-tables/main.go \
		-refresh \
		-client-uri 'aws://?region=localhost&credentials=anon:&local=true'

Next, add a subscriber to the mailing list. Use the local-add Makefile target to do this:

$> make local-add ADDRESS=bob@localhost
go run -mod vendor -ldflags="-s -w" cmd/add-subscriptions/main.go \
		-subscriptions-database-uri 'awsdynamodb://subscriptions?region=localhost&credentials=anon:&local=true&partition_key=Address&allow_scans=true' \
		-address bob@localhost \
		-confirmed
{"address":"bob@localhost","created":1732470161,"confirmed":1732470161,"lastmodified":1732470161,"status":1}
2024/11/24 09:42:41 INFO Subscription added address=bob@localhost

You can confirm the subscriber has been added by using the local-list Makefile target:

$> make local-list
go run -mod vendor -ldflags="-s -w" cmd/list-subscriptions/main.go \
		-subscriptions-database-uri 'awsdynamodb://subscriptions?region=localhost&credentials=anon:&local=true&partition_key=Address&allow_scans=true'
{"address":"bob@localhost","created":1732470161,"confirmed":1732470161,"lastmodified":1732470161,"status":1}

Finally, deliver a message (with an attachment) to all the subscribers using the local-deliver Makefile target:

$> make local-deliver
go run -mod vendor -ldflags="-s -w" cmd/deliver-message/main.go \
		-subscriptions-database-uri 'awsdynamodb://subscriptions?region=localhost&credentials=anon:&local=true&partition_key=Address&allow_scans=true' \
		-deliveries-database-uri 'awsdynamodb://deliveries?region=localhost&credentials=anon:&local=true&partition_key=Address&allow_scans=true' \
		-eventlogs-database-uri 'awsdynamodb://eventlogs?region=localhost&credentials=anon:&local=true&partition_key=Address&allow_scans=true' \
		-sender-uri stdout:// \
		-from do-not-reply@localhost \
		-subject  \
		-body  \
		-attachment /usr/local/go-mailinglist/fixtures/hellokitty.jpg
Mime-Version: 1.0
Date: Sun, 24 Nov 2024 09:44:11 -0800
X-MailingList-Id: 057c4bf7-f8b1-41a4-be10-fbfd9ca85088
From: <do-not-reply@localhost>
To: <bob@localhost>
Subject: -body
Content-Type: multipart/related;
 boundary=5742b7f14e3b26c910ce1b93411111df97a01bd92f5a3708d956d1f9c6e7

--5742b7f14e3b26c910ce1b93411111df97a01bd92f5a3708d956d1f9c6e7
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8


--5742b7f14e3b26c910ce1b93411111df97a01bd92f5a3708d956d1f9c6e7
Content-Disposition: inline; filename="hellokitty.jpg"
Content-ID: <hellokitty.jpg>
Content-Transfer-Encoding: base64
Content-Type: image/jpeg; name="hellokitty.jpg"

/9j/4AAQSkZJRgABAQEAkACQAAD/2wBDAAcFBQYFBAcGBgYIBwcICxILCwoKCxYPEA0SGhYbGhkW
GRgcICgiHB4mHhgZIzAkJiorLS4tGyIyNTEsNSgsLSz/2wBDAQcICAsJCxULCxUsHRkdLCwsLCws
... and so on

Tools

$> make cli
go build -mod vendor -ldflags="-s -w"  -o bin/list-subscriptions cmd/list-subscriptions/main.go
go build -mod vendor -ldflags="-s -w"  -o bin/add-subscriptions cmd/add-subscriptions/main.go
go build -mod vendor -ldflags="-s -w"  -o bin/remove-subscriptions cmd/remove-subscriptions/main.go
go build -mod vendor -ldflags="-s -w"  -o bin/set-subscription-status cmd/set-subscription-status/main.go
go build -mod vendor -ldflags="-s -w"  -o bin/create-dynamodb-tables cmd/create-dynamodb-tables/main.go
go build -mod vendor -ldflags="-s -w"  -o bin/deliver-mail cmd/deliver-message/main.go

create-dynamodb-tables

Instantiate a new set of DynamoDB tables for a mailing list.

$> ./bin/create-dynamodb-tables -h
Usage of ./bin/create-dynamodb-tables:
  -client-uri string
    	A registered aaronland/go-aws-dynamodb URI. (default "aws://?region=localhost&credentials=anon:&local=true")
  -prefix string
    	Optional string to prepend to all table names.
  -refresh
    	Refresh (delete and recreate) tables that have already been created.

add-subscriptions

Add a subscriber to the mailing list

$> ./bin/add-subscriptions -h
  -address value
    	One or more addresses to add as subscriptions
  -confirmed
    	A boolean flag indicating whether the subscriber is confirmed.
  -subscriptions-database-uri string
    	A registered aaronland/go-mailinglist/v2/database.SubscriptionsDatabase URI.
  -verbose
    	Enable verbose (debug) logging.

remove-subscriptions

Remove a subscriber from the mailing list.

$> ./bin/remove-subscriptions -h
  -address value
    	One or more addresses whose subscriptions should be removed.
  -subscriptions-database-uri string
    	A registered aaronland/go-mailinglist/v2/database.SubscriptionsDatabase URI.
  -verbose
    	Enable verbose (debug) logging.

set-subscription-status

Assign the subscription status for one or more subscribers.

$> ./bin/set-subscription-status -h
  -address value
    	One or more addresses whose subscriptions should be removed.
  -status string
    	The status to assign to each address.
  -subscriptions-database-uri string
    	A registered aaronland/go-mailinglist/v2/database.SubscriptionsDatabase URI.
  -verbose
    	Enable verbose (debug) logging.

list-subscriptions

List all of the subscribers for a mailing list.

$> ./bin/list-subscriptions -h
  -subscriptions-database-uri string
    	A registered aaronland/go-mailinglist/v2/database.SubscriptionsDatabase URI.
  -verbose
    	Enable verbose (debug) logging.

deliver-message

Deliver a message to one or more addresses.

$> ./bin/deliver-mail -h
  -attachment value
    	Zero or more URIs referencing files to attach to the message. URIs are dereferenced using the aaronland/gocloud-blob/bucket.ParseURI method.
  -body string
    	The body of the message being delivered. If "-" then body will be read from STDIN.
  -content-type string
    	The content-type of the message body. (default "text/plain")
  -deliveries-database-uri string
    	A registered aaronland/go-mailinglist/v2/database.DeliveriesDatabase URI.
  -eventlogs-database-uri string
    	A registered aaronland/go-mailinglist/v2/database.EventLogsDatabase URI.
  -from string
    	The address delivering the message.
  -message-id string
    	Optional custom message ID to assign to the message. If empty a unique key will be generated on delivery.
  -sender-uri string
    	A registered aaronland/go-mail.Sender URI.
  -subject string
    	The subject of the message being delivered.
  -subscriptions-database-uri string
    	A registered aaronland/go-mailinglist/v2/database.SubscriptionsDatabase URI.
  -to value
    	One or more addresses to deliver the message to. If empty then the message will be delivered to all subscribers whose status is "enabled".
  -verbose
    	Enable verbose (debug) logging.

AWS

DynamoDB

The following URI schemes are available for instantiating DynamoDB database connections:

  • dynamodb:// – the default scheme supported by the gocloud.dev/docstore package.
  • awsdynamodb:// – and alternate scheme that supports defining AWS credentials using labeled strings, described below.

S3

The following URI schemes are available for instantiating S3 data storage instances:

  • s3:// – the default scheme supported by the gocloud.dev/blob package.
  • s3blob:// – and alternate scheme that supports defining AWS credentials using labeled strings, described below.

Credentials

Credentials strings (as ?credentials={CREDENTIALS}) are expected to be a valid aaronland/go-aws-auth credentials "label":

LabelDescription
anon:Empty or anonymous credentials.
env:Read credentials from AWS defined environment variables.
iam:Assume AWS IAM credentials are in effect.
sts:{ARN}Assume the role defined by {ARN} using STS credentials.
{AWS_PROFILE_NAME}This this profile from the default AWS credentials location.
{AWS_CREDENTIALS_PATH}:{AWS_PROFILE_NAME}This this profile from a user-defined AWS credentials location.

For example:

aws:///us-east-1?credentials=iam:

See also

# Packages

No description provided by the author