email: add load_image_as_base64 helper function
This commit is contained in:
parent
384e8a441d
commit
4c51d0086f
5 changed files with 94 additions and 12 deletions
|
@ -1,5 +1,6 @@
|
|||
""" Email client to forge and send emails """
|
||||
|
||||
import base64
|
||||
import email.utils
|
||||
import logging
|
||||
import os
|
||||
|
@ -9,6 +10,7 @@ from email.mime.base import MIMEBase
|
|||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
|
||||
import magic
|
||||
from mako.template import Template as MakoTemplate
|
||||
|
||||
from mylib.config import (
|
||||
|
@ -22,6 +24,14 @@ from mylib.config import (
|
|||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def load_image_as_base64(path):
|
||||
"""Load image file as base64"""
|
||||
log.debug("Load image file '%s'", path)
|
||||
with open(path, "rb") as file_desc:
|
||||
data = file_desc.read()
|
||||
return f"data:{magic.from_buffer(data, mime=True)};base64, {base64.b64encode(data).decode()}"
|
||||
|
||||
|
||||
class EmailClient(
|
||||
ConfigurableObject
|
||||
): # pylint: disable=useless-object-inheritance,too-many-instance-attributes
|
||||
|
@ -165,7 +175,7 @@ class EmailClient(
|
|||
continue
|
||||
template_type = "text" if template_type == ".txt" else template_type[1:]
|
||||
if template_name not in self.templates:
|
||||
self.templates[template_name] = {}
|
||||
self.templates[template_name] = {"path": templates_path}
|
||||
log.debug("Load email template %s %s from %s", template_name, template_type, filepath)
|
||||
with open(filepath, encoding="utf8") as file_desc:
|
||||
self.templates[template_name][template_type] = MakoTemplate(
|
||||
|
@ -239,6 +249,7 @@ class EmailClient(
|
|||
msg["Date"] = email.utils.formatdate(None, True)
|
||||
encoding = encoding if encoding else self._get_option("encoding")
|
||||
if template:
|
||||
log.debug("Forge email from template %s", template)
|
||||
assert template in self.templates, f"Unknown template {template}"
|
||||
# Handle subject from template
|
||||
if not subject:
|
||||
|
@ -264,6 +275,9 @@ class EmailClient(
|
|||
)
|
||||
if self.templates[template].get("html"):
|
||||
if isinstance(self.templates[template]["html"], MakoTemplate):
|
||||
template_vars["load_image_as_base64"] = self.template_image_loader(
|
||||
self.templates[template].get("path")
|
||||
)
|
||||
parts.append((self.templates[template]["html"].render(**template_vars), "html"))
|
||||
else:
|
||||
parts.append((self.templates[template]["html"].format(**template_vars), "html"))
|
||||
|
@ -296,6 +310,19 @@ class EmailClient(
|
|||
msg.attach(part)
|
||||
return msg
|
||||
|
||||
@staticmethod
|
||||
def template_image_loader(directory_path):
|
||||
"""Return wrapper for the load_image_as_base64 function bind on the template directory"""
|
||||
|
||||
def _load_image_as_base64(path):
|
||||
return load_image_as_base64(
|
||||
os.path.join(directory_path, path)
|
||||
if directory_path and not os.path.isabs(path)
|
||||
else path
|
||||
)
|
||||
|
||||
return _load_image_as_base64
|
||||
|
||||
def send(
|
||||
self, recipients, msg=None, subject=None, just_try=None, cc=None, bcc=None, **forge_args
|
||||
):
|
||||
|
|
62
mylib/scripts/email_templates/header.svg
Normal file
62
mylib/scripts/email_templates/header.svg
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="92.738403mm"
|
||||
height="17.141003mm"
|
||||
viewBox="0 0 92.738403 17.141003"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
sodipodi:docname="header.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.84096521"
|
||||
inkscape:cx="92.156012"
|
||||
inkscape:cy="315.11411"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1011"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
inkscape:label="Calque 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-44.730637,-68.858589)">
|
||||
<rect
|
||||
style="fill:none;stroke:#004787;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="rect234"
|
||||
width="90.738403"
|
||||
height="15.141003"
|
||||
x="45.730637"
|
||||
y="69.858589" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.29167px;line-height:125%;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="82.664459"
|
||||
y="79.623909"
|
||||
id="text2144"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2142"
|
||||
style="fill:#004787;fill-opacity:1;stroke-width:0.264583px"
|
||||
x="82.664459"
|
||||
y="79.623909">Header</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
|
@ -1 +1,2 @@
|
|||
<strong>Just a test email.</strong> <small>(sent at ${sent_date})</small>
|
||||
<img src="${load_image_as_base64('header.svg')}" style="display: block" />
|
||||
<p><strong>Just a test email.</strong> <small>(sent at ${sent_date})</small></p>
|
||||
|
|
|
@ -38,19 +38,10 @@ def main(argv=None): # pylint: disable=too-many-locals,too-many-statements
|
|||
"-T",
|
||||
"--template",
|
||||
action="store_true",
|
||||
dest="template",
|
||||
help="Template name to send (default: test)",
|
||||
default="test",
|
||||
)
|
||||
|
||||
test_opts.add_argument(
|
||||
"-m",
|
||||
"--mako",
|
||||
action="store_true",
|
||||
dest="test_mako",
|
||||
help="Test mako templating",
|
||||
)
|
||||
|
||||
test_opts.add_argument(
|
||||
"--cc",
|
||||
action="store",
|
||||
|
@ -93,7 +84,7 @@ def main(argv=None): # pylint: disable=too-many-locals,too-many-statements
|
|||
options.test_to,
|
||||
cc=options.test_cc,
|
||||
bcc=options.test_bcc,
|
||||
template="test",
|
||||
template=options.template,
|
||||
sent_date=datetime.datetime.now(),
|
||||
):
|
||||
log.info("Test email sent")
|
||||
|
|
1
setup.py
1
setup.py
|
@ -22,6 +22,7 @@ extras_require = {
|
|||
"pytz",
|
||||
],
|
||||
"email": [
|
||||
"python-magic",
|
||||
"mako",
|
||||
],
|
||||
"pgsql": [
|
||||
|
|
Loading…
Reference in a new issue