.. image:: https://github.com/jgosmann/doveseed/actions/workflows/ci.yml/badge.svg
:target: https://github.com/jgosmann/doveseed/actions/workflows/ci.yml
:alt: CI and release pipeline
.. image:: https://codecov.io/gh/jgosmann/doveseed/branch/main/graph/badge.svg
:target: https://codecov.io/gh/jgosmann/doveseed
:alt: Codecov coverage
.. image:: https://img.shields.io/pypi/v/doveseed
:target: https://pypi.org/project/doveseed/
:alt: PyPI
.. image:: https://img.shields.io/pypi/pyversions/doveseed
:target: https://pypi.org/project/doveseed/
:alt: PyPI - Python Version
.. image:: https://img.shields.io/pypi/l/doveseed
:target: https://pypi.org/project/doveseed/
:alt: PyPI - License
.. image:: https://github.com/jgosmann/doveseed/blob/main/doveseed-logo.png
:alt: Doveseed logo
:width: 145
Doveseed
========
Doveseed is a backend service for email subscriptions to RSS feeds.
Setup
-----
Configuration
^^^^^^^^^^^^^
Doveseed requires a configuration file in JSON format. Take a look at
``config.sample.json``. The format is as follows:
* ``db``: JSON file in which Doveseed persists its data.
* ``rss``: URL to the RSS feed for which new notifications are to be send.
* ``smtp``
* ``host``: SMTP host used to send notification emails.
* ``port``: SMTP port used to send notification emails (defaul: ``0`` = auto-select).
* ``user``: SMTP logon user name.
* ``password``: SMTP logon password.
* ``ssl_mode``: Activate/deactivate SSL/TLS, valid values ``"no-ssl"``, ``"start-tls"``, ``"tls"`` (default ``"start-tls"``).
* ``check_hostname``: Whether to verify the hostname when using TLS (default ``true``).
* ``template_vars``: Defines template variables to replace in the email templates.
* ``display_name``: Name for the website to use in emails.
* ``host``: Hostname of the website.
* ``sender``: Email address that is sending the notifications.
* ``confirm_url_format``: Template for the URL that is used for confirmation
links. The following values will be replaced in it:
* ``{host}`` with the specified host,
* ``{email}`` with the email address to confirm,
* ``{token}`` with the confirmation token,
* ``{{`` and ``}}`` with ``{`` and ``}``.
* ``email_templates``: Path to the templates for the emails.
* ``confirm_timeout_minutes``: Timeout in minutes during which a subscription needs to be confirmed.
**Ensure that the configuration files have appropriate permissions, i.e. only
readable by you and Doveseed.**
By default the configuration filename is assumed to be ``config.json``.
Email templates
^^^^^^^^^^^^^^^
Templates for the emails sent out are written in
`Jinja <https://jinja.palletsprojects.com/en/2.11.x/>`_.
Look in ``templates/example`` for example email templates.
There is a template for each type of email being sent:
* ``new-post.*``: for notifications about new posts,
* ``subscribe.*``: for requesting confirmation to a new subscription,
* and ``unsubscribe.*``: for requesting confirmation to a cancellation of a subscription.
Each of these templates consists out of three files:
* ``*.subject.txt``: for the subject line of the email,
* ``*.txt``: for the plain text version of the email,
* and ``*.html``: for the HTML version of the email.
REST service
^^^^^^^^^^^^
The REST service runs as a Python `ASGI app
<https://asgi.readthedocs.io/en/latest/>`_. See the FastAPI documentation for
`deployment options <https://fastapi.tiangolo.com/deployment/>`_.
CORS
~~~~
To set appropriate CORS headers use the `FastAPI CORSMiddleware
<https://fastapi.tiangolo.com/tutorial/cors/>`_. Activate it by adding the
following lines to the file where you instantiate the app::
from doveseed.app import app
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["http://example.com"],
allow_methods=["GET", "POST"],
allow_headers=["Authorization"],
)
ReCaptcha
~~~~~~~~~
You activate `ReCaptcha (v2) <https://www.google.com/recaptcha/>`_ verification of
requests with Doveseed.
First, you need to install the required optional dependencies::
pip install 'doveseed[recaptcha]'
Then, add the follwing lines to the file where you instantiate the app::
from doveseed.app import app
from doveseed.recaptcha import ReCaptchaMiddleware
app.add_middleware = ReCaptchaMiddleware('^/(un)?subscribe/.*', 'recaptcha.json')
Also, create the ``recaptcha.json`` with the required ReCaptcha configuration:
* ``hostnames``: List of hostnames to accept ReCaptchas from.
* ``secret``: The shared key between your site and reCAPTCHA.
**Ensure that the configuration files have appropriate permissions, i.e. only
readable by you and Doveseed.**
Database cleanup
^^^^^^^^^^^^^^^^
Expired pending subscription can be cleaned from the database with::
python -m doveseed.cli clean <path to config file>
Ideally, this command is run once per day as a cron job.
Checking for new posts
^^^^^^^^^^^^^^^^^^^^^^
To check for new post and send notification emails run::
python -m doveseed.cli notify <path to config file>
This can either run in a regular interval as a cron job or it can be triggered
in some way after new posts have been published.
**Run this command once to initialize the database before going live because
initially all items in the RSS feed will be considered to be old.** (This
prevents sending a notification email for all already existing items in the
feed.)
REST interface
--------------
Health
^^^^^^
To check the service health:
GET /health
Returns a 204 (no content) status if the service is up and running.
Subscribe
^^^^^^^^^
To subscribe with an email address::
POST /subscribe/<url encoded email>
Content-Type: application/json
{ captcha: "ReCaptcha returned from Google API" }
This will return a ``201 NO CONTENT`` and send out the email requesting
confirmation.
Unsubscribe
^^^^^^^^^^^
To unsubscribe an email address::
POST /unsubscribe/<url encoded email>
Content-Type: application/json
{ captcha: "ReCaptcha returned from Google API" }
This will return a ``201 NO CONTENT`` and send out the email requesting
confirmation if the email is subscribed.
Confirm
^^^^^^^
To confirm a request to subscribe or unsubscribe::
POST /confirm/<url encoded email>
Content-Type: application/json
Authorization: Bearer <token from confirmation reuest email>
This will return a ``201 NO CONTENT`` on success,
and ``401 UNAUTHORIZED`` if the token or email is invalid.
Raw data
{
"_id": null,
"home_page": "https://github.com/jgosmann/doveseed/",
"name": "doveseed",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0.0,>=3.9.0",
"maintainer_email": null,
"keywords": "email, rss, subscriptions",
"author": "Jan Gosmann",
"author_email": "jan@hyper-world.de",
"download_url": "https://files.pythonhosted.org/packages/e0/e7/2830246b8b90acfae8b89dd7ca7ae260b3316d0f7642f5449660db052289/doveseed-2.1.2.tar.gz",
"platform": null,
"description": ".. image:: https://github.com/jgosmann/doveseed/actions/workflows/ci.yml/badge.svg\n :target: https://github.com/jgosmann/doveseed/actions/workflows/ci.yml\n :alt: CI and release pipeline\n.. image:: https://codecov.io/gh/jgosmann/doveseed/branch/main/graph/badge.svg\n :target: https://codecov.io/gh/jgosmann/doveseed\n :alt: Codecov coverage\n.. image:: https://img.shields.io/pypi/v/doveseed\n :target: https://pypi.org/project/doveseed/\n :alt: PyPI\n.. image:: https://img.shields.io/pypi/pyversions/doveseed\n :target: https://pypi.org/project/doveseed/\n :alt: PyPI - Python Version\n.. image:: https://img.shields.io/pypi/l/doveseed\n :target: https://pypi.org/project/doveseed/\n :alt: PyPI - License\n\n.. image:: https://github.com/jgosmann/doveseed/blob/main/doveseed-logo.png\n :alt: Doveseed logo\n :width: 145\n\n\nDoveseed\n========\n\nDoveseed is a backend service for email subscriptions to RSS feeds.\n\n\nSetup\n-----\n\nConfiguration\n^^^^^^^^^^^^^\n\nDoveseed requires a configuration file in JSON format. Take a look at\n``config.sample.json``. The format is as follows:\n\n* ``db``: JSON file in which Doveseed persists its data.\n* ``rss``: URL to the RSS feed for which new notifications are to be send.\n* ``smtp``\n\n * ``host``: SMTP host used to send notification emails.\n * ``port``: SMTP port used to send notification emails (defaul: ``0`` = auto-select).\n * ``user``: SMTP logon user name.\n * ``password``: SMTP logon password.\n * ``ssl_mode``: Activate/deactivate SSL/TLS, valid values ``\"no-ssl\"``, ``\"start-tls\"``, ``\"tls\"`` (default ``\"start-tls\"``).\n * ``check_hostname``: Whether to verify the hostname when using TLS (default ``true``).\n\n* ``template_vars``: Defines template variables to replace in the email templates.\n\n * ``display_name``: Name for the website to use in emails.\n * ``host``: Hostname of the website.\n * ``sender``: Email address that is sending the notifications.\n * ``confirm_url_format``: Template for the URL that is used for confirmation\n links. The following values will be replaced in it:\n\n * ``{host}`` with the specified host,\n * ``{email}`` with the email address to confirm,\n * ``{token}`` with the confirmation token,\n * ``{{`` and ``}}`` with ``{`` and ``}``.\n\n* ``email_templates``: Path to the templates for the emails.\n* ``confirm_timeout_minutes``: Timeout in minutes during which a subscription needs to be confirmed.\n\n**Ensure that the configuration files have appropriate permissions, i.e. only\nreadable by you and Doveseed.**\n\nBy default the configuration filename is assumed to be ``config.json``.\n\n\nEmail templates\n^^^^^^^^^^^^^^^\n\nTemplates for the emails sent out are written in\n`Jinja <https://jinja.palletsprojects.com/en/2.11.x/>`_.\nLook in ``templates/example`` for example email templates.\nThere is a template for each type of email being sent:\n\n* ``new-post.*``: for notifications about new posts,\n* ``subscribe.*``: for requesting confirmation to a new subscription,\n* and ``unsubscribe.*``: for requesting confirmation to a cancellation of a subscription.\n\nEach of these templates consists out of three files:\n\n* ``*.subject.txt``: for the subject line of the email,\n* ``*.txt``: for the plain text version of the email,\n* and ``*.html``: for the HTML version of the email.\n\n\n\nREST service\n^^^^^^^^^^^^\n\nThe REST service runs as a Python `ASGI app\n<https://asgi.readthedocs.io/en/latest/>`_. See the FastAPI documentation for\n`deployment options <https://fastapi.tiangolo.com/deployment/>`_.\n\n\n\nCORS\n~~~~\n\nTo set appropriate CORS headers use the `FastAPI CORSMiddleware\n<https://fastapi.tiangolo.com/tutorial/cors/>`_. Activate it by adding the\nfollowing lines to the file where you instantiate the app::\n\n from doveseed.app import app\n from fastapi.middleware.cors import CORSMiddleware\n\n app.add_middleware(\n CORSMiddleware,\n allow_origins=[\"http://example.com\"],\n allow_methods=[\"GET\", \"POST\"],\n allow_headers=[\"Authorization\"],\n )\n\n\nReCaptcha\n~~~~~~~~~\n\nYou activate `ReCaptcha (v2) <https://www.google.com/recaptcha/>`_ verification of\nrequests with Doveseed.\n\nFirst, you need to install the required optional dependencies::\n\n pip install 'doveseed[recaptcha]'\n\nThen, add the follwing lines to the file where you instantiate the app::\n\n from doveseed.app import app\n from doveseed.recaptcha import ReCaptchaMiddleware\n\n app.add_middleware = ReCaptchaMiddleware('^/(un)?subscribe/.*', 'recaptcha.json')\n\nAlso, create the ``recaptcha.json`` with the required ReCaptcha configuration:\n\n* ``hostnames``: List of hostnames to accept ReCaptchas from.\n* ``secret``: The shared key between your site and reCAPTCHA.\n\n\n**Ensure that the configuration files have appropriate permissions, i.e. only\nreadable by you and Doveseed.**\n\n\nDatabase cleanup\n^^^^^^^^^^^^^^^^\n\nExpired pending subscription can be cleaned from the database with::\n\n python -m doveseed.cli clean <path to config file>\n\nIdeally, this command is run once per day as a cron job.\n\n\nChecking for new posts\n^^^^^^^^^^^^^^^^^^^^^^\n\nTo check for new post and send notification emails run::\n\n python -m doveseed.cli notify <path to config file>\n\nThis can either run in a regular interval as a cron job or it can be triggered\nin some way after new posts have been published.\n\n**Run this command once to initialize the database before going live because\ninitially all items in the RSS feed will be considered to be old.** (This\nprevents sending a notification email for all already existing items in the\nfeed.)\n\n\nREST interface\n--------------\n\nHealth\n^^^^^^\n\nTo check the service health:\n\n GET /health\n\nReturns a 204 (no content) status if the service is up and running.\n\nSubscribe\n^^^^^^^^^\n\nTo subscribe with an email address::\n\n POST /subscribe/<url encoded email>\n Content-Type: application/json\n\n { captcha: \"ReCaptcha returned from Google API\" }\n\nThis will return a ``201 NO CONTENT`` and send out the email requesting\nconfirmation.\n\nUnsubscribe\n^^^^^^^^^^^\n\nTo unsubscribe an email address::\n\n POST /unsubscribe/<url encoded email>\n Content-Type: application/json\n\n { captcha: \"ReCaptcha returned from Google API\" }\n\nThis will return a ``201 NO CONTENT`` and send out the email requesting\nconfirmation if the email is subscribed.\n\nConfirm\n^^^^^^^\n\nTo confirm a request to subscribe or unsubscribe::\n\n POST /confirm/<url encoded email>\n Content-Type: application/json\n Authorization: Bearer <token from confirmation reuest email>\n\nThis will return a ``201 NO CONTENT`` on success,\nand ``401 UNAUTHORIZED`` if the token or email is invalid.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Doveseed is a backend service for email subscriptions to RSS feeds.",
"version": "2.1.2",
"project_urls": {
"Homepage": "https://github.com/jgosmann/doveseed/",
"Repository": "https://github.com/jgosmann/doveseed/"
},
"split_keywords": [
"email",
" rss",
" subscriptions"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "03461564d9a028bb3d0d1012aa7d7b9c37f4ced216cd012fe16cc128f33ac8e1",
"md5": "da0c62a184327846d64c5d0f12cd0364",
"sha256": "3801554bc19438727811ba7f97db84e8a964a07d4d791365ebfb7fdbcebfeccc"
},
"downloads": -1,
"filename": "doveseed-2.1.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "da0c62a184327846d64c5d0f12cd0364",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0.0,>=3.9.0",
"size": 17072,
"upload_time": "2024-11-10T18:04:04",
"upload_time_iso_8601": "2024-11-10T18:04:04.178712Z",
"url": "https://files.pythonhosted.org/packages/03/46/1564d9a028bb3d0d1012aa7d7b9c37f4ced216cd012fe16cc128f33ac8e1/doveseed-2.1.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e0e72830246b8b90acfae8b89dd7ca7ae260b3316d0f7642f5449660db052289",
"md5": "c5754c2b1568ec6ac34d015d8cb6fcc0",
"sha256": "f40c7f1cedda04df03cb278ca5ba7fad12480de4d754c22b23ab541802dace46"
},
"downloads": -1,
"filename": "doveseed-2.1.2.tar.gz",
"has_sig": false,
"md5_digest": "c5754c2b1568ec6ac34d015d8cb6fcc0",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0.0,>=3.9.0",
"size": 14932,
"upload_time": "2024-11-10T18:04:05",
"upload_time_iso_8601": "2024-11-10T18:04:05.137346Z",
"url": "https://files.pythonhosted.org/packages/e0/e7/2830246b8b90acfae8b89dd7ca7ae260b3316d0f7642f5449660db052289/doveseed-2.1.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-10 18:04:05",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "jgosmann",
"github_project": "doveseed",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "doveseed"
}