implement mailer with task queue

This commit is contained in:
dandds
2018-10-11 14:58:33 -04:00
parent 0d9f1cd7e0
commit f7d8783349
7 changed files with 106 additions and 61 deletions

View File

@@ -22,7 +22,8 @@ from atst.domain.authz import Authorization
from atst.models.permissions import Permissions
from atst.eda_client import MockEDAClient
from atst.uploader import Uploader
from atst.utils.mailer import make_mailer
from atst.utils.mailer import Mailer, RedisMailer
from atst.queue import queue
ENV = os.getenv("FLASK_ENV", "dev")
@@ -37,11 +38,11 @@ def make_app(config):
template_folder=parent_dir.child("templates").absolute(),
static_folder=parent_dir.child("static").absolute(),
)
redis = make_redis(config)
make_redis(app, config)
csrf = CSRFProtect()
app.config.update(config)
app.config.update({"SESSION_REDIS": redis})
app.config.update({"SESSION_REDIS": app.redis})
make_flask_callbacks(app)
make_crl_validator(app)
@@ -49,6 +50,7 @@ def make_app(config):
make_eda_client(app)
make_upload_storage(app)
make_mailer(app)
queue.init_app(app)
db.init_app(app)
csrf.init_app(app)
@@ -95,6 +97,7 @@ def map_config(config):
"PERMANENT_SESSION_LIFETIME": config.getint(
"default", "PERMANENT_SESSION_LIFETIME"
),
"RQ_REDIS_URL": config["default"]["REDIS_URI"],
}
@@ -143,8 +146,9 @@ def make_config():
return map_config(config)
def make_redis(config):
return redis.Redis.from_url(config["REDIS_URI"])
def make_redis(app, config):
r = redis.Redis.from_url(config["REDIS_URI"])
app.redis = r
def make_crl_validator(app):
@@ -166,3 +170,22 @@ def make_upload_storage(app):
secret=app.config.get("STORAGE_SECRET"),
)
app.uploader = uploader
def _map_config(config):
return {
"server": config.get("MAIL_SERVER"),
"port": config.get("MAIL_PORT"),
"sender": config.get("MAIL_SENDER"),
"password": config.get("MAIL_PASSWORD"),
"use_tls": config.get("MAIL_TLS", False),
}
def make_mailer(app):
config = _map_config(app.config)
if app.config["DEBUG"]:
mailer = RedisMailer(redis=app.redis, **config)
else:
mailer = Mailer(**config)
app.mailer = mailer

9
atst/queue.py Normal file
View File

@@ -0,0 +1,9 @@
from flask_rq2 import RQ
from flask import current_app as app
queue = RQ()
@queue.job
def send_mail(to, subject, body):
app.mailer.send(to, subject, body)

View File

@@ -10,6 +10,7 @@ from flask import (
from . import redirect_after_login_url
from atst.domain.users import Users
from atst.queue import send_mail
bp = Blueprint("dev", __name__)
@@ -77,7 +78,7 @@ def login_dev():
@bp.route("/test-email")
def test_email():
app.mailer.send(
send_mail.queue(
[request.args.get("to")], request.args.get("subject"), request.args.get("body")
)

View File

@@ -1,6 +1,5 @@
import smtplib
from email.message import EmailMessage
from collections import deque
class _HostConnection:
@@ -25,18 +24,13 @@ class _HostConnection:
self.host.quit()
class Mailer:
def __init__(self, server, port, sender, password, use_tls=False, debug=False):
class BaseMailer:
def __init__(self, server, port, sender, password, use_tls=False):
self.server = server
self.port = port
self.sender = sender
self.password = password
self.use_tls = use_tls
self.debug = debug
self.messages = deque(maxlen=50)
def connection(self):
return _HostConnection(self.server, self.port, self.sender, self.password)
def _message(self, recipients, subject, body):
msg = EmailMessage()
@@ -47,27 +41,33 @@ class Mailer:
return msg
def send(self, recipients, subject, body):
pass
class Mailer(BaseMailer):
def connection(self):
return _HostConnection(self.server, self.port, self.sender, self.password)
def send(self, recipients, subject, body):
message = self._message(recipients, subject, body)
if self.debug:
self.messages.appendleft(message)
else:
with self.connection() as conn:
conn.send_message(message)
with self.connection() as conn:
conn.send_message(message)
def _map_config(config):
return {
"server": config.get("MAIL_SERVER"),
"port": config.get("MAIL_PORT"),
"sender": config.get("MAIL_SENDER"),
"password": config.get("MAIL_PASSWORD"),
"use_tls": config.get("MAIL_TLS", False),
"debug": config.get("DEBUG", False),
}
class RedisMailer(BaseMailer):
def __init__(self, redis, **kwargs):
super().__init__(**kwargs)
self.redis = redis
self._reset()
def _reset(self):
self.redis.delete("atat_inbox")
def make_mailer(app):
config = _map_config(app.config)
mailer = Mailer(**config)
app.mailer = mailer
@property
def messages(self):
return [msg.decode() for msg in self.redis.lrange("atat_inbox", 0, -1)]
def send(self, recipients, subject, body):
message = self._message(recipients, subject, body)
self.redis.lpush("atat_inbox", str(message))