Terarea  2
The automation project
Loading...
Searching...
No Matches
mail_management.py
Go to the documentation of this file.
1"""_summary_
2 The file in charge of managing the emissions of e-mails.
3"""
4
5import ssl
6import smtplib
7from typing import List
8from email import encoders
9from email.message import EmailMessage
10from email.utils import make_msgid
11from email.mime.base import MIMEBase
12from display_tty import Disp, TOML_CONF, FILE_DESCRIPTOR, SAVE_TO_FILE, FILE_NAME
13from . import constants as CONST
14
15
17 """_summary_
18 """
19
20 def __init__(self, error: int = 84, success: int = 0, debug: bool = False) -> None:
21 """_summary_
22 The class in charge of allowing the user to send e-mails.
23
24 Args:
25 error (int, optional): _description_. Defaults to 84.
26 success (int, optional): _description_. Defaults to 0.
27 debug (bool, optional): _description_. Defaults to False.
28 """
29 self.success = success
30 self.error = error
31 self.debug = debug
32
33 # ------------------------- email related data -------------------------
34 self.sender = CONST.SENDER_ADDRESS
35 self.host = CONST.SENDER_HOST
36 self.api_key = CONST.SENDER_KEY
37 self.port = CONST.SENDER_PORT
38
39 # ------------------------ The visual debugger ------------------------
40 self.disp: Disp = Disp(
41 TOML_CONF,
42 SAVE_TO_FILE,
43 FILE_NAME,
44 FILE_DESCRIPTOR,
45 debug=self.debug,
46 logger=self.__class__.__name__
47 )
48
49 def _send(self, em: EmailMessage) -> int:
50 """
51 Internal method to handle the actual sending of an email.
52
53 Args:
54 em (EmailMessage): The email message to be sent.
55
56 Returns:
57 int: The status of the email sending operation.
58 """
59 context = ssl.create_default_context()
60
61 try:
62 with smtplib.SMTP_SSL(self.host, self.port, context=context) as smtp:
63 smtp.login(self.sender, self.api_key)
64 smtp.send_message(em)
65 self.disp.log_debug("Email sent successfully", "_send")
66 return self.success
67 except Exception as e:
68 self.disp.log_critical(f"An error occurred: {e}", "_send")
69 return self.error
70
71 def send_email(self, receiver: str, subject: str, body: str, body_type: str = "html") -> int:
72 """
73 Sends a simple email to a single receiver.
74
75 Args:
76 receiver (str): The recipient's email address.
77 subject (str): The subject of the email.
78 body (str): The content of the email.
79 body_type (str, optional): The MIME type of the email content ('html' or 'plain'). Defaults to 'html'.
80
81 Returns:
82 int: The status of the email sending operation.
83 """
84 em = EmailMessage()
85 em['From'] = self.sender
86 em['To'] = receiver
87 em['Subject'] = subject
88
89 if body_type.lower() == "html":
90 em.add_alternative(body, subtype='html')
91 else:
92 em.set_content(body)
93
94 return self._send(em)
95
96 def send_email_with_attachment(self, receiver: str, subject: str, body: str, attachments: List[str], body_type: str = "html") -> int:
97 """
98 Sends an email with one or more attachments.
99
100 Args:
101 receiver (str): The recipient's email address.
102 subject (str): The subject of the email.
103 body (str): The content of the email.
104 attachments (List[str]): List of file paths for attachments.
105 body_type (str, optional): The MIME type of the email content ('html' or 'plain'). Defaults to 'html'.
106
107 Returns:
108 int: The status of the email sending operation.
109 """
110 em = EmailMessage()
111 em['From'] = self.sender
112 em['To'] = receiver
113 em['Subject'] = subject
114
115 if body_type == "html":
116 em.add_alternative(body, subtype='html')
117 else:
118 em.set_content(body)
119
120 for file in attachments:
121 try:
122 with open(file, 'rb') as f:
123 file_data = f.read()
124 file_name = file.split('/')[-1]
125
126 part = MIMEBase('application', 'octet-stream')
127 part.set_payload(file_data)
128 encoders.encode_base64(part)
129 part.add_header(
130 'Content-Disposition',
131 f'attachment; filename={file_name}'
132 )
133 em.add_attachment(
134 part.get_payload(decode=True),
135 maintype='application',
136 subtype='octet-stream',
137 filename=file_name
138 )
139
140 except Exception as e:
141 self.disp.log_critical(
142 f"Error reading attachment {file}: {e}",
143 "send_email_with_attachment"
144 )
145 return self.error
146
147 return self._send(em)
148
149 def send_email_to_multiple(self, receivers: List[str], subject: str, body: str, body_type: str = "html") -> int:
150 """
151 Sends an email to multiple recipients (To, Cc, or Bcc).
152
153 Args:
154 receivers (List[str]): A list of recipients' email addresses.
155 subject (str): The subject of the email.
156 body (str): The content of the email.
157 body_type (str, optional): The MIME type of the email content ('html' or 'plain'). Defaults to 'html'.
158
159 Returns:
160 int: The status of the email sending operation.
161 """
162 em = EmailMessage()
163 em['From'] = self.sender
164 em['To'] = ', '.join(receivers)
165 em['Subject'] = subject
166
167 if body_type == "html":
168 em.add_alternative(body, subtype='html')
169 else:
170 em.set_content(body)
171
172 return self._send(em)
173
174 def send_email_with_inline_image(self, receiver: str, subject: str, body: str, image_path: str, body_type: str = "html") -> int:
175 """
176 Sends an email with an inline image embedded in the body.
177
178 Args:
179 receiver (str): The recipient's email address.
180 subject (str): The subject of the email.
181 body (str): The content of the email, including a placeholder for the image.
182 image_path (str): The path to the image to be embedded.
183 body_type (str, optional): The MIME type of the email content ('html' or 'plain'). Defaults to 'html'.
184
185 Returns:
186 int: The status of the email sending operation.
187 """
188 em = EmailMessage()
189 em['From'] = self.sender
190 em['To'] = receiver
191 em['Subject'] = subject
192
193 if body_type == "html":
194 em.add_alternative(body, subtype='html')
195 else:
196 em.set_content(body)
197
198 try:
199 with open(image_path, 'rb') as img:
200 img_data = img.read()
201 img_cid = make_msgid()[1:-1]
202 em.add_related(
203 img_data,
204 maintype='image',
205 subtype='jpeg',
206 cid=img_cid
207 )
208 em.set_content(body.format(img_cid=img_cid))
209 except Exception as e:
210 self.disp.log_critical(
211 f"Error embedding inline image: {e}",
212 "send_email_with_inline_image"
213 )
214 return self.error
215
216 return self._send(em)
int send_email_with_inline_image(self, str receiver, str subject, str body, str image_path, str body_type="html")
int send_email(self, str receiver, str subject, str body, str body_type="html")
int send_email_with_attachment(self, str receiver, str subject, str body, List[str] attachments, str body_type="html")
int send_email_to_multiple(self, List[str] receivers, str subject, str body, str body_type="html")
None __init__(self, int error=84, int success=0, bool debug=False)