|
3 | 3 | import os |
4 | 4 | from base64 import b64encode |
5 | 5 | from email.header import decode_header |
| 6 | +from email.message import EmailMessage |
6 | 7 | from email.mime.base import MIMEBase |
7 | 8 | from email.mime.multipart import MIMEMultipart |
8 | 9 | from email.mime.text import MIMEText |
@@ -76,15 +77,23 @@ def deconstruct_multipart_recursive(seen, text, html, attachments, message): |
76 | 77 | if message in seen: |
77 | 78 | return |
78 | 79 | seen.add(message) |
79 | | - if isinstance(message, MIMEMultipart): |
| 80 | + if message.is_multipart(): |
80 | 81 | for part in message.walk(): |
81 | 82 | deconstruct_multipart_recursive(seen, text, html, attachments, part) |
82 | 83 | else: |
83 | 84 | content_type = message.get_content_type() |
84 | 85 | if content_type == "text/plain" and not text: |
85 | | - text.append(message.get_payload(decode=True).decode("utf8")) |
| 86 | + # Use get_content() for EmailMessage, fall back to get_payload for MIME |
| 87 | + if isinstance(message, EmailMessage): |
| 88 | + text.append(message.get_content()) |
| 89 | + else: |
| 90 | + text.append(message.get_payload(decode=True).decode("utf8")) |
86 | 91 | elif content_type == "text/html" and not html: |
87 | | - html.append(message.get_payload(decode=True).decode("utf8")) |
| 92 | + # Use get_content() for EmailMessage, fall back to get_payload for MIME |
| 93 | + if isinstance(message, EmailMessage): |
| 94 | + html.append(message.get_content()) |
| 95 | + else: |
| 96 | + html.append(message.get_payload(decode=True).decode("utf8")) |
88 | 97 | else: |
89 | 98 | # Ignore underlying messages inside `message/rfc822` payload, because the message itself will be passed |
90 | 99 | # as an attachment |
@@ -285,7 +294,7 @@ def _construct_email(self, email, **extra): |
285 | 294 | """Converts incoming data to properly structured dictionary.""" |
286 | 295 | if isinstance(email, dict): |
287 | 296 | email = Email(manager=self._manager, **email) |
288 | | - elif isinstance(email, (MIMEText, MIMEMultipart)): |
| 297 | + elif isinstance(email, (EmailMessage, MIMEText, MIMEMultipart)): |
289 | 298 | email = Email.from_mime(email, self._manager) |
290 | 299 | elif not isinstance(email, Email): |
291 | 300 | raise ValueError |
@@ -348,7 +357,7 @@ def send( |
348 | 357 | ): |
349 | 358 | """Sends a single email. |
350 | 359 |
|
351 | | - :param message: :py:class:`Email` or ``email.mime.text.MIMEText`` instance. |
| 360 | + :param message: :py:class:`Email`, ``email.message.EmailMessage``, or ``email.mime.text.MIMEText`` instance. |
352 | 361 | :param str From: The sender email address. |
353 | 362 | :param To: Recipient's email address. |
354 | 363 | Multiple recipients could be specified as a list or string with comma separated values. |
@@ -391,10 +400,10 @@ def send( |
391 | 400 | Attachments=Attachments, |
392 | 401 | MessageStream=MessageStream, |
393 | 402 | ) |
394 | | - elif isinstance(message, (MIMEText, MIMEMultipart)): |
| 403 | + elif isinstance(message, (EmailMessage, MIMEText, MIMEMultipart)): |
395 | 404 | message = Email.from_mime(message, self) |
396 | 405 | elif not isinstance(message, Email): |
397 | | - raise TypeError("message should be either Email or MIMEText or MIMEMultipart instance") |
| 406 | + raise TypeError("message should be either Email, EmailMessage, MIMEText or MIMEMultipart instance") |
398 | 407 | return message.send() |
399 | 408 |
|
400 | 409 | def send_with_template( |
|
0 commit comments