fix: move email
stuff from subpackage to module
This commit is contained in:
parent
902412322e
commit
6c8f1c973d
|
@ -1,6 +0,0 @@
|
|||
|
||||
``wuttjamaican.email.handler``
|
||||
==============================
|
||||
|
||||
.. automodule:: wuttjamaican.email.handler
|
||||
:members:
|
|
@ -1,6 +0,0 @@
|
|||
|
||||
``wuttjamaican.email.message``
|
||||
==============================
|
||||
|
||||
.. automodule:: wuttjamaican.email.message
|
||||
:members:
|
|
@ -189,7 +189,7 @@ Glossary
|
|||
The :term:`handler` responsible for sending email on behalf of
|
||||
the :term:`app`.
|
||||
|
||||
Default is :class:`~wuttjamaican.email.handler.EmailHandler`.
|
||||
Default is :class:`~wuttjamaican.email.EmailHandler`.
|
||||
|
||||
email key
|
||||
String idenfier for a certain :term:`email type`. Each email key
|
||||
|
|
|
@ -82,8 +82,6 @@ Contents
|
|||
api/wuttjamaican.db.sess
|
||||
api/wuttjamaican.db.util
|
||||
api/wuttjamaican.email
|
||||
api/wuttjamaican.email.handler
|
||||
api/wuttjamaican.email.message
|
||||
api/wuttjamaican.enum
|
||||
api/wuttjamaican.exc
|
||||
api/wuttjamaican.install
|
||||
|
|
|
@ -50,9 +50,8 @@ for one or both of the ``text/plain`` and ``text/html`` content-types
|
|||
(using ``txt`` and ``html`` as shorthand name, respectively).
|
||||
|
||||
Template files must use the :doc:`Mako template language <mako:index>`
|
||||
and be named based on the
|
||||
:attr:`~wuttjamaican.email.message.Message.key` for the email type, as
|
||||
well as content-type.
|
||||
and be named based on the :attr:`~wuttjamaican.email.Message.key` for
|
||||
the email type, as well as content-type.
|
||||
|
||||
Therefore a new email of type ``poser_alert_foo`` would need one or
|
||||
both of these defined:
|
||||
|
|
|
@ -768,7 +768,7 @@ class AppHandler:
|
|||
|
||||
See also :meth:`send_email()`.
|
||||
|
||||
:rtype: :class:`~wuttjamaican.email.handler.EmailHandler`
|
||||
:rtype: :class:`~wuttjamaican.email.EmailHandler`
|
||||
"""
|
||||
if 'email' not in self.handlers:
|
||||
spec = self.config.get(f'{self.appname}.email.handler',
|
||||
|
@ -823,7 +823,7 @@ class AppHandler:
|
|||
Send an email message.
|
||||
|
||||
This is a convenience wrapper around
|
||||
:meth:`~wuttjamaican.email.handler.EmailHandler.send_email()`.
|
||||
:meth:`~wuttjamaican.email.EmailHandler.send_email()`.
|
||||
"""
|
||||
self.get_email_handler().send_email(*args, **kwargs)
|
||||
|
||||
|
|
|
@ -26,15 +26,146 @@ Email Handler
|
|||
|
||||
import logging
|
||||
import smtplib
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
|
||||
from wuttjamaican.app import GenericHandler
|
||||
from wuttjamaican.util import resource_path
|
||||
from wuttjamaican.email.message import Message
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Message:
|
||||
"""
|
||||
Represents an email message to be sent.
|
||||
|
||||
:param to: Recipient(s) for the message. This may be either a
|
||||
string, or list of strings. If a string, it will be converted
|
||||
to a list since that is how the :attr:`to` attribute tracks it.
|
||||
Similar logic is used for :attr:`cc` and :attr:`bcc`.
|
||||
|
||||
All attributes shown below may also be specified via constructor.
|
||||
|
||||
.. attribute:: key
|
||||
|
||||
Unique key indicating the "type" of message. An "ad-hoc"
|
||||
message created arbitrarily may not have/need a key; however
|
||||
one created via
|
||||
:meth:`~wuttjamaican.email.EmailHandler.make_auto_message()`
|
||||
will always have a key.
|
||||
|
||||
This key is not used for anything within the ``Message`` class
|
||||
logic. It is used by
|
||||
:meth:`~wuttjamaican.email.EmailHandler.make_auto_message()`
|
||||
when constructing the message, and the key is set on the final
|
||||
message only as a reference.
|
||||
|
||||
.. attribute:: sender
|
||||
|
||||
Sender (``From:``) address for the message.
|
||||
|
||||
.. attribute:: subject
|
||||
|
||||
Subject text for the message.
|
||||
|
||||
.. attribute:: to
|
||||
|
||||
List of ``To:`` recipients for the message.
|
||||
|
||||
.. attribute:: cc
|
||||
|
||||
List of ``Cc:`` recipients for the message.
|
||||
|
||||
.. attribute:: bcc
|
||||
|
||||
List of ``Bcc:`` recipients for the message.
|
||||
|
||||
.. attribute:: replyto
|
||||
|
||||
Optional reply-to (``Reply-To:``) address for the message.
|
||||
|
||||
.. attribute:: txt_body
|
||||
|
||||
String with the ``text/plain`` body content.
|
||||
|
||||
.. attribute:: html_body
|
||||
|
||||
String with the ``text/html`` body content.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
key=None,
|
||||
sender=None,
|
||||
subject=None,
|
||||
to=None,
|
||||
cc=None,
|
||||
bcc=None,
|
||||
replyto=None,
|
||||
txt_body=None,
|
||||
html_body=None,
|
||||
):
|
||||
self.key = key
|
||||
self.sender = sender
|
||||
self.subject = subject
|
||||
self.set_recips('to', to)
|
||||
self.set_recips('cc', cc)
|
||||
self.set_recips('bcc', bcc)
|
||||
self.replyto = replyto
|
||||
self.txt_body = txt_body
|
||||
self.html_body = html_body
|
||||
|
||||
def set_recips(self, name, value):
|
||||
""" """
|
||||
if value:
|
||||
if isinstance(value, str):
|
||||
value = [value]
|
||||
if not isinstance(value, (list, tuple)):
|
||||
raise ValueError("must specify a string, tuple or list value")
|
||||
else:
|
||||
value = []
|
||||
setattr(self, name, list(value))
|
||||
|
||||
def as_string(self):
|
||||
"""
|
||||
Returns the complete message as string. This is called from
|
||||
within
|
||||
:meth:`~wuttjamaican.email.EmailHandler.deliver_message()` to
|
||||
obtain the SMTP payload.
|
||||
"""
|
||||
msg = None
|
||||
|
||||
if self.txt_body and self.html_body:
|
||||
txt = MIMEText(self.txt_body, _charset='utf_8')
|
||||
html = MIMEText(self.html_body, _subtype='html', _charset='utf_8')
|
||||
msg = MIMEMultipart(_subtype='alternative', _subparts=[txt, html])
|
||||
|
||||
elif self.txt_body:
|
||||
msg = MIMEText(self.txt_body, _charset='utf_8')
|
||||
|
||||
elif self.html_body:
|
||||
msg = MIMEText(self.html_body, 'html', _charset='utf_8')
|
||||
|
||||
if not msg:
|
||||
raise ValueError("message has no body parts")
|
||||
|
||||
msg['Subject'] = self.subject
|
||||
msg['From'] = self.sender
|
||||
|
||||
for addr in self.to:
|
||||
msg['To'] = addr
|
||||
for addr in self.cc:
|
||||
msg['Cc'] = addr
|
||||
for addr in self.bcc:
|
||||
msg['Bcc'] = addr
|
||||
|
||||
if self.replyto:
|
||||
msg.add_header('Reply-To', self.replyto)
|
||||
|
||||
return msg.as_string()
|
||||
|
||||
|
||||
class EmailHandler(GenericHandler):
|
||||
"""
|
||||
Base class and default implementation for the :term:`email
|
||||
|
@ -89,7 +220,7 @@ class EmailHandler(GenericHandler):
|
|||
This is the "raw" factory which is simply a wrapper around the
|
||||
class constructor. See also :meth:`make_auto_message()`.
|
||||
|
||||
:returns: :class:`~wuttjamaican.email.message.Message` object.
|
||||
:returns: :class:`~wuttjamaican.email.Message` object.
|
||||
"""
|
||||
return Message(**kwargs)
|
||||
|
||||
|
@ -112,7 +243,7 @@ class EmailHandler(GenericHandler):
|
|||
:param \**kwargs: Any remaining kwargs are passed as-is to
|
||||
:meth:`make_message()`. More on this below.
|
||||
|
||||
:returns: :class:`~wuttjamaican.email.message.Message` object.
|
||||
:returns: :class:`~wuttjamaican.email.Message` object.
|
||||
|
||||
This method may invoke some others, to gather the message
|
||||
attributes. Each will check config, or render a template, or
|
||||
|
@ -147,8 +278,8 @@ class EmailHandler(GenericHandler):
|
|||
def get_auto_sender(self, key):
|
||||
"""
|
||||
Returns automatic
|
||||
:attr:`~wuttjamaican.email.message.Message.sender` address for
|
||||
a message, as determined by config.
|
||||
:attr:`~wuttjamaican.email.Message.sender` address for a
|
||||
message, as determined by config.
|
||||
"""
|
||||
# prefer configured sender specific to key
|
||||
sender = self.config.get(f'{self.config.appname}.email.{key}.sender')
|
||||
|
@ -160,9 +291,8 @@ class EmailHandler(GenericHandler):
|
|||
|
||||
def get_auto_subject(self, key, context={}, rendered=True):
|
||||
"""
|
||||
Returns automatic
|
||||
:attr:`~wuttjamaican.email.message.Message.subject` line for a
|
||||
message, as determined by config.
|
||||
Returns automatic :attr:`~wuttjamaican.email.Message.subject`
|
||||
line for a message, as determined by config.
|
||||
|
||||
This calls :meth:`get_auto_subject_template()` and then
|
||||
renders the result using the given context.
|
||||
|
@ -200,25 +330,22 @@ class EmailHandler(GenericHandler):
|
|||
|
||||
def get_auto_to(self, key):
|
||||
"""
|
||||
Returns automatic
|
||||
:attr:`~wuttjamaican.email.message.Message.to` recipient
|
||||
address(es) for a message, as determined by config.
|
||||
Returns automatic :attr:`~wuttjamaican.email.Message.to`
|
||||
recipient address(es) for a message, as determined by config.
|
||||
"""
|
||||
return self.get_auto_recips(key, 'to')
|
||||
|
||||
def get_auto_cc(self, key):
|
||||
"""
|
||||
Returns automatic
|
||||
:attr:`~wuttjamaican.email.message.Message.cc` recipient
|
||||
address(es) for a message, as determined by config.
|
||||
Returns automatic :attr:`~wuttjamaican.email.Message.cc`
|
||||
recipient address(es) for a message, as determined by config.
|
||||
"""
|
||||
return self.get_auto_recips(key, 'cc')
|
||||
|
||||
def get_auto_bcc(self, key):
|
||||
"""
|
||||
Returns automatic
|
||||
:attr:`~wuttjamaican.email.message.Message.bcc` recipient
|
||||
address(es) for a message, as determined by config.
|
||||
Returns automatic :attr:`~wuttjamaican.email.Message.bcc`
|
||||
recipient address(es) for a message, as determined by config.
|
||||
"""
|
||||
return self.get_auto_recips(key, 'bcc')
|
||||
|
||||
|
@ -239,10 +366,9 @@ class EmailHandler(GenericHandler):
|
|||
|
||||
def get_auto_txt_body(self, key, context={}):
|
||||
"""
|
||||
Returns automatic
|
||||
:attr:`~wuttjamaican.email.message.Message.txt_body` content
|
||||
for a message, as determined by config. This renders a
|
||||
template with the given context.
|
||||
Returns automatic :attr:`~wuttjamaican.email.Message.txt_body`
|
||||
content for a message, as determined by config. This renders
|
||||
a template with the given context.
|
||||
"""
|
||||
template = self.get_auto_body_template(key, 'txt')
|
||||
if template:
|
||||
|
@ -251,9 +377,9 @@ class EmailHandler(GenericHandler):
|
|||
def get_auto_html_body(self, key, context={}):
|
||||
"""
|
||||
Returns automatic
|
||||
:attr:`~wuttjamaican.email.message.Message.html_body` content
|
||||
for a message, as determined by config. This renders a
|
||||
template with the given context.
|
||||
:attr:`~wuttjamaican.email.Message.html_body` content for a
|
||||
message, as determined by config. This renders a template
|
||||
with the given context.
|
||||
"""
|
||||
template = self.get_auto_body_template(key, 'html')
|
||||
if template:
|
||||
|
@ -327,10 +453,9 @@ class EmailHandler(GenericHandler):
|
|||
"""
|
||||
Deliver a message via SMTP smarthost.
|
||||
|
||||
:param message: Either a
|
||||
:class:`~wuttjamaican.email.message.Message` object or
|
||||
similar, or a string representing the complete message to
|
||||
be sent as-is.
|
||||
:param message: Either a :class:`~wuttjamaican.email.Message`
|
||||
object or similar, or a string representing the complete
|
||||
message to be sent as-is.
|
||||
|
||||
:param sender: Optional sender address to use for delivery.
|
||||
If not specified, will be read from ``message``.
|
||||
|
@ -339,10 +464,10 @@ class EmailHandler(GenericHandler):
|
|||
If not specified, will be read from ``message``.
|
||||
|
||||
A general rule here is that you can either provide a proper
|
||||
:class:`~wuttjamaican.email.message.Message` object, **or**
|
||||
you *must* provide ``sender`` and ``recips``. The logic is
|
||||
not smart enough (yet?) to parse sender/recips from a simple
|
||||
string message.
|
||||
:class:`~wuttjamaican.email.Message` object, **or** you *must*
|
||||
provide ``sender`` and ``recips``. The logic is not smart
|
||||
enough (yet?) to parse sender/recips from a simple string
|
||||
message.
|
||||
|
||||
Note also, this method does not (yet?) have robust error
|
||||
handling, so if an error occurs with the SMTP session, it will
|
|
@ -1,33 +0,0 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# WuttJamaican -- Base package for Wutta Framework
|
||||
# Copyright © 2023-2024 Lance Edgar
|
||||
#
|
||||
# This file is part of Wutta Framework.
|
||||
#
|
||||
# Wutta Framework is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option) any
|
||||
# later version.
|
||||
#
|
||||
# Wutta Framework is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Email Utilities
|
||||
|
||||
The following are available in this ``wuttjamaican.email`` namespace:
|
||||
|
||||
* :class:`~wuttjamaican.email.handler.EmailHandler`
|
||||
* :class:`~wuttjamaican.email.message.Message`
|
||||
"""
|
||||
|
||||
from .handler import EmailHandler
|
||||
from .message import Message
|
|
@ -1,158 +0,0 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# WuttJamaican -- Base package for Wutta Framework
|
||||
# Copyright © 2023-2024 Lance Edgar
|
||||
#
|
||||
# This file is part of Wutta Framework.
|
||||
#
|
||||
# Wutta Framework is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option) any
|
||||
# later version.
|
||||
#
|
||||
# Wutta Framework is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Wutta Framework. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Email Message
|
||||
"""
|
||||
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
|
||||
|
||||
class Message:
|
||||
"""
|
||||
Represents an email message to be sent.
|
||||
|
||||
:param to: Recipient(s) for the message. This may be either a
|
||||
string, or list of strings. If a string, it will be converted
|
||||
to a list since that is how the :attr:`to` attribute tracks it.
|
||||
Similar logic is used for :attr:`cc` and :attr:`bcc`.
|
||||
|
||||
All attributes shown below may also be specified via constructor.
|
||||
|
||||
.. attribute:: key
|
||||
|
||||
Unique key indicating the "type" of message. An "ad-hoc"
|
||||
message created arbitrarily may not have/need a key; however
|
||||
one created via
|
||||
:meth:`~wuttjamaican.email.handler.EmailHandler.make_auto_message()`
|
||||
will always have a key.
|
||||
|
||||
This key is not used for anything within the ``Message`` class
|
||||
logic. It is used by
|
||||
:meth:`~wuttjamaican.email.handler.EmailHandler.make_auto_message()`
|
||||
when constructing the message, and the key is set on the final
|
||||
message only as a reference.
|
||||
|
||||
.. attribute:: sender
|
||||
|
||||
Sender (``From:``) address for the message.
|
||||
|
||||
.. attribute:: subject
|
||||
|
||||
Subject text for the message.
|
||||
|
||||
.. attribute:: to
|
||||
|
||||
List of ``To:`` recipients for the message.
|
||||
|
||||
.. attribute:: cc
|
||||
|
||||
List of ``Cc:`` recipients for the message.
|
||||
|
||||
.. attribute:: bcc
|
||||
|
||||
List of ``Bcc:`` recipients for the message.
|
||||
|
||||
.. attribute:: replyto
|
||||
|
||||
Optional reply-to (``Reply-To:``) address for the message.
|
||||
|
||||
.. attribute:: txt_body
|
||||
|
||||
String with the ``text/plain`` body content.
|
||||
|
||||
.. attribute:: html_body
|
||||
|
||||
String with the ``text/html`` body content.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
key=None,
|
||||
sender=None,
|
||||
subject=None,
|
||||
to=None,
|
||||
cc=None,
|
||||
bcc=None,
|
||||
replyto=None,
|
||||
txt_body=None,
|
||||
html_body=None,
|
||||
):
|
||||
self.key = key
|
||||
self.sender = sender
|
||||
self.subject = subject
|
||||
self.set_recips('to', to)
|
||||
self.set_recips('cc', cc)
|
||||
self.set_recips('bcc', bcc)
|
||||
self.replyto = replyto
|
||||
self.txt_body = txt_body
|
||||
self.html_body = html_body
|
||||
|
||||
def set_recips(self, name, value):
|
||||
""" """
|
||||
if value:
|
||||
if isinstance(value, str):
|
||||
value = [value]
|
||||
if not isinstance(value, (list, tuple)):
|
||||
raise ValueError("must specify a string, tuple or list value")
|
||||
else:
|
||||
value = []
|
||||
setattr(self, name, list(value))
|
||||
|
||||
def as_string(self):
|
||||
"""
|
||||
Returns the complete message as string. This is called from
|
||||
within
|
||||
:meth:`~wuttjamaican.email.handler.EmailHandler.deliver_message()`
|
||||
to obtain the SMTP payload.
|
||||
"""
|
||||
msg = None
|
||||
|
||||
if self.txt_body and self.html_body:
|
||||
txt = MIMEText(self.txt_body, _charset='utf_8')
|
||||
html = MIMEText(self.html_body, _subtype='html', _charset='utf_8')
|
||||
msg = MIMEMultipart(_subtype='alternative', _subparts=[txt, html])
|
||||
|
||||
elif self.txt_body:
|
||||
msg = MIMEText(self.txt_body, _charset='utf_8')
|
||||
|
||||
elif self.html_body:
|
||||
msg = MIMEText(self.html_body, 'html', _charset='utf_8')
|
||||
|
||||
if not msg:
|
||||
raise ValueError("message has no body parts")
|
||||
|
||||
msg['Subject'] = self.subject
|
||||
msg['From'] = self.sender
|
||||
|
||||
for addr in self.to:
|
||||
msg['To'] = addr
|
||||
for addr in self.cc:
|
||||
msg['Cc'] = addr
|
||||
for addr in self.bcc:
|
||||
msg['Bcc'] = addr
|
||||
|
||||
if self.replyto:
|
||||
msg.add_header('Reply-To', self.replyto)
|
||||
|
||||
return msg.as_string()
|
|
@ -1,76 +0,0 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
|
||||
from unittest import TestCase
|
||||
|
||||
from wuttjamaican.email import message as mod
|
||||
|
||||
|
||||
class TestMessage(TestCase):
|
||||
|
||||
def make_message(self, **kwargs):
|
||||
return mod.Message(**kwargs)
|
||||
|
||||
def test_set_recips(self):
|
||||
msg = self.make_message()
|
||||
self.assertEqual(msg.to, [])
|
||||
|
||||
# set as list
|
||||
msg.set_recips('to', ['sally@example.com'])
|
||||
self.assertEqual(msg.to, ['sally@example.com'])
|
||||
|
||||
# set as tuple
|
||||
msg.set_recips('to', ('barney@example.com',))
|
||||
self.assertEqual(msg.to, ['barney@example.com'])
|
||||
|
||||
# set as string
|
||||
msg.set_recips('to', 'wilma@example.com')
|
||||
self.assertEqual(msg.to, ['wilma@example.com'])
|
||||
|
||||
# set as null
|
||||
msg.set_recips('to', None)
|
||||
self.assertEqual(msg.to, [])
|
||||
|
||||
# otherwise error
|
||||
self.assertRaises(ValueError, msg.set_recips, 'to', {'foo': 'foo@example.com'})
|
||||
|
||||
def test_as_string(self):
|
||||
|
||||
# error if no body
|
||||
msg = self.make_message()
|
||||
self.assertRaises(ValueError, msg.as_string)
|
||||
|
||||
# txt body
|
||||
msg = self.make_message(sender='bob@example.com',
|
||||
txt_body="hello world")
|
||||
complete = msg.as_string()
|
||||
self.assertIn('From: bob@example.com', complete)
|
||||
|
||||
# html body
|
||||
msg = self.make_message(sender='bob@example.com',
|
||||
html_body="<p>hello world</p>")
|
||||
complete = msg.as_string()
|
||||
self.assertIn('From: bob@example.com', complete)
|
||||
|
||||
# txt + html body
|
||||
msg = self.make_message(sender='bob@example.com',
|
||||
txt_body="hello world",
|
||||
html_body="<p>hello world</p>")
|
||||
complete = msg.as_string()
|
||||
self.assertIn('From: bob@example.com', complete)
|
||||
|
||||
# everything
|
||||
msg = self.make_message(sender='bob@example.com',
|
||||
subject='meeting follow-up',
|
||||
to='sally@example.com',
|
||||
cc='marketing@example.com',
|
||||
bcc='bob@example.com',
|
||||
replyto='sales@example.com',
|
||||
txt_body="hello world",
|
||||
html_body="<p>hello world</p>")
|
||||
complete = msg.as_string()
|
||||
self.assertIn('From: bob@example.com', complete)
|
||||
self.assertIn('Subject: meeting follow-up', complete)
|
||||
self.assertIn('To: sally@example.com', complete)
|
||||
self.assertIn('Cc: marketing@example.com', complete)
|
||||
self.assertIn('Bcc: bob@example.com', complete)
|
||||
self.assertIn('Reply-To: sales@example.com', complete)
|
|
@ -5,8 +5,7 @@ from unittest.mock import patch, MagicMock
|
|||
|
||||
import pytest
|
||||
|
||||
from wuttjamaican.email import handler as mod
|
||||
from wuttjamaican.email import Message
|
||||
from wuttjamaican import email as mod
|
||||
from wuttjamaican.conf import WuttaConfig
|
||||
from wuttjamaican.util import resource_path
|
||||
from wuttjamaican.exc import ConfigurationError
|
||||
|
@ -36,28 +35,28 @@ class TestEmailHandler(TestCase):
|
|||
|
||||
# provider may specify paths as list
|
||||
providers = {
|
||||
'wuttatest': MagicMock(email_templates=['wuttjamaican.email:templates']),
|
||||
'wuttatest': MagicMock(email_templates=['wuttjamaican:email-templates']),
|
||||
}
|
||||
with patch.object(self.app, 'providers', new=providers):
|
||||
handler = self.make_handler()
|
||||
path = resource_path('wuttjamaican.email:templates')
|
||||
path = resource_path('wuttjamaican:email-templates')
|
||||
self.assertEqual(handler.txt_templates.directories, [path])
|
||||
self.assertEqual(handler.html_templates.directories, [path])
|
||||
|
||||
# provider may specify paths as string
|
||||
providers = {
|
||||
'wuttatest': MagicMock(email_templates='wuttjamaican.email:templates'),
|
||||
'wuttatest': MagicMock(email_templates='wuttjamaican:email-templates'),
|
||||
}
|
||||
with patch.object(self.app, 'providers', new=providers):
|
||||
handler = self.make_handler()
|
||||
path = resource_path('wuttjamaican.email:templates')
|
||||
path = resource_path('wuttjamaican:email-templates')
|
||||
self.assertEqual(handler.txt_templates.directories, [path])
|
||||
self.assertEqual(handler.html_templates.directories, [path])
|
||||
|
||||
def test_make_message(self):
|
||||
handler = self.make_handler()
|
||||
msg = handler.make_message()
|
||||
self.assertIsInstance(msg, Message)
|
||||
self.assertIsInstance(msg, mod.Message)
|
||||
|
||||
def test_make_auto_message(self):
|
||||
handler = self.make_handler()
|
||||
|
@ -70,7 +69,7 @@ class TestEmailHandler(TestCase):
|
|||
|
||||
# message is empty by default
|
||||
msg = handler.make_auto_message('foo')
|
||||
self.assertIsInstance(msg, Message)
|
||||
self.assertIsInstance(msg, mod.Message)
|
||||
self.assertEqual(msg.key, 'foo')
|
||||
self.assertEqual(msg.sender, 'bob@example.com')
|
||||
self.assertEqual(msg.subject, "Automated message")
|
||||
|
@ -85,7 +84,7 @@ class TestEmailHandler(TestCase):
|
|||
# then we should get back a more complete message
|
||||
self.config.setdefault('wutta.email.test_foo.subject', "hello foo")
|
||||
self.config.setdefault('wutta.email.test_foo.to', 'sally@example.com')
|
||||
self.config.setdefault('wutta.email.templates', 'tests.email:templates')
|
||||
self.config.setdefault('wutta.email.templates', 'tests:email-templates')
|
||||
handler = self.make_handler()
|
||||
msg = handler.make_auto_message('test_foo')
|
||||
self.assertEqual(msg.key, 'test_foo')
|
||||
|
@ -240,7 +239,7 @@ class TestEmailHandler(TestCase):
|
|||
|
||||
# but returns a template if it exists
|
||||
providers = {
|
||||
'wuttatest': MagicMock(email_templates=['tests.email:templates']),
|
||||
'wuttatest': MagicMock(email_templates=['tests:email-templates']),
|
||||
}
|
||||
with patch.object(self.app, 'providers', new=providers):
|
||||
handler = self.make_handler()
|
||||
|
@ -257,7 +256,7 @@ class TestEmailHandler(TestCase):
|
|||
|
||||
# but returns body if template exists
|
||||
providers = {
|
||||
'wuttatest': MagicMock(email_templates=['tests.email:templates']),
|
||||
'wuttatest': MagicMock(email_templates=['tests:email-templates']),
|
||||
}
|
||||
with patch.object(self.app, 'providers', new=providers):
|
||||
handler = self.make_handler()
|
||||
|
@ -273,7 +272,7 @@ class TestEmailHandler(TestCase):
|
|||
|
||||
# but returns body if template exists
|
||||
providers = {
|
||||
'wuttatest': MagicMock(email_templates=['tests.email:templates']),
|
||||
'wuttatest': MagicMock(email_templates=['tests:email-templates']),
|
||||
}
|
||||
with patch.object(self.app, 'providers', new=providers):
|
||||
handler = self.make_handler()
|
||||
|
@ -456,3 +455,74 @@ class TestEmailHandler(TestCase):
|
|||
self.config.setdefault('wutta.email.default.enabled', False)
|
||||
handler.send_email('bar', sender='bar@example.com', txt_body="hello world")
|
||||
self.assertFalse(deliver_message.called)
|
||||
|
||||
|
||||
class TestMessage(TestCase):
|
||||
|
||||
def make_message(self, **kwargs):
|
||||
return mod.Message(**kwargs)
|
||||
|
||||
def test_set_recips(self):
|
||||
msg = self.make_message()
|
||||
self.assertEqual(msg.to, [])
|
||||
|
||||
# set as list
|
||||
msg.set_recips('to', ['sally@example.com'])
|
||||
self.assertEqual(msg.to, ['sally@example.com'])
|
||||
|
||||
# set as tuple
|
||||
msg.set_recips('to', ('barney@example.com',))
|
||||
self.assertEqual(msg.to, ['barney@example.com'])
|
||||
|
||||
# set as string
|
||||
msg.set_recips('to', 'wilma@example.com')
|
||||
self.assertEqual(msg.to, ['wilma@example.com'])
|
||||
|
||||
# set as null
|
||||
msg.set_recips('to', None)
|
||||
self.assertEqual(msg.to, [])
|
||||
|
||||
# otherwise error
|
||||
self.assertRaises(ValueError, msg.set_recips, 'to', {'foo': 'foo@example.com'})
|
||||
|
||||
def test_as_string(self):
|
||||
|
||||
# error if no body
|
||||
msg = self.make_message()
|
||||
self.assertRaises(ValueError, msg.as_string)
|
||||
|
||||
# txt body
|
||||
msg = self.make_message(sender='bob@example.com',
|
||||
txt_body="hello world")
|
||||
complete = msg.as_string()
|
||||
self.assertIn('From: bob@example.com', complete)
|
||||
|
||||
# html body
|
||||
msg = self.make_message(sender='bob@example.com',
|
||||
html_body="<p>hello world</p>")
|
||||
complete = msg.as_string()
|
||||
self.assertIn('From: bob@example.com', complete)
|
||||
|
||||
# txt + html body
|
||||
msg = self.make_message(sender='bob@example.com',
|
||||
txt_body="hello world",
|
||||
html_body="<p>hello world</p>")
|
||||
complete = msg.as_string()
|
||||
self.assertIn('From: bob@example.com', complete)
|
||||
|
||||
# everything
|
||||
msg = self.make_message(sender='bob@example.com',
|
||||
subject='meeting follow-up',
|
||||
to='sally@example.com',
|
||||
cc='marketing@example.com',
|
||||
bcc='bob@example.com',
|
||||
replyto='sales@example.com',
|
||||
txt_body="hello world",
|
||||
html_body="<p>hello world</p>")
|
||||
complete = msg.as_string()
|
||||
self.assertIn('From: bob@example.com', complete)
|
||||
self.assertIn('Subject: meeting follow-up', complete)
|
||||
self.assertIn('To: sally@example.com', complete)
|
||||
self.assertIn('Cc: marketing@example.com', complete)
|
||||
self.assertIn('Bcc: bob@example.com', complete)
|
||||
self.assertIn('Reply-To: sales@example.com', complete)
|
Loading…
Reference in a new issue