~homeworkprod/byceps

cd50e271d16bbd0175777573ba4c38c6021d68cc — Jochen Kupperschmidt a month ago a9b80fe
Replace Marrow Mailer with stdlib email assembly and sending
4 files changed, 33 insertions(+), 54 deletions(-)

M byceps/application.py
M byceps/email.py
M config/development-example.py
M requirements.txt
M byceps/application.py => byceps/application.py +0 -3
@@ 20,7 20,6 @@ from redis import StrictRedis
from .blueprints.blueprints import register_blueprints
from . import config, config_defaults
from .database import db
from . import email
from .util.authorization import has_current_user_permission, load_permissions
from .util.l10n import get_current_user_locale
from .util import templatefilters, templatefunctions


@@ 65,8 64,6 @@ def create_app(
    # Initialize Redis client.
    app.redis_client = StrictRedis.from_url(app.config['REDIS_URL'])

    email.init_app(app)

    app_mode = config.get_app_mode(app)

    load_permissions()

M byceps/email.py => byceps/email.py +33 -47
@@ 2,68 2,54 @@
byceps.email
~~~~~~~~~~~~

Sending e-mail.
Send e-mail.

:Copyright: 2014-2022 Jochen Kupperschmidt
:License: Revised BSD (see `LICENSE` file for details)
"""

from __future__ import annotations
from typing import Any
from email.message import EmailMessage
from smtplib import SMTP

from flask import current_app, Flask
from flask import current_app

# Hack to avoid import error in `marrow.util` on Python 3.8+.
import sys

sys.modules['cgi.parse_qsl'] = None
from marrow.mailer import Mailer


def init_app(app: Flask) -> None:
    config = _get_config(app)
    app.marrowmailer = Mailer(config)


def _get_config(app: Flask) -> dict[str, Any]:
    config = {
        'transport.use': app.config.get('MAIL_TRANSPORT', 'smtp'),
        'transport.host': app.config.get('MAIL_SERVER', 'localhost'),
        'transport.port': app.config.get('MAIL_PORT', 25),
        'transport.debug': app.config.get('MAIL_DEBUG', app.debug),
        'message.author': app.config['MAIL_DEFAULT_SENDER'],
    }

    username = app.config.get('MAIL_USERNAME', None)
    if username is not None:
        config['transport.username'] = username
def send(sender: str, recipients: list[str], subject: str, body: str) -> None:
    """Assemble and send an e-mail."""
    if current_app.config.get('MAIL_SUPPRESS_SEND', False):
        current_app.logger.debug('Suppressing sending of email.')
        return

    password = app.config.get('MAIL_PASSWORD', None)
    if password is not None:
        config['transport.password'] = password
    message = _build_message(sender, recipients, subject, body)

    if app.config.get('MAIL_USE_SSL', False):
        config['transport.tls'] = 'ssl'
    current_app.logger.debug('Sending email.')
    _send_via_smtp(message)

    if app.config.get('MAIL_USE_TLS', False):
        config['transport.tls'] = 'required'

    return config
def _build_message(
    sender: str, recipients: list[str], subject: str, body: str
) -> EmailMessage:
    """Assemble message."""
    message = EmailMessage()
    message['From'] = sender
    message['To'] = ', '.join(recipients)
    message['Subject'] = subject
    message.set_content(body)
    return message


def send(sender: str, recipients: list[str], subject: str, body: str) -> None:
    """Assemble and send an e-mail."""
    if current_app.config.get('MAIL_SUPPRESS_SEND', False):
        current_app.logger.debug('Suppressing sending of email.')
        return
def _send_via_smtp(message: EmailMessage) -> None:
    """Send email via SMTP."""
    config = current_app.config

    mailer = current_app.marrowmailer
    host = config.get('MAIL_HOST', 'localhost')
    port = config.get('MAIL_PORT', 25)
    username = config.get('MAIL_USERNAME', None)
    password = config.get('MAIL_PASSWORD', None)

    message = mailer.new(
        author=sender, to=recipients, subject=subject, plain=body, brand=False
    )
    with SMTP(host, port) as smtp:
        if username and password:
            smtp.login(username, password)

    current_app.logger.debug('Sending email.')
    mailer.start()
    mailer.send(message)
    mailer.stop()
        smtp.send_message(message)

M config/development-example.py => config/development-example.py +0 -2
@@ 15,7 15,5 @@ REDIS_URL = 'redis://127.0.0.1:6379/0'
APP_MODE = os.environ.get('APP_MODE')
SITE_ID = os.environ.get('SITE_ID')

MAIL_TRANSPORT = 'logging'

DEBUG_TOOLBAR_ENABLED = True
STYLE_GUIDE_ENABLED = True

M requirements.txt => requirements.txt +0 -2
@@ 10,8 10,6 @@ hiredis==2.0.0
itsdangerous==2.1.2
jinja2==3.1.2
markupsafe==2.1.1
marrow.mailer==4.0.3
marrow.util==1.2.3
marshmallow==3.17.0
mistletoe==0.8.2
pillow==9.2.0