Skip to content

Commit a2d6891

Browse files
committed
docs(email): add email backend document
1 parent 3cf2df0 commit a2d6891

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

utils/email/docs/email.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
## Overview
2+
This system supports **pluggable email backends** in Django, allowing dynamic switching between Email Backend:
3+
4+
5+
## Backend Selection
6+
- The email backend is controlled via environment variables:
7+
- **SMTP Backend (Development)**
8+
```env
9+
EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
10+
DEFAULT_FROM_EMAIL =<email>
11+
EMAIL_HOST=<host>
12+
EMAIL_PORT=<port>
13+
EMAIL_USE_TLS=False
14+
EMAIL_HOST_PASSWORD=<password>
15+
EMAIL_TO=<email>
16+
````
17+
- **Custom API Backend (Production)**
18+
```env
19+
EMAIL_BACKEND=utils.email.base.ApiEmailBackend
20+
EMAIL_API_URL=<API_ENDPOINT>
21+
EMAIL_API_KEY=<API_KEY>
22+
DEFAULT_FROM_EMAIL=<email>
23+
EMAIL_TO=<email>
24+
```
25+
26+
## High-Level Architecture
27+
```mermaid
28+
flowchart TD
29+
A["Django App<br/>(send_mail / EmailMessage)"]
30+
B["EMAIL_BACKEND<br/>(Configured via ENV)"]
31+
C["SMTP Backend"]
32+
D["Custom Email Backend"]
33+
A --> B
34+
B --> C
35+
B --> D
36+
```
37+
38+
## Custom Email Backend Components
39+
40+
- Base Email Backend (`EmailBackend`)
41+
- An abstract class extending Django’s `BaseEmailBackend`.
42+
- Manage HTTP session lifecycle (`open`, `close`)
43+
- Ensure thread safety using `threading.RLock`
44+
- Provide reusable utilities (e.g., Base64 encoding)
45+
46+
- Custom Email Backend (`ApiEmailBackend`)
47+
- Implementation of `EmailBackend` for a specific external email API.
48+
- Transform `EmailMessage` into API-compatible payload
49+
- Encode email fields using Base64
50+
- Support HTML and plain text email content
51+
- Handle API responses (success/failure)
52+
53+
**Key Methods**
54+
55+
| Method | Description |
56+
| ------------------- | -------------------------------------- |
57+
| `open()` | Initializes HTTP session |
58+
| `close()` | Closes HTTP session |
59+
| `send_messages()` | Sends batch of email messages |
60+
| `_send_message()` | Sends a single email |
61+
| `_build_headers()` | Constructs HTTP headers |
62+
| `_build_payload()` | Abstract method for payload generation |
63+
| `_handle_success()` | Handles successful response |
64+
| `_handle_failure()` | Handles failed response |
65+
66+
## Request Flow
67+
1. Django constructs an `EmailMessage`
68+
2. `send_messages()` is invoked by the backend
69+
3. A thread-safe session is initialized
70+
4. For each message:
71+
- `_build_headers()` prepares HTTP headers
72+
- `_build_payload()` converts message to API format
73+
- HTTP POST request is sent to the API endpoint
74+
5. Response handling:
75+
- Success → logged and counted
76+
- Failure → logged and optionally raises exception
77+
78+
## Header Construction
79+
Default headers
80+
```json
81+
{
82+
"Content-Type": "application/json"
83+
}
84+
```
85+
> Note: The current API does not support passing the API key via request headers Therefore, the API key is appended as a query parameter in the endpoint URL instead.
86+
87+
## Payload Format
88+
The email message is converted into a JSON payload:
89+
90+
```json
91+
{
92+
"FromAsBase64": "<encoded>",
93+
"ToAsBase64": "<encoded>",
94+
"CcAsBase64": "<encoded>",
95+
"BccAsBase64": "<encoded>",
96+
"SubjectAsBase64": "<encoded>",
97+
"BodyAsBase64": "<encoded>",
98+
"IsBodyHtml": true
99+
}
100+
```
101+
102+
## Thread Safety
103+
- A `threading.RLock` is used to ensure safe concurrent access
104+
- Prevents race conditions when multiple threads send emails
105+
- Ensures session reuse without corruption

0 commit comments

Comments
 (0)