Skip to main content

Transactional email module for Pokie

Project description

Welcome to Pokie-mail

Tests pypi license

Transactional SMTP email support for Pokie applications

Features

The pokie-mail package implements a simple templating system for emails, as well as a job queue to send them. The templating system supports placeholders and locales, and has the notion of channel - allowing it to be extended to use other mechanisms such as push notifications or other rich notification providers.

The provided worker will attempt to send upto 10k emails per batch from the queue, using the configured rick_mailer sink for channel 0 submissions.

Other channel submissions (such as site notifications and push notifications) need to be implemented with their specific behaviour.

Usage

How to add templates

The module supports both embedded html templates and text templates, as well as a list of placeholders and default values. Application templates can either be imported directly via SQL or using Pokie's fixture mechanism. There are also functions that enable adding new templates at runtime.

Templates can have placeholders and default values; Template placeholders are freeform - one can use whatever format is suitable to represent the placeholders, but a common form is to use double placeholders, such as {{placeholder_name}}:

    template = MessageTemplateRecord(
        template="template_name",
        language="en",
        channel=0,
        label="this is an example template",
        subject="template subject",
        body="the quick {{color}} {{animal}} {{what}} over the lazy dog", # text version
        html="<b>the quick {{color}} {{animal}} {{what}} over the lazy dog</b>", # html version
        placeholders={
            "{{color}}": "blue", # placeholder and default value
            "{{animal}}": "duck", 
            "{{what}}": "flies"
        },
    )

Integrate with your application

Just add "pokie_mail" module to the module list, add MailConfigTemplate to your configuration and optionally override the default SMTP parameters if necessary:

from rick.resource.config import EnvironmentConfig
from pokie.config.template import BaseConfigTemplate, PgConfigTemplate, TestConfigTemplate
from pokie.core import FlaskApplication
from pokie.core.factories.pgsql import PgSqlFactory
from pokie_mail.config import MailConfigTemplate


# your application configuration

class Config(EnvironmentConfig, BaseConfigTemplate, PgConfigTemplate, TestConfigTemplate, MailConfigTemplate):
    # ==== Other configuration settings =====
    (...)
    
    # ==== MailConfigTemplate settings =====
    # number of emails to send at once
    MAILS_PER_RUN = 10000
    
    # SMTP Configuration [to use with mailhog]
    SMTP_HOST = "localhost"
    SMTP_PORT = 1025
    SMTP_USERNAME = ""
    SMTP_PASSWORD = ""

    
def build_pokie():
    # load configuration from ENV
    cfg = Config().build()

    # modules to load & initialize
    modules = [
        'pokie_mail', # enable pokie email
        # your other modules below
        (...)
        
    ]

    # factories to run
    factories = [PgSqlFactory]

    # build app
    pokie_app = FlaskApplication(cfg)
    flask_app = pokie_app.build(modules, factories)
    return pokie_app, flask_app


main, app = build_pokie()

if __name__ == '__main__':
    main.cli()

Assembling messages

Queuing a message is a two-step process - first get the message builder for the desired template, then the resulting message is queued using the MessageQueueService:

from pokie_mail.service import MessageTemplateService
from pokie_mail.service import MessageQueueService
from rick.mixin import Injectable
from pokie.constants import DI_SERVICES
from pokie_mail.constants import SVC_MESSAGE_TEMPLATE, SVC_MESSAGE_QUEUE

class SomeService(Injectable):

    def notify_user(self, email:str, first_name:str, last_name:str):
        
        # get template service
        svc_template = self.get_di().get(DI_SERVICES).get(SVC_MESSAGE_TEMPLATE) # type: MessageTemplateService

        # get queue service
        svc_queue = self.get_di().get(DI_SERVICES).get(SVC_MESSAGE_QUEUE) # type: MessageQueueService

        # get template builder for the template "template_notify_user" to assemble the message
        builder = svc_template.get_builder("template_notify_user", "en")
        
        # now assemble the message record
        message = builder.assemble(
            msg_from="nobody@somewhere.local",
            msg_to=email,
            data= {
                "{{first_name}}": first_name,
                "{{last_name}}": last_name,                
            }
        )
        
        # queue message for sending
        message_id = svc_queue.queue(message)

Configuration

SMTP configuration is performed in the main config class, and can be overridden by using the traditional environment variable mechanisms and/or StrOrFile for credential loading:

from rick.resource.config import EnvironmentConfig
from pokie.config.template import BaseConfigTemplate, PgConfigTemplate, TestConfigTemplate
from pokie_mail.config import MailConfigTemplate

# base configuration
class Config(EnvironmentConfig, BaseConfigTemplate, PgConfigTemplate, TestConfigTemplate, MailConfigTemplate):
    # ==== Other configuration settings =====
    (...)
    
    # ==== MailConfigTemplate settings =====
    # number of emails to send at once
    MAILS_PER_RUN = 10000
    
    # SMTP Configuration [to use with mailhog]
    SMTP_HOST = "localhost"
    SMTP_PORT = 1025
    SMTP_USE_TLS = False
    SMTP_USE_SSL = False
    SMTP_DEBUG = False
    SMTP_USERNAME = ""
    SMTP_PASSWORD = ""
    SMTP_DEFAULT_SENDER = None
    SMTP_TIMEOUT = None
    SMTP_SSL_KEYFILE = None
    SMTP_SSL_CERTFILE = None

The above example can be used to forward email to MailHog during development.

Sending email in development mode

Use the configuration shown previously to use MailHog to intercept mail messages. To run the mail queue, open the job runner in a separate console:

$ python3 main.py job:run

Sending email in production

To send email in production, configure a background process to run the job runner:

$ python3 main.py job:run

Running tests

Running tests require a PostgreSQL database server with access credentials that can run CREATE DATABASE/DROP DATABASE commands. The test database is created automatically.

running with pytest

Install required dependencies:

$ pip3 install -r requirements-dev.txt

Define the appropriate environment variables to access the database, and run pytest (optionally with code coverage):

$ TEST_DB_HOST='localhost' TEST_DB_USER='db_user' TEST_DB_PASSWORD='db_password' python3 main.py pytest [-cov=pokie_mail]

running with tox

Edit tox.ini and set the appropriate database credentials, then just run tox with the desired environment, eg:

$ tox -e py310

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

Pokie-mail-1.0.0.tar.gz (11.4 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page