plain.email 0.11.1__tar.gz → 0.12.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {plain_email-0.11.1 → plain_email-0.12.0}/.gitignore +3 -3
- {plain_email-0.11.1 → plain_email-0.12.0}/PKG-INFO +1 -1
- {plain_email-0.11.1 → plain_email-0.12.0}/plain/email/CHANGELOG.md +11 -0
- {plain_email-0.11.1 → plain_email-0.12.0}/plain/email/backends/base.py +4 -4
- {plain_email-0.11.1 → plain_email-0.12.0}/plain/email/backends/filebased.py +5 -0
- {plain_email-0.11.1 → plain_email-0.12.0}/plain/email/backends/smtp.py +2 -1
- {plain_email-0.11.1 → plain_email-0.12.0}/plain/email/message.py +1 -1
- {plain_email-0.11.1 → plain_email-0.12.0}/pyproject.toml +1 -1
- {plain_email-0.11.1 → plain_email-0.12.0}/LICENSE +0 -0
- {plain_email-0.11.1 → plain_email-0.12.0}/README.md +0 -0
- {plain_email-0.11.1 → plain_email-0.12.0}/plain/email/README.md +0 -0
- {plain_email-0.11.1 → plain_email-0.12.0}/plain/email/__init__.py +0 -0
- {plain_email-0.11.1 → plain_email-0.12.0}/plain/email/backends/__init__.py +0 -0
- {plain_email-0.11.1 → plain_email-0.12.0}/plain/email/backends/console.py +0 -0
- {plain_email-0.11.1 → plain_email-0.12.0}/plain/email/default_settings.py +0 -0
- {plain_email-0.11.1 → plain_email-0.12.0}/plain/email/utils.py +0 -0
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# plain-email changelog
|
|
2
2
|
|
|
3
|
+
## [0.12.0](https://github.com/dropseed/plain/releases/plain-email@0.12.0) (2025-11-12)
|
|
4
|
+
|
|
5
|
+
### What's changed
|
|
6
|
+
|
|
7
|
+
- The filebased email backend now requires `EMAIL_FILE_PATH` to be set and raises `ImproperlyConfigured` if not provided ([f4dbcef](https://github.com/dropseed/plain/commit/f4dbcefa929058be517cb1d4ab35bd73a89f26b8))
|
|
8
|
+
- `BaseEmailBackend` now uses Python's abstract base class with `@abstractmethod` for better type checking ([245b5f4](https://github.com/dropseed/plain/commit/245b5f472c89178b8b764869f1624f8fc885b0f7))
|
|
9
|
+
|
|
10
|
+
### Upgrade instructions
|
|
11
|
+
|
|
12
|
+
- If using the filebased email backend, ensure `EMAIL_FILE_PATH` is configured in your settings or passed when initializing the backend
|
|
13
|
+
|
|
3
14
|
## [0.11.1](https://github.com/dropseed/plain/releases/plain-email@0.11.1) (2025-10-06)
|
|
4
15
|
|
|
5
16
|
### What's changed
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
5
6
|
from typing import TYPE_CHECKING, Any
|
|
6
7
|
|
|
7
8
|
if TYPE_CHECKING:
|
|
@@ -10,7 +11,7 @@ if TYPE_CHECKING:
|
|
|
10
11
|
from ..message import EmailMessage
|
|
11
12
|
|
|
12
13
|
|
|
13
|
-
class BaseEmailBackend:
|
|
14
|
+
class BaseEmailBackend(ABC):
|
|
14
15
|
"""
|
|
15
16
|
Base class for email backend implementations.
|
|
16
17
|
|
|
@@ -66,11 +67,10 @@ class BaseEmailBackend:
|
|
|
66
67
|
) -> None:
|
|
67
68
|
self.close()
|
|
68
69
|
|
|
70
|
+
@abstractmethod
|
|
69
71
|
def send_messages(self, email_messages: list[EmailMessage]) -> int:
|
|
70
72
|
"""
|
|
71
73
|
Send one or more EmailMessage objects and return the number of email
|
|
72
74
|
messages sent.
|
|
73
75
|
"""
|
|
74
|
-
|
|
75
|
-
"subclasses of BaseEmailBackend must override send_messages() method"
|
|
76
|
-
)
|
|
76
|
+
...
|
|
@@ -22,6 +22,10 @@ class EmailBackend(ConsoleEmailBackend):
|
|
|
22
22
|
self.file_path = file_path
|
|
23
23
|
else:
|
|
24
24
|
self.file_path = getattr(settings, "EMAIL_FILE_PATH", None)
|
|
25
|
+
if not self.file_path:
|
|
26
|
+
raise ImproperlyConfigured(
|
|
27
|
+
"EMAIL_FILE_PATH must be set for the filebased email backend"
|
|
28
|
+
)
|
|
25
29
|
self.file_path = os.path.abspath(self.file_path)
|
|
26
30
|
try:
|
|
27
31
|
os.makedirs(self.file_path, exist_ok=True)
|
|
@@ -45,6 +49,7 @@ class EmailBackend(ConsoleEmailBackend):
|
|
|
45
49
|
super().__init__(*args, **kwargs)
|
|
46
50
|
|
|
47
51
|
def write_message(self, message: EmailMessage) -> None:
|
|
52
|
+
assert self.stream is not None, "stream should be opened before writing"
|
|
48
53
|
self.stream.write(message.message().as_bytes() + b"\n")
|
|
49
54
|
self.stream.write(b"-" * 79)
|
|
50
55
|
self.stream.write(b"\n")
|
|
@@ -84,7 +84,7 @@ class EmailBackend(BaseEmailBackend):
|
|
|
84
84
|
|
|
85
85
|
# If local_hostname is not specified, socket.getfqdn() gets used.
|
|
86
86
|
# For performance, we use the cached FQDN for local_hostname.
|
|
87
|
-
connection_params = {"local_hostname": DNS_NAME.get_fqdn()}
|
|
87
|
+
connection_params: dict[str, Any] = {"local_hostname": DNS_NAME.get_fqdn()}
|
|
88
88
|
if self.timeout is not None:
|
|
89
89
|
connection_params["timeout"] = self.timeout
|
|
90
90
|
if self.use_ssl:
|
|
@@ -158,6 +158,7 @@ class EmailBackend(BaseEmailBackend):
|
|
|
158
158
|
sanitize_address(addr, encoding) for addr in email_message.recipients()
|
|
159
159
|
]
|
|
160
160
|
message = email_message.message()
|
|
161
|
+
assert self.connection is not None, "connection should be open before sending"
|
|
161
162
|
try:
|
|
162
163
|
self.connection.sendmail(
|
|
163
164
|
from_email, recipients, message.as_bytes(linesep="\r\n")
|
|
@@ -439,7 +439,7 @@ class EmailMessage:
|
|
|
439
439
|
return attachment
|
|
440
440
|
|
|
441
441
|
def _create_attachment(
|
|
442
|
-
self, filename: str | None, content: str | bytes, mimetype: str
|
|
442
|
+
self, filename: str | None, content: str | bytes, mimetype: str
|
|
443
443
|
) -> SafeMIMEText | SafeMIMEMessage | MIMEBase:
|
|
444
444
|
"""
|
|
445
445
|
Convert the filename, content, mimetype triple into a MIME attachment
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|