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 """
|
""" Email client to forge and send emails """
|
||||||
|
|
||||||
|
import base64
|
||||||
import email.utils
|
import email.utils
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
@ -9,6 +10,7 @@ from email.mime.base import MIMEBase
|
||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
|
|
||||||
|
import magic
|
||||||
from mako.template import Template as MakoTemplate
|
from mako.template import Template as MakoTemplate
|
||||||
|
|
||||||
from mylib.config import (
|
from mylib.config import (
|
||||||
|
@ -22,6 +24,14 @@ from mylib.config import (
|
||||||
log = logging.getLogger(__name__)
|
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(
|
class EmailClient(
|
||||||
ConfigurableObject
|
ConfigurableObject
|
||||||
): # pylint: disable=useless-object-inheritance,too-many-instance-attributes
|
): # pylint: disable=useless-object-inheritance,too-many-instance-attributes
|
||||||
|
@ -165,7 +175,7 @@ class EmailClient(
|
||||||
continue
|
continue
|
||||||
template_type = "text" if template_type == ".txt" else template_type[1:]
|
template_type = "text" if template_type == ".txt" else template_type[1:]
|
||||||
if template_name not in self.templates:
|
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)
|
log.debug("Load email template %s %s from %s", template_name, template_type, filepath)
|
||||||
with open(filepath, encoding="utf8") as file_desc:
|
with open(filepath, encoding="utf8") as file_desc:
|
||||||
self.templates[template_name][template_type] = MakoTemplate(
|
self.templates[template_name][template_type] = MakoTemplate(
|
||||||
|
@ -239,6 +249,7 @@ class EmailClient(
|
||||||
msg["Date"] = email.utils.formatdate(None, True)
|
msg["Date"] = email.utils.formatdate(None, True)
|
||||||
encoding = encoding if encoding else self._get_option("encoding")
|
encoding = encoding if encoding else self._get_option("encoding")
|
||||||
if template:
|
if template:
|
||||||
|
log.debug("Forge email from template %s", template)
|
||||||
assert template in self.templates, f"Unknown template {template}"
|
assert template in self.templates, f"Unknown template {template}"
|
||||||
# Handle subject from template
|
# Handle subject from template
|
||||||
if not subject:
|
if not subject:
|
||||||
|
@ -264,6 +275,9 @@ class EmailClient(
|
||||||
)
|
)
|
||||||
if self.templates[template].get("html"):
|
if self.templates[template].get("html"):
|
||||||
if isinstance(self.templates[template]["html"], MakoTemplate):
|
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"))
|
parts.append((self.templates[template]["html"].render(**template_vars), "html"))
|
||||||
else:
|
else:
|
||||||
parts.append((self.templates[template]["html"].format(**template_vars), "html"))
|
parts.append((self.templates[template]["html"].format(**template_vars), "html"))
|
||||||
|
@ -296,6 +310,19 @@ class EmailClient(
|
||||||
msg.attach(part)
|
msg.attach(part)
|
||||||
return msg
|
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(
|
def send(
|
||||||
self, recipients, msg=None, subject=None, just_try=None, cc=None, bcc=None, **forge_args
|
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",
|
"-T",
|
||||||
"--template",
|
"--template",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
dest="template",
|
|
||||||
help="Template name to send (default: test)",
|
help="Template name to send (default: test)",
|
||||||
default="test",
|
default="test",
|
||||||
)
|
)
|
||||||
|
|
||||||
test_opts.add_argument(
|
|
||||||
"-m",
|
|
||||||
"--mako",
|
|
||||||
action="store_true",
|
|
||||||
dest="test_mako",
|
|
||||||
help="Test mako templating",
|
|
||||||
)
|
|
||||||
|
|
||||||
test_opts.add_argument(
|
test_opts.add_argument(
|
||||||
"--cc",
|
"--cc",
|
||||||
action="store",
|
action="store",
|
||||||
|
@ -93,7 +84,7 @@ def main(argv=None): # pylint: disable=too-many-locals,too-many-statements
|
||||||
options.test_to,
|
options.test_to,
|
||||||
cc=options.test_cc,
|
cc=options.test_cc,
|
||||||
bcc=options.test_bcc,
|
bcc=options.test_bcc,
|
||||||
template="test",
|
template=options.template,
|
||||||
sent_date=datetime.datetime.now(),
|
sent_date=datetime.datetime.now(),
|
||||||
):
|
):
|
||||||
log.info("Test email sent")
|
log.info("Test email sent")
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -22,6 +22,7 @@ extras_require = {
|
||||||
"pytz",
|
"pytz",
|
||||||
],
|
],
|
||||||
"email": [
|
"email": [
|
||||||
|
"python-magic",
|
||||||
"mako",
|
"mako",
|
||||||
],
|
],
|
||||||
"pgsql": [
|
"pgsql": [
|
||||||
|
|
Loading…
Reference in a new issue