1"""Base email backend class."""
2
3from abc import ABC, abstractmethod
4from typing import TYPE_CHECKING, Self
5
6if TYPE_CHECKING:
7 from types import TracebackType
8
9 from ..message import EmailMessage
10
11__all__ = ["BaseEmailBackend"]
12
13
14class BaseEmailBackend(ABC):
15 """
16 Base class for email backend implementations.
17
18 Subclasses must at least overwrite send_messages().
19
20 open() and close() can be called indirectly by using a backend object as a
21 context manager:
22
23 with backend as connection:
24 # do something with connection
25 pass
26 """
27
28 def open(self) -> bool:
29 """
30 Open a network connection.
31
32 This method can be overwritten by backend implementations to
33 open a network connection.
34
35 It's up to the backend implementation to track the status of
36 a network connection if it's needed by the backend.
37
38 This method can be called by applications to force a single
39 network connection to be used when sending mails. See the
40 send_messages() method of the SMTP backend for a reference
41 implementation.
42
43 The default implementation does nothing.
44 """
45 return False
46
47 def close(self) -> None:
48 """Close a network connection."""
49
50 def __enter__(self) -> Self:
51 try:
52 self.open()
53 except Exception:
54 self.close()
55 raise
56 return self
57
58 def __exit__(
59 self,
60 exc_type: type[BaseException] | None,
61 exc_value: BaseException | None,
62 traceback: TracebackType | None,
63 ) -> None:
64 self.close()
65
66 @abstractmethod
67 def send_messages(self, email_messages: list[EmailMessage]) -> int:
68 """
69 Send one or more EmailMessage objects and return the number of email
70 messages sent.
71 """
72 ...