Coverage for functions \ flipdare \ mailer \ core \ email_sanitizer.py: 96%
68 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
1#!/usr/bin/env python
2# Copyright (c) 2026 Flipdare Pty Ltd. All rights reserved.
3#
4# This file is part of Flipdare's proprietary software and contains
5# confidential and copyrighted material. Unauthorised copying,
6# modification, distribution, or use of this file is strictly
7# prohibited without prior written permission from Flipdare Pty Ltd.
8#
9# This software includes third-party components licensed under MIT,
10# BSD, and Apache 2.0 licences. See THIRD_PARTY_NOTICES for details.
11#
13from __future__ import annotations
15from typing import Any
16from datetime import datetime
17from flipdare.app_globals import is_valid_email, is_valid_url
18from flipdare.app_log import LOG
19from flipdare.app_types import ReportListType
20from flipdare.constants import IS_TRACE
21from flipdare.util.time_util import TimeUtil
23__all__ = ["EmailPreSanitizer"]
26class EmailPreSanitizer:
27 def __init__(self, data: ReportListType) -> None:
28 self.data = data
30 def format(self, is_html: bool = False) -> ReportListType:
31 data = self.data
33 formatted_data: ReportListType = []
34 for row in data:
35 formatted_row: list[Any] = []
36 for item in row:
37 if isinstance(item, datetime):
38 formatted_row.append(TimeUtil.formatted_user(item))
39 continue
40 if isinstance(item, (int, float)):
41 formatted_row.append(item)
42 continue
43 if not isinstance(item, str):
44 formatted_row.append(item)
45 continue
47 # if we get here we have a html string.
48 if not is_html:
49 formatted_row.append(item)
50 continue
52 is_web: bool = False
53 is_email: bool = False
54 if item.startswith(("http://", "https://", "www.")):
55 # we do a basic check first (for performance)
56 is_web = is_valid_url(item)
57 elif "@" in item:
58 # we do a basic check first (for performance)
59 is_email = is_valid_email(item).is_valid
61 if is_web:
62 formatted_row.append(f'<a href="{item}">{item}</a>')
63 elif is_email:
64 formatted_row.append(f'<a href="mailto:{item}">{item}</a>')
65 else:
66 formatted_row.append(item.replace("\n", "<br />\n"))
68 if IS_TRACE:
69 msg = f"Formatted:\n\tBefore={row}\n\tAfter={formatted_row}"
70 LOG().trace(msg)
72 formatted_data.append(formatted_row)
73 return formatted_data
76class EmailPostSanitizer:
77 # we need to add newline as well so we dont get
78 # (500, b'Line too long (see RFC5321 4.5.3.1.6)')
79 # errors when sending emails.
80 def __init__(self, data: str | list[str], headers: list[str] | None = None) -> None:
81 self.data = data
82 self.headers = headers
84 def format(self, is_html: bool = False) -> str:
85 data = self.data
87 result = ""
88 headers = self.headers
89 data = self.data
90 if isinstance(data, str):
91 data = [data]
93 for i in range(len(data)):
94 header = headers[i] if headers is not None and i < len(headers) else ""
95 if header != "":
96 header = f"<h1>{header}</h1>\n" if is_html else f"# {header}\n\n"
98 value = data[i]
99 if is_html:
100 value = value.replace("</tr>", "</tr>\n")
101 value = value.replace("<br />", "<br />\n")
103 sep = "<br />\n" if is_html else "\n"
104 result += f"{header}{sep}{value}\n" if header != "" else f"{value}\n"
105 return result