{"id":16347882,"url":"https://github.com/victoriadrake/simple-subscribe","last_synced_at":"2025-03-21T00:30:25.930Z","repository":{"id":57608709,"uuid":"309204228","full_name":"victoriadrake/simple-subscribe","owner":"victoriadrake","description":"Collect emails with a subscription box you can add to any page and build your own independent subscriber base.","archived":false,"fork":false,"pushed_at":"2020-11-28T20:21:38.000Z","size":589,"stargazers_count":85,"open_issues_count":0,"forks_count":8,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-17T19:01:43.007Z","etag":null,"topics":["aws-lambda","dynamodb","email-marketing","newsletter-api","newsletter-subscriptions","serverless","subscription","subscription-manager"],"latest_commit_sha":null,"homepage":"https://simplesubscribe.org/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/victoriadrake.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-EULA","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-11-01T22:51:10.000Z","updated_at":"2025-02-03T15:30:33.000Z","dependencies_parsed_at":"2022-08-30T09:41:20.690Z","dependency_job_id":null,"html_url":"https://github.com/victoriadrake/simple-subscribe","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/victoriadrake%2Fsimple-subscribe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/victoriadrake%2Fsimple-subscribe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/victoriadrake%2Fsimple-subscribe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/victoriadrake%2Fsimple-subscribe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/victoriadrake","download_url":"https://codeload.github.com/victoriadrake/simple-subscribe/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244717112,"owners_count":20498280,"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-lambda","dynamodb","email-marketing","newsletter-api","newsletter-subscriptions","serverless","subscription","subscription-manager"],"created_at":"2024-10-11T00:46:46.870Z","updated_at":"2025-03-21T00:30:25.437Z","avatar_url":"https://github.com/victoriadrake.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 💌 Simple Subscribe\n\nBuild an independent subscriber base. [SimpleSubscribe.org](https://simplesubscribe.org/).\n\n- [About the Project](#about-the-project)\n- [What this Does](#what-this-does)\n- [How this Works](#how-this-works)\n  - [Subscribing](#subscribing)\n  - [Verifying](#verifying)\n  - [Providing Unsubscribe Links](#providing-unsubscribe-links)\n- [Requirements and Installation](#requirements-and-installation)\n  - [Environment Variables for Lambda](#environment-variables-for-lambda)\n  - [Create the Sign Up Form](#create-the-sign-up-form)\n- [Security Considerations](#security-considerations)\n  - [Time-Limited Tokens](#time-limited-tokens)\n  - [Periodic Clean Up](#periodic-clean-up)\n- [Dual License](#dual-license)\n- [Contributing](#contributing)\n  - [Open an Issue](#open-an-issue)\n  - [Send a Pull Request](#send-a-pull-request)\n\n## About the Project\n\nSimple 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.\n\nIf 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.\n\nSimple 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.\n\nThe daughter project [RSS Mailer](https://github.com/victoriadrake/rss-mailer) offers one option for mailing your list by turning RSS feed items into email messages.\n\n## What this Does\n\nSimple Subscribe will let your visitors:\n\n- Enter their email and hit a **Subscribe** button to sign up.\n- Receive a confirmation email in their inbox with a link to finish signing up (double opt-in).\n- Send requests to unsubscribe from your list and automatically have their email removed.\n\nSimple Subscribe handles one part of your subscription newsletter flow: allowing people to subscribe! Here are a few things this project does not do:\n\n- Send newsletters to your list.\n- Click tracking or other metrics.\n- Dance the samba. 💃\n\nIf you'd like to help extend the functionality of this project, please read [Contributing](#contributing).\n\n## How this Works\n\n### Subscribing\n\nSimple 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:\n\n| email                    | confirm | id           | timestamp           |\n| ------------------------ | ------- | ------------ | ------------------- |\n| `subscriber@example.com` | _false_ | `uuid-xxxxx` | 2020-11-01 00:27:39 |\n\n### Verifying\n\nAfter subscribing, the intended subscriber receives an email from SES containing a link. This link takes the format:\n\n```url\n\u003cBASE_URL\u003e\u003cVERIFY_PATH\u003e/?email=subscriber@example.com\u0026id=uuid-xxxxx\n```\n\nVisiting 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:\n\n| email                    | confirm | id           | timestamp           |\n| ------------------------ | ------- | ------------ | ------------------- |\n| `subscriber@example.com` | _true_  | `uuid-xxxxx` | 2020-11-01 00:37:39 |\n\nWhen querying for people to send your newsletter, ensure you only return emails where `confirm` is `true`.\n\n### Providing Unsubscribe Links\n\nSimple 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:\n\n```url\n\u003cBASE_URL\u003e\u003cUNSUBSCRIBE_PATH\u003e/?email=subscriber@example.com\u0026id=uuid-xxxxx\n```\n\nIf the provided `email` and `id` match a database item, that item will be deleted.\n\n## Requirements and Installation\n\nWhile 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.\n\nThe following AWS resources are needed. For set up help, see the provided links.\n\n- [Create a DynamoDB table](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/getting-started-step-1.html) with key `email`, a string. Key names are case-sensitive.\n- [Create a Lambda Function](https://docs.aws.amazon.com/lambda/latest/dg/getting-started-create-function.html) with `main.go` uploaded as the code, and appropriate environment variables (see below). Ensure it has [permissions](https://docs.aws.amazon.com/lambda/latest/dg/lambda-permissions.html) to access DynamoDB and SES.\n- [Set up an API Gateway trigger](https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html?icmpid=docs_lambda_console) for your Lambda. Ensure [`payloadFormatVersion` for your integration](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html) is `2.0`.\n- [Set up AWS Simple Email Service](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-email-set-up.html) 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](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-addresses-and-domains.html).\n- Optionally, if you're interested in giving your API a custom domain, see the [AWS docs on setting up custom domain names for APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html).\n\nThe `scripts/` directory has some helpers in it. To use these:\n\n1. [Install AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) and [set up credentials](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started-set-up-credentials.html) on your machine.\n2. Create a `.env` in this repository's root with the appropriate values as described below.\n\n### Environment Variables for Lambda\n\nThe API will look for the following environment variables:\n\n- `DB_TABLE_NAME`: your DynamoDB table\n- `BASE_URL`: the address of your site, beginning with `https://` and ending with `/`\n- `API_URL`: the endpoint of your API, ending with `/`\n\nAs well as these API endpoints:\n\n- `SUBSCRIBE_PATH`: the name of your subscription endpoint, e.g. `signup`\n- `UNSUBSCRIBE_PATH`: the name of your unsubscribe endpoint, e.g. `unsubscribe`\n- `VERIFY_PATH`: the name of your email verification endpoint, e.g. `verify`\n- `SENDER_EMAIL`: the email your confirmation message will be coming from\n- `SENDER_NAME`: the name you'd like the confirmation message to come from\n\nAs well as these website pages:\n\n- `CONFIRM_SUBSCRIBE_PAGE`: the path of the page your subscriber sees after submitting their email, e.g. `confirm`\n- `SUCCESS_PAGE`: the path of the page your subscriber sees when they complete sign up, e.g. `success`\n- `ERROR_PAGE`: the path of your error page, e.g. `error`\n- `CONFIRM_UNSUBSCRIBE_PAGE`: the path of the page shown after someone successfully unsubscribes, e.g. `unsubscribed`\n\nPages that your subscriber is sent to after an action are constructed with the base URL in the format `\u003cBASE_URL\u003e\u003cSUCCESS_PAGE\u003e`.\n\nYou can [input Lambda environment variables in the AWS console](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html), or use the AWS CLI.\n\nIf you're using the AWS CLI, you can pass the environment variables for Lambda in the following shorthand format:\n\n```sh\nVariables={KeyName1=string,KeyName2=string}\n```\n\nThe 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.\n\nHere's an example of a suitable `.env` that you can copy and modify:\n\n```text\nNAME=\"simple-subscribe\"\nDB_TABLE_NAME=\"SimpleSubscribe\"\n\nLAMBDA_ENV=\"Variables={\\\nDB_TABLE_NAME=SimpleSubscribe,\\\nBASE_URL=https://example.com/,\\\nAPI_URL=https://api.example.com/,\\\nERROR_PAGE=error,\\\nSUCCESS_PAGE=success,\\\nCONFIRM_SUBSCRIBE_PAGE=confirm,\\\nCONFIRM_UNSUBSCRIBE_PAGE=unsubscribed,\\\nSUBSCRIBE_PATH=signup,\\\nUNSUBSCRIBE_PATH=unsubscribe,\\\nVERIFY_PATH=verify,\\\nSENDER_EMAIL=no-reply@example.com,\\\nSENDER_NAME='Ford Prefect'}\"\n```\n\nWhile none of these are private or secret, it's good practice to have Git ignore environment variables. You can do this with `echo .env \u003e\u003e .gitignore` if it's not already there.\n\n### Create the Sign Up Form\n\nYour visitors will need a form to put their email into. Here's an example HTML snippet:\n\n```html\n\u003c!-- Simple Subscribe subscription form begins --\u003e\n\u003cdiv class=\"form-container\"\u003e\n    \u003cp\u003eEnter your email below to subscribe.\u003c/p\u003e\n    \u003cdiv class=\"form-row\" id=\"subscribe\"\u003e\n        \u003c!-- Change the below 'action' to your API subscribe endpoint --\u003e\n        \u003cform action=\"/your/subscribe/path/\" method=\"get\"\u003e\n            \u003clabel hidden for=\"email\"\u003eEnter your email to subscribe\u003c/label\u003e\n            \u003cinput type=\"email\" name=\"email\" id=\"email\" placeholder=\"Enter your email\" required\u003e\n            \u003cbutton type=\"submit\" class=\"primary\" value=\"Subscribe\"\u003eSubscribe\u003c/button\u003e\n        \u003c/form\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003c!-- Subscription form ends --\u003e\n```\n\n## Security Considerations\n\nStandard considerations apply:\n\n- Principle of least privilege: ensure your people and functions have only the minimum necessary permissions for accessing each of your AWS resources.\n- Encryption: ensure your website is using HTTPS in general, and in particular for requests sent to your API.\n- 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 `\u003cinput type=\"email\" ...\u003e` as in the example above.)\n\nHere are some additional security features you may consider:\n\n### Time-Limited Tokens\n\nThe `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.\n\n### Periodic Clean Up\n\nIt 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.\n\nIf you are particularly concerned about data integrity, you may want to explore [On-Demand Backup](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/backuprestore_HowItWorks.html) or [Point-in-Time Recovery](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery.html) for DynamoDB.\n\n## Dual License\n\nSimple Subscribe is available under the [Mozilla Public License 2.0 (MPL-2.0)](https://www.mozilla.org/en-US/MPL/2.0/) for non-monetized applications, such as building and sending your own free newsletter.\n\nFor 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](LICENSE-EULA). You may purchase a license at [SimpleSubscribe.org](https://simplesubscribe.org/).\n\n## Contributing\n\nSimple Subscribe would be happy to have your contribution! Add helper scripts, improve the code, or even just fix a typo you found.\n\nHere are a couple ways you can help out. Thank you for being a part of this open source project! 💕\n\n### Open an Issue\n\nPlease open an issue to tell me about bugs, or anything that might need fixing or updating.\n\n### Send a Pull Request\n\nIf 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.\n\nPlease [fork the repository](https://help.github.com/en/github/getting-started-with-github/fork-a-repo), then check out a local branch that includes the issue number, such as `fix-\u003cissue number\u003e`. For example, `git checkout -b fix-42`.\n\nBefore you submit your PR, make sure your fork is [synced with `master`](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/syncing-a-fork), then [create a PR](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork). You may want to [allow edits from maintainers](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/allowing-changes-to-a-pull-request-branch-created-from-a-fork) so that I can help with small changes like fixing typos.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvictoriadrake%2Fsimple-subscribe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvictoriadrake%2Fsimple-subscribe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvictoriadrake%2Fsimple-subscribe/lists"}