Skip to content

Commit

Permalink
Provides an option to send HTML emails
Browse files Browse the repository at this point in the history
  • Loading branch information
David Read committed Dec 20, 2019
1 parent f4cfe5e commit 3cd4345
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 8 deletions.
24 changes: 18 additions & 6 deletions ckan/lib/mailer.py
Expand Up @@ -6,6 +6,7 @@
import socket
import logging
from time import time
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.header import Header
from email import utils
Expand All @@ -30,14 +31,23 @@ class MailerException(Exception):

def _mail_recipient(recipient_name, recipient_email,
sender_name, sender_url, subject,
body, headers=None):
body, body_html=None, headers=None):

if not headers:
headers = {}

mail_from = config.get('smtp.mail_from')
reply_to = config.get('smtp.reply_to')
msg = MIMEText(body.encode('utf-8'), 'plain', 'utf-8')
if body_html:
# multipart
msg = MIMEMultipart('alternative')
part1 = MIMEText(body.encode('utf-8'), 'plain', 'utf-8')
part2 = MIMEText(body_html.encode('utf-8'), 'html', 'utf-8')
msg.attach(part1)
msg.attach(part2)
else:
# just plain text
msg = MIMEText(body.encode('utf-8'), 'plain', 'utf-8')
for k, v in headers.items():
if k in msg.keys():
msg.replace_header(k, v)
Expand Down Expand Up @@ -107,19 +117,21 @@ def _mail_recipient(recipient_name, recipient_email,


def mail_recipient(recipient_name, recipient_email, subject,
body, headers={}):
body, body_html=None, headers={}):
'''Sends an email'''
site_title = config.get('ckan.site_title')
site_url = config.get('ckan.site_url')
return _mail_recipient(recipient_name, recipient_email,
site_title, site_url, subject, body,
headers=headers)
body_html=body_html, headers=headers)


def mail_user(recipient, subject, body, headers={}):
def mail_user(recipient, subject, body, body_html=None, headers={}):
'''Sends an email to a CKAN user'''
if (recipient.email is None) or not len(recipient.email):
raise MailerException(_("No recipient email address available!"))
mail_recipient(recipient.display_name, recipient.email, subject,
body, headers=headers)
body, body_html=body_html, headers=headers)


def get_reset_link_body(user):
Expand Down
43 changes: 41 additions & 2 deletions ckan/tests/lib/test_mailer.py
Expand Up @@ -44,8 +44,8 @@ def teardown_class(cls):
def setup(self):
self.clear_smtp_messages()

def mime_encode(self, msg, recipient_name):
text = MIMEText(msg.encode("utf-8"), "plain", "utf-8")
def mime_encode(self, msg, recipient_name, subtype='plain'):
text = MIMEText(msg.encode("utf-8"), subtype, "utf-8")
encoded_body = text.get_payload().strip()
return encoded_body

Expand Down Expand Up @@ -84,11 +84,50 @@ def test_mail_recipient(self):
assert test_email["headers"].keys()[0] in msg[3], msg[3]
assert test_email["headers"].values()[0] in msg[3], msg[3]
assert test_email["subject"] in msg[3], msg[3]
assert msg[3].startswith('Content-Type: text/plain'), msg[3]
expected_body = self.mime_encode(
test_email["body"], test_email["recipient_name"]
)
assert expected_body in msg[3]

def test_mail_recipient_with_html(self):
user = factories.User()

msgs = self.get_smtp_messages()
assert msgs == []

# send email
test_email = {
"recipient_name": "Bob",
"recipient_email": user["email"],
"subject": "Meeting",
"body": "The meeting is cancelled.",
"body_html": "The <a href=\"meeting\">meeting</a> is cancelled.",
"headers": {"header1": "value1"},
}
mailer.mail_recipient(**test_email)

# check it went to the mock smtp server
msgs = self.get_smtp_messages()
assert len(msgs) == 1
msg = msgs[0]
assert msg[1] == config["smtp.mail_from"]
assert msg[2] == [test_email["recipient_email"]]
assert test_email["headers"].keys()[0] in msg[3], msg[3]
assert test_email["headers"].values()[0] in msg[3], msg[3]
assert test_email["subject"] in msg[3], msg[3]
assert msg[3].startswith('Content-Type: multipart'), msg[3]
expected_plain_body = self.mime_encode(
test_email["body"], test_email["recipient_name"],
subtype='plain'
)
assert expected_plain_body in msg[3]
expected_html_body = self.mime_encode(
test_email["body_html"], test_email["recipient_name"],
subtype='html'
)
assert expected_html_body in msg[3]

def test_mail_user(self):

user = factories.User()
Expand Down

0 comments on commit 3cd4345

Please sign in to comment.