plain.email 0.12.0__tar.gz → 0.13.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.
@@ -5,6 +5,8 @@
5
5
  __pycache__
6
6
  *.DS_Store
7
7
 
8
+ /*.code-workspace
9
+
8
10
  # Test apps
9
11
  plain*/tests/.plain
10
12
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plain.email
3
- Version: 0.12.0
3
+ Version: 0.13.0
4
4
  Summary: Everything you need to send email in Plain.
5
5
  Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
6
6
  License-Expression: BSD-3-Clause
@@ -1,5 +1,15 @@
1
1
  # plain-email changelog
2
2
 
3
+ ## [0.13.0](https://github.com/dropseed/plain/releases/plain-email@0.13.0) (2025-12-04)
4
+
5
+ ### What's changed
6
+
7
+ - Internal typing improvements for better type checker compatibility ([ac1eeb0](https://github.com/dropseed/plain/commit/ac1eeb0ea05b26dfc7e32c50f2a5a5bc7e098ceb))
8
+
9
+ ### Upgrade instructions
10
+
11
+ - No changes required
12
+
3
13
  ## [0.12.0](https://github.com/dropseed/plain/releases/plain-email@0.12.0) (2025-11-12)
4
14
 
5
15
  ### What's changed
@@ -28,7 +28,7 @@ class BaseEmailBackend(ABC):
28
28
  def __init__(self, fail_silently: bool = False, **kwargs: Any) -> None:
29
29
  self.fail_silently = fail_silently
30
30
 
31
- def open(self) -> None:
31
+ def open(self) -> bool | None:
32
32
  """
33
33
  Open a network connection.
34
34
 
@@ -23,9 +23,13 @@ class EmailBackend(BaseEmailBackend):
23
23
  def write_message(self, message: EmailMessage) -> None:
24
24
  msg = message.message()
25
25
  msg_data = msg.as_bytes()
26
- charset = (
27
- msg.get_charset().get_output_charset() if msg.get_charset() else "utf-8"
28
- )
26
+ msg_charset = msg.get_charset()
27
+ if msg_charset is None:
28
+ charset = "utf-8"
29
+ elif isinstance(msg_charset, str):
30
+ charset = msg_charset
31
+ else:
32
+ charset = msg_charset.get_output_charset() or "utf-8"
29
33
  msg_data = msg_data.decode(charset)
30
34
  self.stream.write(f"{msg_data}\n")
31
35
  self.stream.write("-" * 79)
@@ -16,17 +16,16 @@ if TYPE_CHECKING:
16
16
 
17
17
 
18
18
  class EmailBackend(ConsoleEmailBackend):
19
+ file_path: str # Set during __init__, validated to be non-None
20
+
19
21
  def __init__(self, *args: Any, file_path: str | None = None, **kwargs: Any) -> None:
20
- self._fname = None
21
- if file_path is not None:
22
- self.file_path = file_path
23
- else:
24
- self.file_path = getattr(settings, "EMAIL_FILE_PATH", None)
25
- if not self.file_path:
22
+ self._fname: str | None = None
23
+ _file_path: str | None = file_path or getattr(settings, "EMAIL_FILE_PATH", None)
24
+ if not _file_path:
26
25
  raise ImproperlyConfigured(
27
26
  "EMAIL_FILE_PATH must be set for the filebased email backend"
28
27
  )
29
- self.file_path = os.path.abspath(self.file_path)
28
+ self.file_path = os.path.abspath(_file_path)
30
29
  try:
31
30
  os.makedirs(self.file_path, exist_ok=True)
32
31
  except FileExistsError:
@@ -181,7 +181,7 @@ class SafeMIMEText(MIMEMixin, MIMEText):
181
181
  name, val = forbid_multi_line_headers(name, val, self.encoding)
182
182
  MIMEText.__setitem__(self, name, val)
183
183
 
184
- def set_payload(
184
+ def set_payload( # type: ignore[override]
185
185
  self, payload: str, charset: str | Charset.Charset | None = None
186
186
  ) -> None:
187
187
  if charset == "utf-8" and not isinstance(charset, Charset.Charset):
@@ -349,11 +349,10 @@ class EmailMessage:
349
349
  elif content is None:
350
350
  raise ValueError("content must be provided.")
351
351
  else:
352
- mimetype = (
353
- mimetype
354
- or mimetypes.guess_type(filename)[0]
355
- or DEFAULT_ATTACHMENT_MIME_TYPE
356
- )
352
+ if filename is not None and mimetype is None:
353
+ mimetype = mimetypes.guess_type(filename)[0]
354
+ if mimetype is None:
355
+ mimetype = DEFAULT_ATTACHMENT_MIME_TYPE
357
356
  basetype, subtype = mimetype.split("/", 1)
358
357
 
359
358
  if basetype == "text":
@@ -434,6 +433,7 @@ class EmailMessage:
434
433
  else:
435
434
  # Encode non-text attachments with base64.
436
435
  attachment = MIMEBase(basetype, subtype)
436
+ assert isinstance(content, bytes), "Non-text attachments must be bytes"
437
437
  attachment.set_payload(content)
438
438
  Encoders.encode_base64(attachment)
439
439
  return attachment
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "plain.email"
3
- version = "0.12.0"
3
+ version = "0.13.0"
4
4
  description = "Everything you need to send email in Plain."
5
5
  authors = [{name = "Dave Gaeddert", email = "dave.gaeddert@dropseed.dev"}]
6
6
  license = "BSD-3-Clause"
File without changes
File without changes