sendgrid-email-service 0.0.1__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.
Files changed (29) hide show
  1. sendgrid_email_service-0.0.1/LICENSE +21 -0
  2. sendgrid_email_service-0.0.1/PKG-INFO +338 -0
  3. sendgrid_email_service-0.0.1/README.md +302 -0
  4. sendgrid_email_service-0.0.1/pyproject.toml +65 -0
  5. sendgrid_email_service-0.0.1/setup.cfg +4 -0
  6. sendgrid_email_service-0.0.1/src/sendgrid_email_service/__init__.py +51 -0
  7. sendgrid_email_service-0.0.1/src/sendgrid_email_service/client.py +103 -0
  8. sendgrid_email_service-0.0.1/src/sendgrid_email_service/config.py +141 -0
  9. sendgrid_email_service-0.0.1/src/sendgrid_email_service/exceptions.py +103 -0
  10. sendgrid_email_service-0.0.1/src/sendgrid_email_service/models.py +80 -0
  11. sendgrid_email_service-0.0.1/src/sendgrid_email_service/py.typed +1 -0
  12. sendgrid_email_service-0.0.1/src/sendgrid_email_service/template/renderer.py +128 -0
  13. sendgrid_email_service-0.0.1/src/sendgrid_email_service/templates/reset_password.html +220 -0
  14. sendgrid_email_service-0.0.1/src/sendgrid_email_service/templates/verify_account.html +197 -0
  15. sendgrid_email_service-0.0.1/src/sendgrid_email_service/templates/welcome.html +177 -0
  16. sendgrid_email_service-0.0.1/src/sendgrid_email_service/transport/__init__.py +0 -0
  17. sendgrid_email_service-0.0.1/src/sendgrid_email_service/transport/smtp.py +205 -0
  18. sendgrid_email_service-0.0.1/src/sendgrid_email_service.egg-info/PKG-INFO +338 -0
  19. sendgrid_email_service-0.0.1/src/sendgrid_email_service.egg-info/SOURCES.txt +27 -0
  20. sendgrid_email_service-0.0.1/src/sendgrid_email_service.egg-info/dependency_links.txt +1 -0
  21. sendgrid_email_service-0.0.1/src/sendgrid_email_service.egg-info/requires.txt +8 -0
  22. sendgrid_email_service-0.0.1/src/sendgrid_email_service.egg-info/top_level.txt +1 -0
  23. sendgrid_email_service-0.0.1/tests/test_client.py +80 -0
  24. sendgrid_email_service-0.0.1/tests/test_config.py +116 -0
  25. sendgrid_email_service-0.0.1/tests/test_logging.py +60 -0
  26. sendgrid_email_service-0.0.1/tests/test_models.py +66 -0
  27. sendgrid_email_service-0.0.1/tests/test_packaging.py +44 -0
  28. sendgrid_email_service-0.0.1/tests/test_template.py +80 -0
  29. sendgrid_email_service-0.0.1/tests/test_transport.py +163 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FireCompass
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,338 @@
1
+ Metadata-Version: 2.4
2
+ Name: sendgrid-email-service
3
+ Version: 0.0.1
4
+ Summary: A modern Python SDK for sending transactional and marketing emails via SMTP with Jinja2 templates, structured logging, and robust error handling.
5
+ Author-email: Abhay Kumar Gupta <abhayguptaak39@gmail.com>
6
+ Maintainer-email: Abhay Kumar Gupta <abhayguptaak39@gmail.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/abhay39/sendgrid-stmp-email-service
9
+ Project-URL: Repository, https://github.com/abhay39/sendgrid-stmp-email-service
10
+ Project-URL: Issues, https://github.com/abhay39/sendgrid-stmp-email-service/issues
11
+ Keywords: email,smtp,sendgrid,templates,jinja2,mailer,sdk,transactional-email
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Communications :: Email
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.9
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: Jinja2<4.0.0,>=3.1.0
29
+ Requires-Dist: python-dotenv<2.0.0,>=1.0.0
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
32
+ Requires-Dist: pytest-mock>=3.12.0; extra == "dev"
33
+ Requires-Dist: build>=1.0.0; extra == "dev"
34
+ Requires-Dist: twine>=5.0.0; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ # sendgrid-email-service
38
+
39
+ [![PyPI version](https://img.shields.io/pypi/v/sendgrid-email-service.svg)](https://pypi.org/project/sendgrid-email-service/)
40
+ [![Python Versions](https://img.shields.io/pypi/pyversions/sendgrid-email-service.svg)](https://pypi.org/project/sendgrid-email-service/)
41
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
42
+ [![Type Checked: typed](https://img.shields.io/badge/typing-typed-blue.svg)](https://www.python.org/dev/peps/pep-0561/)
43
+
44
+ A modern, production-ready Python SDK for sending transactional and marketing emails via SMTP (including SendGrid SMTP relays) with built-in Jinja2 templating, structured logging, secure credential handling, and comprehensive exception management.
45
+
46
+ ---
47
+
48
+ ## Features
49
+
50
+ - 🚀 **Production-Grade Delivery**: Reliable SMTP transport supporting TLS encryption, authentication, and timeouts.
51
+ - 🎨 **Built-in & Custom Jinja2 Templates**: Comes with responsive pre-built templates (`welcome`, `reset_password`, `verify_account`) and allows custom template directories.
52
+ - 🪵 **Enterprise Logging**: PEP 282 compliant logging with `NullHandler` by default, granular log levels (`DEBUG`, `INFO`, `ERROR`), and automatic password masking.
53
+ - 🛡️ **Comprehensive Exception Hierarchy**: Clear, actionable exceptions for validation, templates, authentication, connection timeouts, and delivery errors.
54
+ - ⚙️ **Flexible Configuration**: Seamlessly configure via `.env` files, environment variables, or typed `EmailConfig` objects.
55
+ - 📦 **PEP 561 Compliant**: Fully typed (`py.typed`) for autocomplete and static analysis with MyPy and IDEs.
56
+
57
+ ---
58
+
59
+ ## Installation
60
+
61
+ Install via `pip`:
62
+
63
+ ```bash
64
+ pip install sendgrid-email-service
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Quick Start
70
+
71
+ ### 1. Environment Configuration
72
+
73
+ Create a `.env` file in your project root or set environment variables:
74
+
75
+ ```ini
76
+ # SMTP Configuration (SendGrid, Mailpit, Amazon SES, or custom SMTP)
77
+ EMAIL_SMTP_HOST=smtp.sendgrid.net
78
+ EMAIL_SMTP_PORT=587
79
+ EMAIL_SMTP_USERNAME=apikey
80
+ EMAIL_SMTP_PASSWORD=your-sendgrid-api-key
81
+
82
+ # Sender Defaults
83
+ EMAIL_FROM=notifications@yourdomain.com
84
+ EMAIL_FROM_NAME=Your Company
85
+
86
+ # Optional Settings
87
+ EMAIL_USE_TLS=true
88
+ EMAIL_TIMEOUT=30
89
+ ```
90
+
91
+ ### 2. Send Plain Text or HTML Email
92
+
93
+ ```python
94
+ from sendgrid_email_service import EmailClient
95
+
96
+ # Automatically loads configuration from .env / environment variables
97
+ client = EmailClient()
98
+
99
+ # Send a simple email
100
+ client.send(
101
+ to="recipient@example.com",
102
+ subject="Welcome to Our Platform",
103
+ body="Hello! Thank you for joining us.",
104
+ )
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Working with Templates
110
+
111
+ `sendgrid-email-service` includes responsive, production-ready HTML templates out of the box.
112
+
113
+ ### Built-in Templates
114
+
115
+ | Template Name | Description | Available Context Variables |
116
+ | :--- | :--- | :--- |
117
+ | `welcome` | Onboarding & welcome message | `name`, `company_name`, `action_url`, `year` |
118
+ | `reset_password` | Password recovery with secure action button | `name`, `reset_url`, `company_name`, `expiry_hours`, `support_email`, `year` |
119
+ | `verify_account` | Email verification & activation link | `name`, `verification_url`, `company_name`, `expiry_hours`, `support_email`, `year` |
120
+
121
+ ### Example: Sending a Template Email
122
+
123
+ ```python
124
+ from sendgrid_email_service import EmailClient
125
+
126
+ client = EmailClient()
127
+
128
+ client.send(
129
+ to="user@example.com",
130
+ subject="Welcome to FireCompass!",
131
+ template="welcome",
132
+ data={
133
+ "name": "Jane Doe",
134
+ "company_name": "FireCompass",
135
+ "action_url": "https://app.firecompass.com/dashboard",
136
+ "year": 2026,
137
+ },
138
+ )
139
+ ```
140
+
141
+ ### Example: Using Custom Templates
142
+
143
+ You can point `EmailClient` to your own Jinja2 template directory:
144
+
145
+ ```python
146
+ from pathlib import Path
147
+ from sendgrid_email_service import EmailClient
148
+
149
+ client = EmailClient(template_directory=Path("./my_custom_templates"))
150
+
151
+ client.send(
152
+ to="customer@example.com",
153
+ subject="Your Invoice is Ready",
154
+ template="monthly_invoice", # Looks for monthly_invoice.html in ./my_custom_templates
155
+ data={
156
+ "customer_name": "Acme Corp",
157
+ "invoice_number": "INV-2026-001",
158
+ "amount_due": "$149.00",
159
+ },
160
+ )
161
+ ```
162
+
163
+ ---
164
+
165
+ ## Programmatic Configuration
166
+
167
+ Instead of environment variables, you can configure the client directly using `EmailConfig`:
168
+
169
+ ```python
170
+ from sendgrid_email_service import EmailClient, EmailConfig
171
+
172
+ config = EmailConfig(
173
+ smtp_host="smtp.sendgrid.net",
174
+ smtp_port=587,
175
+ smtp_username="apikey",
176
+ smtp_password="your-api-key-here",
177
+ from_email="no-reply@company.com",
178
+ from_name="My Company",
179
+ use_tls=True,
180
+ timeout=30,
181
+ )
182
+
183
+ client = EmailClient(config=config)
184
+ ```
185
+
186
+ ---
187
+
188
+ ## Exception Handling
189
+
190
+ The SDK provides a clean exception hierarchy inheriting from `EmailError`:
191
+
192
+ ```
193
+ EmailError (Base)
194
+ ├── EmailConfigurationError
195
+ ├── EmailValidationError
196
+ ├── EmailTemplateError
197
+ └── EmailSendError
198
+ ├── EmailConnectionError
199
+ ├── EmailAuthenticationError
200
+ ├── EmailTimeoutError
201
+ └── EmailRecipientsRefusedError
202
+ ```
203
+
204
+ ### Example: Robust Error Handling
205
+
206
+ ```python
207
+ import logging
208
+ from sendgrid_email_service import (
209
+ EmailClient,
210
+ EmailAuthenticationError,
211
+ EmailConnectionError,
212
+ EmailRecipientsRefusedError,
213
+ EmailTimeoutError,
214
+ EmailValidationError,
215
+ EmailTemplateError,
216
+ EmailSendError,
217
+ EmailError,
218
+ )
219
+
220
+ client = EmailClient()
221
+
222
+ try:
223
+ client.send(
224
+ to="client@example.com",
225
+ subject="Important Update",
226
+ template="welcome",
227
+ data={"name": "Alice", "company_name": "Acme Inc."},
228
+ )
229
+
230
+ except EmailValidationError as e:
231
+ print(f"Invalid email input on field '{e.field}': {e}")
232
+
233
+ except EmailTemplateError as e:
234
+ print(f"Template error ({e.template_name}): {e}")
235
+
236
+ except EmailAuthenticationError as e:
237
+ print(f"SMTP Auth failure for user '{e.username}': {e}")
238
+
239
+ except EmailConnectionError as e:
240
+ print(f"Could not connect to SMTP server ({e.host}:{e.port}): {e}")
241
+
242
+ except EmailTimeoutError as e:
243
+ print(f"Operation timed out after {e.timeout}s: {e}")
244
+
245
+ except EmailRecipientsRefusedError as e:
246
+ print(f"Server refused recipients {e.recipients}: {e}")
247
+
248
+ except EmailSendError as e:
249
+ print(f"Failed to send email: {e}")
250
+
251
+ except EmailError as e:
252
+ print(f"General email SDK error: {e}")
253
+ ```
254
+
255
+ ---
256
+
257
+ ## Logging Configuration
258
+
259
+ `sendgrid-email-service` adheres to Python library best practices (PEP 282). By default, it emits no logs unless your application configures logging.
260
+
261
+ ### Example: Enabling Logs in Your Application
262
+
263
+ ```python
264
+ import logging
265
+ import sys
266
+
267
+ # Configure root or package logger
268
+ logging.basicConfig(
269
+ level=logging.INFO,
270
+ format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
271
+ handlers=[logging.StreamHandler(sys.stdout)],
272
+ )
273
+
274
+ # Enable DEBUG logging specifically for sendgrid_email_service
275
+ logging.getLogger("sendgrid_email_service").setLevel(logging.DEBUG)
276
+ ```
277
+
278
+ > **Security Guarantee**: Passwords and sensitive credentials are automatically masked (e.g. `***`) and are never written to log files.
279
+
280
+ ---
281
+
282
+ ## Local Development with Mailpit
283
+
284
+ You can test email sending locally using [Mailpit](https://github.com/axllent/mailpit) included via Docker Compose:
285
+
286
+ 1. Start Mailpit:
287
+ ```bash
288
+ docker compose up -d
289
+ ```
290
+ 2. Set `.env` to point to localhost:
291
+ ```ini
292
+ EMAIL_SMTP_HOST=localhost
293
+ EMAIL_SMTP_PORT=1025
294
+ EMAIL_USE_TLS=false
295
+ ```
296
+ 3. View sent emails in your browser at `http://localhost:8025`.
297
+
298
+ ---
299
+
300
+ ## Running Tests
301
+
302
+ Install dev dependencies and run `pytest`:
303
+
304
+ ```bash
305
+ pip install -e ".[dev]"
306
+ pytest tests/ -v
307
+ ```
308
+
309
+ ---
310
+
311
+ ## Publishing to PyPI
312
+
313
+ 1. **Build distribution archives**:
314
+ ```bash
315
+ python -m build
316
+ ```
317
+
318
+ 2. **Verify archives with Twine**:
319
+ ```bash
320
+ twine check dist/*
321
+ ```
322
+
323
+ 3. **Upload to TestPyPI** (Optional):
324
+ ```bash
325
+ twine upload --repository testpypi dist/*
326
+ ```
327
+
328
+ 4. **Upload to PyPI**:
329
+ ```bash
330
+ twine upload dist/*
331
+ ```
332
+
333
+ ---
334
+
335
+ ## License
336
+
337
+ Distributed under the [MIT License](LICENSE).
338
+ # sendgrid-stmp-email-service
@@ -0,0 +1,302 @@
1
+ # sendgrid-email-service
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/sendgrid-email-service.svg)](https://pypi.org/project/sendgrid-email-service/)
4
+ [![Python Versions](https://img.shields.io/pypi/pyversions/sendgrid-email-service.svg)](https://pypi.org/project/sendgrid-email-service/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
+ [![Type Checked: typed](https://img.shields.io/badge/typing-typed-blue.svg)](https://www.python.org/dev/peps/pep-0561/)
7
+
8
+ A modern, production-ready Python SDK for sending transactional and marketing emails via SMTP (including SendGrid SMTP relays) with built-in Jinja2 templating, structured logging, secure credential handling, and comprehensive exception management.
9
+
10
+ ---
11
+
12
+ ## Features
13
+
14
+ - 🚀 **Production-Grade Delivery**: Reliable SMTP transport supporting TLS encryption, authentication, and timeouts.
15
+ - 🎨 **Built-in & Custom Jinja2 Templates**: Comes with responsive pre-built templates (`welcome`, `reset_password`, `verify_account`) and allows custom template directories.
16
+ - 🪵 **Enterprise Logging**: PEP 282 compliant logging with `NullHandler` by default, granular log levels (`DEBUG`, `INFO`, `ERROR`), and automatic password masking.
17
+ - 🛡️ **Comprehensive Exception Hierarchy**: Clear, actionable exceptions for validation, templates, authentication, connection timeouts, and delivery errors.
18
+ - ⚙️ **Flexible Configuration**: Seamlessly configure via `.env` files, environment variables, or typed `EmailConfig` objects.
19
+ - 📦 **PEP 561 Compliant**: Fully typed (`py.typed`) for autocomplete and static analysis with MyPy and IDEs.
20
+
21
+ ---
22
+
23
+ ## Installation
24
+
25
+ Install via `pip`:
26
+
27
+ ```bash
28
+ pip install sendgrid-email-service
29
+ ```
30
+
31
+ ---
32
+
33
+ ## Quick Start
34
+
35
+ ### 1. Environment Configuration
36
+
37
+ Create a `.env` file in your project root or set environment variables:
38
+
39
+ ```ini
40
+ # SMTP Configuration (SendGrid, Mailpit, Amazon SES, or custom SMTP)
41
+ EMAIL_SMTP_HOST=smtp.sendgrid.net
42
+ EMAIL_SMTP_PORT=587
43
+ EMAIL_SMTP_USERNAME=apikey
44
+ EMAIL_SMTP_PASSWORD=your-sendgrid-api-key
45
+
46
+ # Sender Defaults
47
+ EMAIL_FROM=notifications@yourdomain.com
48
+ EMAIL_FROM_NAME=Your Company
49
+
50
+ # Optional Settings
51
+ EMAIL_USE_TLS=true
52
+ EMAIL_TIMEOUT=30
53
+ ```
54
+
55
+ ### 2. Send Plain Text or HTML Email
56
+
57
+ ```python
58
+ from sendgrid_email_service import EmailClient
59
+
60
+ # Automatically loads configuration from .env / environment variables
61
+ client = EmailClient()
62
+
63
+ # Send a simple email
64
+ client.send(
65
+ to="recipient@example.com",
66
+ subject="Welcome to Our Platform",
67
+ body="Hello! Thank you for joining us.",
68
+ )
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Working with Templates
74
+
75
+ `sendgrid-email-service` includes responsive, production-ready HTML templates out of the box.
76
+
77
+ ### Built-in Templates
78
+
79
+ | Template Name | Description | Available Context Variables |
80
+ | :--- | :--- | :--- |
81
+ | `welcome` | Onboarding & welcome message | `name`, `company_name`, `action_url`, `year` |
82
+ | `reset_password` | Password recovery with secure action button | `name`, `reset_url`, `company_name`, `expiry_hours`, `support_email`, `year` |
83
+ | `verify_account` | Email verification & activation link | `name`, `verification_url`, `company_name`, `expiry_hours`, `support_email`, `year` |
84
+
85
+ ### Example: Sending a Template Email
86
+
87
+ ```python
88
+ from sendgrid_email_service import EmailClient
89
+
90
+ client = EmailClient()
91
+
92
+ client.send(
93
+ to="user@example.com",
94
+ subject="Welcome to FireCompass!",
95
+ template="welcome",
96
+ data={
97
+ "name": "Jane Doe",
98
+ "company_name": "FireCompass",
99
+ "action_url": "https://app.firecompass.com/dashboard",
100
+ "year": 2026,
101
+ },
102
+ )
103
+ ```
104
+
105
+ ### Example: Using Custom Templates
106
+
107
+ You can point `EmailClient` to your own Jinja2 template directory:
108
+
109
+ ```python
110
+ from pathlib import Path
111
+ from sendgrid_email_service import EmailClient
112
+
113
+ client = EmailClient(template_directory=Path("./my_custom_templates"))
114
+
115
+ client.send(
116
+ to="customer@example.com",
117
+ subject="Your Invoice is Ready",
118
+ template="monthly_invoice", # Looks for monthly_invoice.html in ./my_custom_templates
119
+ data={
120
+ "customer_name": "Acme Corp",
121
+ "invoice_number": "INV-2026-001",
122
+ "amount_due": "$149.00",
123
+ },
124
+ )
125
+ ```
126
+
127
+ ---
128
+
129
+ ## Programmatic Configuration
130
+
131
+ Instead of environment variables, you can configure the client directly using `EmailConfig`:
132
+
133
+ ```python
134
+ from sendgrid_email_service import EmailClient, EmailConfig
135
+
136
+ config = EmailConfig(
137
+ smtp_host="smtp.sendgrid.net",
138
+ smtp_port=587,
139
+ smtp_username="apikey",
140
+ smtp_password="your-api-key-here",
141
+ from_email="no-reply@company.com",
142
+ from_name="My Company",
143
+ use_tls=True,
144
+ timeout=30,
145
+ )
146
+
147
+ client = EmailClient(config=config)
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Exception Handling
153
+
154
+ The SDK provides a clean exception hierarchy inheriting from `EmailError`:
155
+
156
+ ```
157
+ EmailError (Base)
158
+ ├── EmailConfigurationError
159
+ ├── EmailValidationError
160
+ ├── EmailTemplateError
161
+ └── EmailSendError
162
+ ├── EmailConnectionError
163
+ ├── EmailAuthenticationError
164
+ ├── EmailTimeoutError
165
+ └── EmailRecipientsRefusedError
166
+ ```
167
+
168
+ ### Example: Robust Error Handling
169
+
170
+ ```python
171
+ import logging
172
+ from sendgrid_email_service import (
173
+ EmailClient,
174
+ EmailAuthenticationError,
175
+ EmailConnectionError,
176
+ EmailRecipientsRefusedError,
177
+ EmailTimeoutError,
178
+ EmailValidationError,
179
+ EmailTemplateError,
180
+ EmailSendError,
181
+ EmailError,
182
+ )
183
+
184
+ client = EmailClient()
185
+
186
+ try:
187
+ client.send(
188
+ to="client@example.com",
189
+ subject="Important Update",
190
+ template="welcome",
191
+ data={"name": "Alice", "company_name": "Acme Inc."},
192
+ )
193
+
194
+ except EmailValidationError as e:
195
+ print(f"Invalid email input on field '{e.field}': {e}")
196
+
197
+ except EmailTemplateError as e:
198
+ print(f"Template error ({e.template_name}): {e}")
199
+
200
+ except EmailAuthenticationError as e:
201
+ print(f"SMTP Auth failure for user '{e.username}': {e}")
202
+
203
+ except EmailConnectionError as e:
204
+ print(f"Could not connect to SMTP server ({e.host}:{e.port}): {e}")
205
+
206
+ except EmailTimeoutError as e:
207
+ print(f"Operation timed out after {e.timeout}s: {e}")
208
+
209
+ except EmailRecipientsRefusedError as e:
210
+ print(f"Server refused recipients {e.recipients}: {e}")
211
+
212
+ except EmailSendError as e:
213
+ print(f"Failed to send email: {e}")
214
+
215
+ except EmailError as e:
216
+ print(f"General email SDK error: {e}")
217
+ ```
218
+
219
+ ---
220
+
221
+ ## Logging Configuration
222
+
223
+ `sendgrid-email-service` adheres to Python library best practices (PEP 282). By default, it emits no logs unless your application configures logging.
224
+
225
+ ### Example: Enabling Logs in Your Application
226
+
227
+ ```python
228
+ import logging
229
+ import sys
230
+
231
+ # Configure root or package logger
232
+ logging.basicConfig(
233
+ level=logging.INFO,
234
+ format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
235
+ handlers=[logging.StreamHandler(sys.stdout)],
236
+ )
237
+
238
+ # Enable DEBUG logging specifically for sendgrid_email_service
239
+ logging.getLogger("sendgrid_email_service").setLevel(logging.DEBUG)
240
+ ```
241
+
242
+ > **Security Guarantee**: Passwords and sensitive credentials are automatically masked (e.g. `***`) and are never written to log files.
243
+
244
+ ---
245
+
246
+ ## Local Development with Mailpit
247
+
248
+ You can test email sending locally using [Mailpit](https://github.com/axllent/mailpit) included via Docker Compose:
249
+
250
+ 1. Start Mailpit:
251
+ ```bash
252
+ docker compose up -d
253
+ ```
254
+ 2. Set `.env` to point to localhost:
255
+ ```ini
256
+ EMAIL_SMTP_HOST=localhost
257
+ EMAIL_SMTP_PORT=1025
258
+ EMAIL_USE_TLS=false
259
+ ```
260
+ 3. View sent emails in your browser at `http://localhost:8025`.
261
+
262
+ ---
263
+
264
+ ## Running Tests
265
+
266
+ Install dev dependencies and run `pytest`:
267
+
268
+ ```bash
269
+ pip install -e ".[dev]"
270
+ pytest tests/ -v
271
+ ```
272
+
273
+ ---
274
+
275
+ ## Publishing to PyPI
276
+
277
+ 1. **Build distribution archives**:
278
+ ```bash
279
+ python -m build
280
+ ```
281
+
282
+ 2. **Verify archives with Twine**:
283
+ ```bash
284
+ twine check dist/*
285
+ ```
286
+
287
+ 3. **Upload to TestPyPI** (Optional):
288
+ ```bash
289
+ twine upload --repository testpypi dist/*
290
+ ```
291
+
292
+ 4. **Upload to PyPI**:
293
+ ```bash
294
+ twine upload dist/*
295
+ ```
296
+
297
+ ---
298
+
299
+ ## License
300
+
301
+ Distributed under the [MIT License](LICENSE).
302
+ # sendgrid-stmp-email-service