1"""
2This module is essentially a wrapper for Python's premailer and whatever the
3default mail transfer is (usually Postfix). Note that the premailer package
4(https://pypi.org/project/premailer/) is required for style embedding.
5
6This module provides the following methods:
7 - `mailprep`: embed CSS styles into inline HTML tags
8 - `sendmail`: send HTML or plaintext email using default mail handler
9"""
10
11import logging
12logger = logging.getLogger(__name__)
13
14from os.path import isfile
15import premailer
16from email.mime.text import MIMEText
17import subprocess
18
19
20def mailprep(htmlin, stylesheet):
21 """
22 Embed CSS styles from a file into inline HTML tags. Requires the premailer
23 package (https://pypi.org/project/premailer/).
24 """
25
26 logger.debug("Converting stylesheet " + stylesheet + " to inline tags")
27 if not isfile(stylesheet):
28 logger.warning("Cannot read stylesheet {}: file does not exist".format(stylesheet))
29 raise FileNotFoundError
30 pm = premailer.Premailer(htmlin, external_styles=stylesheet)
31 htmlout = pm.transform()
32 logger.info("Converted stylesheet to inline tags")
33 return htmlout
34
35
36def sendmail(mailbin, body, recipient, subject, html=True, sender=""):
37 """
38 Prepare and send an email in either HTML or plain text format. The default
39 MTA path is usually correct, but can be modified in the config option
40 "mailbin" in the [mail] section.
41 """
42
43 logger.debug("Sending email")
44 msg = MIMEText(body, 'html' if html else 'plain')
45 if sender:
46 msg["From"] = sender
47 msg["To"] = recipient
48 msg["Content-type"] = "text/html: te: text/html" if html else "text/plain: te: text/plain"
49 msg["Subject"] = subject
50 mailproc = subprocess.Popen([mailbin, "--debug-level=" + str(10 if logging.root.level == logging.DEBUG else 0), "-t"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
51 logger.debug("Compiled message and opened process")
52 try:
53 stdout = mailproc.communicate(msg.as_bytes(), timeout=15)
54 logger.debug("sendmail output: {}".format(stdout))
55 logger.info("Sent email to {0}".format(recipient))
56 return 0
57 except Exception as e:
58 mailproc.kill()
59 logger.warning("Failed to send message: {0}".format(str(e)))