Build an independent subscriber base. SimpleSubscribe.org.
- About the Project
- What this Does
- How this Works
- Requirements and Installation
- Security Considerations
- Dual License
- Contributing
Simple Subscribe grew out of a desire to allow individuals and organizations to build their own independent subscriber base. It helps you collect emails with a subscription box you can add to any page.
If you're interested in managing your own mailing list or newsletter, you can use Simple Subscribe to collect email addresses. It uses an AWS Lambda to handle subscribe and unsubscribe requests via API, and stores email addresses in a DynamoDB table.
Simple Subscribe handles subscription requests, email confirmations (double opt-in), and unsubscription requests for you. You're free to use your own email solution to mail your recipients.
The daughter project RSS Mailer offers one option for mailing your list by turning RSS feed items into email messages.
Simple Subscribe will let your visitors:
- Enter their email and hit a Subscribe button to sign up.
- Receive a confirmation email in their inbox with a link to finish signing up (double opt-in).
- Send requests to unsubscribe from your list and automatically have their email removed.
Simple Subscribe handles one part of your subscription newsletter flow: allowing people to subscribe! Here are a few things this project does not do:
- Send newsletters to your list.
- Click tracking or other metrics.
- Dance the samba. π
If you'd like to help extend the functionality of this project, please read Contributing.
Simple Subscribe receives a GET request to your SUBSCRIBE_PATH
with a query string containing the intended subscriber's email. It then generates an id
value and adds both email
and id
to your DynamoDB table. The table item now looks like:
confirm | id | timestamp | |
---|---|---|---|
subscriber@example.com |
false | uuid-xxxxx |
2020-11-01 00:27:39 |
After subscribing, the intended subscriber receives an email from SES containing a link. This link takes the format:
<BASE_URL><VERIFY_PATH>/?email=subscriber@example.com&id=uuid-xxxxx
Visiting the link sends a request to your VERIFY_PATH
with the email
and id
. Simple Subscribe ensures these values match the database values, then sets confirm
to true
and updates the timestamp. The table item now looks like:
confirm | id | timestamp | |
---|---|---|---|
subscriber@example.com |
true | uuid-xxxxx |
2020-11-01 00:37:39 |
When querying for people to send your newsletter, ensure you only return emails where confirm
is true
.
Simple Subscribe uses email
and id
as arguments to the function that deletes an item from your DynamoDB table. To allow people to remove themselves from your list, provide a URL in emails that includes their email
and id
as a query string in the UNSUBSCRIBE_PATH
. It looks something like:
<BASE_URL><UNSUBSCRIBE_PATH>/?email=subscriber@example.com&id=uuid-xxxxx
If the provided email
and id
match a database item, that item will be deleted.
While Simple Subscribe is in limited beta, you can create the following required resources via the AWS web console. Future releases will feature infrastructure as code.
The following AWS resources are needed. For set up help, see the provided links.
- Create a DynamoDB table with key
email
, a string. Key names are case-sensitive. - Create a Lambda Function with
main.go
uploaded as the code, and appropriate environment variables (see below). Ensure it has permissions to access DynamoDB and SES. - Set up an API Gateway trigger for your Lambda. Ensure
payloadFormatVersion
for your integration is2.0
. - Set up AWS Simple Email Service for sending a subscription confirmation email. If it's your first time sending with SES, you may need to add and verify your email address or domain.
- Optionally, if you're interested in giving your API a custom domain, see the AWS docs on setting up custom domain names for APIs.
The scripts/
directory has some helpers in it. To use these:
- Install AWS CLI and set up credentials on your machine.
- Create a
.env
in this repository's root with the appropriate values as described below.
The API will look for the following environment variables:
DB_TABLE_NAME
: your DynamoDB tableBASE_URL
: the address of your site, beginning withhttps://
and ending with/
API_URL
: the endpoint of your API, ending with/
As well as these API endpoints:
SUBSCRIBE_PATH
: the name of your subscription endpoint, e.g.signup
UNSUBSCRIBE_PATH
: the name of your unsubscribe endpoint, e.g.unsubscribe
VERIFY_PATH
: the name of your email verification endpoint, e.g.verify
SENDER_EMAIL
: the email your confirmation message will be coming fromSENDER_NAME
: the name you'd like the confirmation message to come from
As well as these website pages:
CONFIRM_SUBSCRIBE_PAGE
: the path of the page your subscriber sees after submitting their email, e.g.confirm
SUCCESS_PAGE
: the path of the page your subscriber sees when they complete sign up, e.g.success
ERROR_PAGE
: the path of your error page, e.g.error
CONFIRM_UNSUBSCRIBE_PAGE
: the path of the page shown after someone successfully unsubscribes, e.g.unsubscribed
Pages that your subscriber is sent to after an action are constructed with the base URL in the format <BASE_URL><SUCCESS_PAGE>
.
You can input Lambda environment variables in the AWS console, or use the AWS CLI.
If you're using the AWS CLI, you can pass the environment variables for Lambda in the following shorthand format:
Variables={KeyName1=string,KeyName2=string}
The script update-lambda.sh
is provided for convenience. It will upload main.go
to your Lambda function and replace Lambda environment variables for you by sourcing .env
. Ensure that LAMBDA_ENV
is present to hold them.
Here's an example of a suitable .env
that you can copy and modify:
NAME="simple-subscribe"
DB_TABLE_NAME="SimpleSubscribe"
LAMBDA_ENV="Variables={\
DB_TABLE_NAME=SimpleSubscribe,\
BASE_URL=https://example.com/,\
API_URL=https://api.example.com/,\
ERROR_PAGE=error,\
SUCCESS_PAGE=success,\
CONFIRM_SUBSCRIBE_PAGE=confirm,\
CONFIRM_UNSUBSCRIBE_PAGE=unsubscribed,\
SUBSCRIBE_PATH=signup,\
UNSUBSCRIBE_PATH=unsubscribe,\
VERIFY_PATH=verify,\
SENDER_EMAIL=no-reply@example.com,\
SENDER_NAME='Ford Prefect'}"
While none of these are private or secret, it's good practice to have Git ignore environment variables. You can do this with echo .env >> .gitignore
if it's not already there.
Your visitors will need a form to put their email into. Here's an example HTML snippet:
<!-- Simple Subscribe subscription form begins -->
<div class="form-container">
<p>Enter your email below to subscribe.</p>
<div class="form-row" id="subscribe">
<!-- Change the below 'action' to your API subscribe endpoint -->
<form action="/your/subscribe/path/" method="get">
<label hidden for="email">Enter your email to subscribe</label>
<input type="email" name="email" id="email" placeholder="Enter your email" required>
<button type="submit" class="primary" value="Subscribe">Subscribe</button>
</form>
</div>
</div>
<!-- Subscription form ends -->
Standard considerations apply:
- Principle of least privilege: ensure your people and functions have only the minimum necessary permissions for accessing each of your AWS resources.
- Encryption: ensure your website is using HTTPS in general, and in particular for requests sent to your API.
- Validation: ensure your subscription form only processes input in the form of valid email addresses. (Most browsers will help you with this if you use
<input type="email" ...>
as in the example above.)
Here are some additional security features you may consider:
The id
in Simple Subscribe is a UUID that acts as a token to permit verifying or unsubscribing emails. You may wish to expire or rotate these tokens after a certain time frame. You can do this with a periodic clean up (below) or with an AWS Lambda that provides more nuanced timing. Ensure that expiring your tokens does not prevent a subscriber from unsubscribing.
It would be a good idea to periodically clean up your DynamoDB table to avoid retaining email addresses where confirm
is false
past a certain time frame.
If you are particularly concerned about data integrity, you may want to explore On-Demand Backup or Point-in-Time Recovery for DynamoDB.
Simple Subscribe is available under the Mozilla Public License 2.0 (MPL-2.0) for non-monetized applications, such as building and sending your own free newsletter.
For commercial organizations or monetized applications, a one-time commercial license fee of $49 helps to support maintenance and further development. Commercial or monetized usage is subject to the End-User License Agreement. You may purchase a license at SimpleSubscribe.org.
Simple Subscribe would be happy to have your contribution! Add helper scripts, improve the code, or even just fix a typo you found.
Here are a couple ways you can help out. Thank you for being a part of this open source project! π
Please open an issue to tell me about bugs, or anything that might need fixing or updating.
If you would like to change or fix something yourself, a pull request (PR) is most welcome! Please open an issue before you start working. That way, you can let other people know that you're taking care of it and no one ends up doing extra work.
Please fork the repository, then check out a local branch that includes the issue number, such as fix-<issue number>
. For example, git checkout -b fix-42
.
Before you submit your PR, make sure your fork is synced with master
, then create a PR. You may want to allow edits from maintainers so that I can help with small changes like fixing typos.