Coverage for chalicelib/utils/email_handler.py: 76%
72 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:56 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:56 +0000
1import logging
2import re
3from email.header import Header
4from email.mime.image import MIMEImage
5from email.mime.multipart import MIMEMultipart
6from email.mime.text import MIMEText
8from decouple import config
10from chalicelib.utils import smtp
12logger = logging.getLogger(__name__)
15def __get_html_from_file(source, formatting_variables):
16 if formatting_variables is None: 16 ↛ 17line 16 didn't jump to line 17 because the condition on line 16 was never true
17 formatting_variables = {}
18 formatting_variables["frontend_url"] = config("SITE_URL")
19 with open(source, "r") as body:
20 BODY_HTML = body.read()
21 if formatting_variables is not None and len(formatting_variables.keys()) > 0: 21 ↛ 24line 21 didn't jump to line 24
22 BODY_HTML = re.sub(r"%(?![(])", "%%", BODY_HTML)
23 BODY_HTML = BODY_HTML % {**formatting_variables}
24 return BODY_HTML
27def __replace_images(HTML):
28 pattern_holder = re.compile(r'<img[\w\W\n]+?(src="[a-zA-Z0-9.+\/\\-]+")')
29 pattern_src = re.compile(r'src="(.*?)"')
30 mime_img = []
31 swap = []
32 for m in re.finditer(pattern_holder, HTML):
33 sub = m.groups()[0]
34 sub = str(re.findall(pattern_src, sub)[0])
35 if sub not in swap: 35 ↛ 32line 35 didn't jump to line 32 because the condition on line 35 was always true
36 swap.append(sub)
37 cid = f"img-{len(mime_img)}"
38 HTML = HTML.replace(sub, f"cid:{cid}")
39 sub = "chalicelib/utils/html/" + sub
40 with open(sub, "rb") as image_file:
41 img_data = image_file.read()
42 mime_img.append(MIMEImage(img_data))
43 mime_img[-1].add_header('Content-ID', f'<{cid}>')
44 return HTML, mime_img
47def send_html(BODY_HTML, SUBJECT, recipient):
48 BODY_HTML, mime_img = __replace_images(BODY_HTML)
49 if not isinstance(recipient, list): 49 ↛ 51line 49 didn't jump to line 51 because the condition on line 49 was always true
50 recipient = [recipient]
51 msg = MIMEMultipart('related')
52 msg['Subject'] = Header(SUBJECT, 'utf-8')
53 msg['From'] = config("EMAIL_FROM")
55 body = MIMEText(BODY_HTML, 'html', "utf-8")
56 msg.attach(body)
57 for m in mime_img:
58 msg.attach(m)
60 with smtp.SMTPClient() as s:
61 for r in recipient:
62 msg["To"] = r
63 try:
64 logger.info(f"Email sending to: {r}")
65 s.send_message(msg)
66 except Exception as e:
67 logger.error("!!! Email error!")
68 logger.error(e)
71def send_text(recipients, text, subject):
72 with smtp.SMTPClient() as s:
73 msg = MIMEMultipart()
74 msg['Subject'] = Header(subject, 'utf-8')
75 msg['From'] = config("EMAIL_FROM")
76 msg['To'] = ", ".join(recipients)
77 body = MIMEText(text)
78 msg.attach(body)
79 try:
80 s.send_message(msg)
81 except Exception as e:
82 logger.error("!! Text-email failed: " + subject),
83 logger.error(e)
86def __escape_text_html(text):
87 return text.replace("@", "<span>@</span>").replace(".", "<span>.</span>").replace("=", "<span>=</span>")