Coverage for src/email_message.py: 100%
44 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-10-16 04:41 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2025-10-16 04:41 +0000
1"""Email message module."""
3import time
4import uuid
5from email.mime.text import MIMEText
6from typing import Any
9class EmailMessage:
10 """
11 Email message class for creating and managing email messages.
13 This class handles the creation of email messages with proper formatting
14 and MIME structure for sending via SMTP.
15 """
17 def __init__(self, **kwargs: Any) -> None:
18 """
19 Initialize email message with provided parameters and defaults.
21 Args:
22 **kwargs: Email parameters including to, from, subject, body, etc.
23 """
24 params = self._process_email_parameters(kwargs)
26 self.to = params.get("to")
27 self.rto = params.get("rto")
28 self.cc = params.get("cc")
29 self.bcc = params.get("bcc")
30 self.sender = params.get("from")
31 self.subject = params.get("subject", "")
32 self.body = params.get("body")
33 self.html = params.get("html")
34 self.date = params.get("date", self._generate_default_date())
35 self.charset = params.get("charset", self._get_default_charset())
36 self.headers = params.get("headers", {})
38 self.message_id = self.make_key()
40 def _process_email_parameters(self, kwargs: dict[str, Any]) -> dict[str, Any]:
41 """
42 Process and normalize email parameters from kwargs.
44 This function handles the transformation of keyword arguments into
45 a normalized parameter dictionary for email message creation.
47 Args:
48 kwargs: Raw keyword arguments passed to constructor
50 Returns:
51 Dict containing processed email parameters
52 """
53 params = {}
54 for item in kwargs.items():
55 params[item[0]] = item[1]
56 return params
58 def _generate_default_date(self) -> str:
59 """
60 Generate default date string in RFC 2822 format.
62 Returns:
63 Formatted date string for email headers
64 """
65 return time.strftime("%a, %d %b %Y %H:%M:%S %z", time.gmtime())
67 def _get_default_charset(self) -> str:
68 """
69 Get default character encoding for email messages.
71 Returns:
72 Default charset string
73 """
74 return "us-ascii"
76 def make_key(self) -> str:
77 """
78 Generate unique message ID.
80 Creates a unique identifier for the email message using UUID4.
82 Returns:
83 Unique string identifier for the message
84 """
85 return str(uuid.uuid4())
87 def as_string(self) -> str:
88 """
89 Return plaintext email content as string.
91 This is the main public interface for getting the formatted email
92 message ready for sending via SMTP.
94 Returns:
95 Complete email message as formatted string
96 """
97 return self._plaintext()
99 def _plaintext(self) -> str:
100 """
101 Create plaintext email content and convert to string.
103 Orchestrates the creation of MIME message structure and conversion
104 to string format for email transmission.
106 Returns:
107 Formatted email message string
108 """
109 msg = self._create_mime_message()
110 self._set_info(msg)
111 return msg.as_string()
113 def _create_mime_message(self) -> MIMEText:
114 """
115 Create MIME text message object.
117 Handles the creation of the core MIME structure with proper
118 content and encoding.
120 Returns:
121 MIMEText object ready for header setting
122 """
123 # Handle None body by using empty string
124 body_text = self.body if self.body is not None else ""
125 return MIMEText(body_text, "plain", self.charset)
127 def _set_info(self, msg: MIMEText) -> None:
128 """
129 Set email header information on MIME message.
131 Configures the essential email headers (Subject, From, To, Date)
132 on the provided MIME message object. Handles None values gracefully.
134 Args:
135 msg: MIMEText object to configure with headers
136 """
137 msg["Subject"] = self.subject or ""
138 msg["From"] = self.sender or ""
139 msg["To"] = self.to or ""
140 msg["Date"] = self.date