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