dgsender 1.0.0a2__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.
- dgsender-1.0.0a2/LICENSE +21 -0
- dgsender-1.0.0a2/PKG-INFO +670 -0
- dgsender-1.0.0a2/README.md +627 -0
- dgsender-1.0.0a2/dgsender/__init__.py +95 -0
- dgsender-1.0.0a2/dgsender/async_email_sender.py +119 -0
- dgsender-1.0.0a2/dgsender/async_sender.py +214 -0
- dgsender-1.0.0a2/dgsender/async_slack_sender.py +164 -0
- dgsender-1.0.0a2/dgsender/async_telegram_sender.py +166 -0
- dgsender-1.0.0a2/dgsender/base.py +116 -0
- dgsender-1.0.0a2/dgsender/composite_sender.py +56 -0
- dgsender-1.0.0a2/dgsender/email_sender.py +160 -0
- dgsender-1.0.0a2/dgsender/exceptions.py +19 -0
- dgsender-1.0.0a2/dgsender/mailer.py +545 -0
- dgsender-1.0.0a2/dgsender/metrics.py +152 -0
- dgsender-1.0.0a2/dgsender/slack_sender.py +90 -0
- dgsender-1.0.0a2/dgsender/telegram_sender.py +135 -0
- dgsender-1.0.0a2/dgsender/zabbix_sender.py +63 -0
- dgsender-1.0.0a2/dgsender.egg-info/PKG-INFO +670 -0
- dgsender-1.0.0a2/dgsender.egg-info/SOURCES.txt +22 -0
- dgsender-1.0.0a2/dgsender.egg-info/dependency_links.txt +1 -0
- dgsender-1.0.0a2/dgsender.egg-info/requires.txt +28 -0
- dgsender-1.0.0a2/dgsender.egg-info/top_level.txt +1 -0
- dgsender-1.0.0a2/pyproject.toml +71 -0
- dgsender-1.0.0a2/setup.cfg +4 -0
dgsender-1.0.0a2/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [year] [fullname]
|
|
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,670 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dgsender
|
|
3
|
+
Version: 1.0.0a2
|
|
4
|
+
Summary: Unified sender package for email, telegram, slack and zabbix with async support.
|
|
5
|
+
Author-email: Roman Rasputin <admin@roro.su>
|
|
6
|
+
License: MIT License
|
|
7
|
+
Project-URL: Homepage, https://gitlab.com/gng-group/dgsender
|
|
8
|
+
Project-URL: BugTracker, https://gitlab.com/gng-group/dgsender/issues
|
|
9
|
+
Keywords: telegram,email,zabbix
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Classifier: Topic :: System :: Distributed Computing
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: requests>=2.25.0
|
|
24
|
+
Provides-Extra: mail
|
|
25
|
+
Provides-Extra: tg
|
|
26
|
+
Requires-Dist: requests>=2.25.0; extra == "tg"
|
|
27
|
+
Provides-Extra: zabbix
|
|
28
|
+
Requires-Dist: divinegift>=1.3.16; extra == "zabbix"
|
|
29
|
+
Provides-Extra: slack
|
|
30
|
+
Requires-Dist: requests>=2.25.0; extra == "slack"
|
|
31
|
+
Provides-Extra: async-mail
|
|
32
|
+
Provides-Extra: async-tg
|
|
33
|
+
Requires-Dist: aiohttp>=3.8.0; extra == "async-tg"
|
|
34
|
+
Provides-Extra: async-slack
|
|
35
|
+
Requires-Dist: aiohttp>=3.8.0; extra == "async-slack"
|
|
36
|
+
Provides-Extra: metrics
|
|
37
|
+
Requires-Dist: dgmetrics>=1.0.0a7; extra == "metrics"
|
|
38
|
+
Provides-Extra: all
|
|
39
|
+
Requires-Dist: requests>=2.25.0; extra == "all"
|
|
40
|
+
Requires-Dist: aiohttp>=3.8.0; extra == "all"
|
|
41
|
+
Requires-Dist: dgmetrics>=1.0.0a7; extra == "all"
|
|
42
|
+
Dynamic: license-file
|
|
43
|
+
|
|
44
|
+
```markdown
|
|
45
|
+
# dgsender
|
|
46
|
+
|
|
47
|
+
Unified sender package for email, telegram, slack and zabbix with async support.
|
|
48
|
+
|
|
49
|
+
## Features
|
|
50
|
+
|
|
51
|
+
- π§ **Email sending** - SMTP with TLS/SSL support, attachments, HTML emails
|
|
52
|
+
- π± **Telegram** - Bot messaging with proxy support
|
|
53
|
+
- π¬ **Slack/Mattermost** - Webhook integration
|
|
54
|
+
- π **Zabbix** - Monitoring data submission
|
|
55
|
+
- β‘ **Async support** - Non-blocking operations for high performance
|
|
56
|
+
- π **Metrics integration** - Optional metrics collection with dgmetrics
|
|
57
|
+
- πͺ΅ **Custom logging** - Flexible logging configuration
|
|
58
|
+
- π§ **Modular design** - Install only what you need
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
|
|
62
|
+
### Basic installation
|
|
63
|
+
```bash
|
|
64
|
+
pip install dgsender
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### With specific features
|
|
68
|
+
```bash
|
|
69
|
+
# Telegram only
|
|
70
|
+
pip install dgsender[tg]
|
|
71
|
+
|
|
72
|
+
# Email only
|
|
73
|
+
pip install dgsender[mail]
|
|
74
|
+
|
|
75
|
+
# Zabbix only
|
|
76
|
+
pip install dgsender[zabbix]
|
|
77
|
+
|
|
78
|
+
# Async support
|
|
79
|
+
pip install dgsender[async]
|
|
80
|
+
|
|
81
|
+
# Metrics support
|
|
82
|
+
pip install dgsender[metrics]
|
|
83
|
+
|
|
84
|
+
# All features
|
|
85
|
+
pip install dgsender[all]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Quick Start
|
|
89
|
+
|
|
90
|
+
### Email Sending
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from dgsender import EmailSender
|
|
94
|
+
|
|
95
|
+
# Synchronous email sender
|
|
96
|
+
email_sender = EmailSender(
|
|
97
|
+
host="smtp.gmail.com",
|
|
98
|
+
port=587,
|
|
99
|
+
use_tls=True,
|
|
100
|
+
username="user@gmail.com",
|
|
101
|
+
password="password"
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
email_sender.send(
|
|
105
|
+
msg="Hello from dgsender!",
|
|
106
|
+
subject="Test Email",
|
|
107
|
+
to=["recipient@example.com"],
|
|
108
|
+
from_addr="sender@example.com",
|
|
109
|
+
is_html=True
|
|
110
|
+
)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Telegram Messages
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from dgsender import TelegramSender
|
|
117
|
+
|
|
118
|
+
tg_sender = TelegramSender(token="your_bot_token")
|
|
119
|
+
tg_sender.send("Hello Telegram!", chat_id=123456789)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Async Senders
|
|
123
|
+
|
|
124
|
+
### Async Email Sender
|
|
125
|
+
```python
|
|
126
|
+
import asyncio
|
|
127
|
+
from dgsender import AsyncEmailSender
|
|
128
|
+
|
|
129
|
+
async def main():
|
|
130
|
+
sender = AsyncEmailSender(
|
|
131
|
+
host="smtp.gmail.com",
|
|
132
|
+
port=587,
|
|
133
|
+
use_tls=True,
|
|
134
|
+
username="user@gmail.com",
|
|
135
|
+
password="password"
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
# Send single email
|
|
139
|
+
await sender.send(
|
|
140
|
+
msg="Hello from async!",
|
|
141
|
+
subject="Async Test",
|
|
142
|
+
to=["user@example.com"]
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# Send multiple emails concurrently
|
|
146
|
+
messages = [
|
|
147
|
+
{
|
|
148
|
+
"msg": "Message 1",
|
|
149
|
+
"subject": "Test 1",
|
|
150
|
+
"to": ["user1@example.com"]
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"msg": "Message 2",
|
|
154
|
+
"subject": "Test 2",
|
|
155
|
+
"to": ["user2@example.com"]
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
results = await sender.send_multiple(messages)
|
|
159
|
+
|
|
160
|
+
asyncio.run(main())
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Core Components
|
|
164
|
+
|
|
165
|
+
### Email Senders
|
|
166
|
+
|
|
167
|
+
#### Synchronous EmailSender
|
|
168
|
+
```python
|
|
169
|
+
from dgsender import EmailSender
|
|
170
|
+
|
|
171
|
+
sender = EmailSender(
|
|
172
|
+
host="smtp.example.com",
|
|
173
|
+
port=587,
|
|
174
|
+
use_tls=True,
|
|
175
|
+
username="user@example.com",
|
|
176
|
+
password="password"
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# Send with attachments
|
|
180
|
+
sender.send(
|
|
181
|
+
msg="<h1>HTML Content</h1>",
|
|
182
|
+
subject="Email with attachments",
|
|
183
|
+
to=["user1@example.com", "user2@example.com"],
|
|
184
|
+
cc=["manager@example.com"],
|
|
185
|
+
attachments=["file1.pdf", "image.jpg"],
|
|
186
|
+
is_html=True
|
|
187
|
+
)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### Asynchronous AsyncEmailSender
|
|
191
|
+
```python
|
|
192
|
+
from dgsender import AsyncEmailSender
|
|
193
|
+
|
|
194
|
+
async def send_emails():
|
|
195
|
+
sender = AsyncEmailSender(
|
|
196
|
+
host="smtp.example.com",
|
|
197
|
+
port=587,
|
|
198
|
+
use_tls=True
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
await sender.send(
|
|
202
|
+
msg="Async email content",
|
|
203
|
+
subject="Async Test",
|
|
204
|
+
to=["user@example.com"]
|
|
205
|
+
)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Telegram Senders
|
|
209
|
+
|
|
210
|
+
#### Synchronous TelegramSender
|
|
211
|
+
```python
|
|
212
|
+
from dgsender import TelegramSender
|
|
213
|
+
|
|
214
|
+
# Basic usage
|
|
215
|
+
tg = TelegramSender(token="your_bot_token")
|
|
216
|
+
tg.send("Simple message", chat_id=123456)
|
|
217
|
+
|
|
218
|
+
# With proxy and custom options
|
|
219
|
+
tg = TelegramSender(
|
|
220
|
+
token="your_bot_token",
|
|
221
|
+
base_url="https://api.telegram.org/bot",
|
|
222
|
+
proxy={"http": "http://proxy:3128", "https": "https://proxy:3128"}
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
tg.send(
|
|
226
|
+
"Formatted message",
|
|
227
|
+
chat_id=123456,
|
|
228
|
+
parse_mode="Markdown",
|
|
229
|
+
disable_web_page_preview=True
|
|
230
|
+
)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
#### Asynchronous AsyncTelegramSender
|
|
234
|
+
```python
|
|
235
|
+
from dgsender import AsyncTelegramSender
|
|
236
|
+
|
|
237
|
+
async def send_telegram():
|
|
238
|
+
tg = AsyncTelegramSender(token="your_bot_token")
|
|
239
|
+
await tg.send("Async telegram message", chat_id=123456)
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Slack/Mattermost Senders
|
|
243
|
+
|
|
244
|
+
```python
|
|
245
|
+
from dgsender import SlackSender
|
|
246
|
+
|
|
247
|
+
slack = SlackSender(webhook_url="https://hooks.slack.com/services/XXX")
|
|
248
|
+
slack.send("Hello Slack!")
|
|
249
|
+
|
|
250
|
+
# With custom options
|
|
251
|
+
slack.send(
|
|
252
|
+
"Custom message",
|
|
253
|
+
channel="#alerts",
|
|
254
|
+
username="MyBot",
|
|
255
|
+
icon_url="https://example.com/icon.png"
|
|
256
|
+
)
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Zabbix Sender
|
|
260
|
+
|
|
261
|
+
```python
|
|
262
|
+
from dgsender import ZabbixSender
|
|
263
|
+
|
|
264
|
+
zabbix = ZabbixSender(server="zabbix.example.com", port=10051)
|
|
265
|
+
zabbix.send(
|
|
266
|
+
host="web-server-01",
|
|
267
|
+
key="web.response.time",
|
|
268
|
+
value=150
|
|
269
|
+
)
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Composite Sender
|
|
273
|
+
|
|
274
|
+
```python
|
|
275
|
+
from dgsender import CompositeSender, TelegramSender, EmailSender, SlackSender
|
|
276
|
+
|
|
277
|
+
# Create multiple senders
|
|
278
|
+
tg_sender = TelegramSender(token="tg_token")
|
|
279
|
+
email_sender = EmailSender(host="smtp.example.com")
|
|
280
|
+
slack_sender = SlackSender(webhook_url="slack_webhook")
|
|
281
|
+
|
|
282
|
+
# Combine them
|
|
283
|
+
composite = CompositeSender(senders=[tg_sender, email_sender, slack_sender])
|
|
284
|
+
|
|
285
|
+
# Send to all channels
|
|
286
|
+
results = composite.send_all(
|
|
287
|
+
"Important notification!",
|
|
288
|
+
# Telegram specific
|
|
289
|
+
chat_id=123456,
|
|
290
|
+
# Email specific
|
|
291
|
+
subject="Alert",
|
|
292
|
+
to=["admin@example.com"],
|
|
293
|
+
# Slack specific
|
|
294
|
+
channel="#alerts"
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
print(f"Results: {results}")
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## Advanced Usage
|
|
301
|
+
|
|
302
|
+
### Custom Logging
|
|
303
|
+
|
|
304
|
+
```python
|
|
305
|
+
import logging
|
|
306
|
+
from dgsender import EmailSender
|
|
307
|
+
|
|
308
|
+
# Setup custom logger
|
|
309
|
+
logger = logging.getLogger('my_app')
|
|
310
|
+
handler = logging.StreamHandler()
|
|
311
|
+
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
312
|
+
handler.setFormatter(formatter)
|
|
313
|
+
logger.addHandler(handler)
|
|
314
|
+
|
|
315
|
+
# Use custom logger
|
|
316
|
+
sender = EmailSender(
|
|
317
|
+
host="smtp.example.com",
|
|
318
|
+
logger_instance=logger
|
|
319
|
+
)
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Metrics Integration
|
|
323
|
+
|
|
324
|
+
```python
|
|
325
|
+
from dgsender import EmailSender, TelegramSender
|
|
326
|
+
from dgmetrics import Metrics # Optional dependency
|
|
327
|
+
|
|
328
|
+
# Initialize metrics
|
|
329
|
+
metrics = Metrics()
|
|
330
|
+
|
|
331
|
+
# Senders with metrics
|
|
332
|
+
email_sender = EmailSender(
|
|
333
|
+
host="smtp.example.com",
|
|
334
|
+
metrics_instance=metrics
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
tg_sender = TelegramSender(
|
|
338
|
+
token="your_bot_token",
|
|
339
|
+
metrics_instance=metrics
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
# Send messages (metrics are collected automatically)
|
|
343
|
+
email_sender.send(...)
|
|
344
|
+
tg_sender.send(...)
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Custom Metrics Class
|
|
348
|
+
|
|
349
|
+
```python
|
|
350
|
+
from dgsender import EmailSender
|
|
351
|
+
|
|
352
|
+
class MyMetrics:
|
|
353
|
+
def counter(self, name, value=1, tags=None):
|
|
354
|
+
print(f"Counter: {name} = {value}")
|
|
355
|
+
|
|
356
|
+
def gauge(self, name, value, tags=None):
|
|
357
|
+
print(f"Gauge: {name} = {value}")
|
|
358
|
+
|
|
359
|
+
def timer(self, name, value, tags=None):
|
|
360
|
+
print(f"Timer: {name} = {value}s")
|
|
361
|
+
|
|
362
|
+
sender = EmailSender(
|
|
363
|
+
host="smtp.example.com",
|
|
364
|
+
metrics_instance=MyMetrics()
|
|
365
|
+
)
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Error Handling
|
|
369
|
+
|
|
370
|
+
```python
|
|
371
|
+
from dgsender import EmailSender, EmailSendError
|
|
372
|
+
|
|
373
|
+
sender = EmailSender(host="smtp.example.com")
|
|
374
|
+
|
|
375
|
+
try:
|
|
376
|
+
sender.send(
|
|
377
|
+
msg="Test message",
|
|
378
|
+
subject="Test",
|
|
379
|
+
to=["user@example.com"]
|
|
380
|
+
)
|
|
381
|
+
except EmailSendError as e:
|
|
382
|
+
print(f"Failed to send email: {e}")
|
|
383
|
+
except Exception as e:
|
|
384
|
+
print(f"Unexpected error: {e}")
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Low-level Mailer Usage
|
|
388
|
+
|
|
389
|
+
```python
|
|
390
|
+
from dgsender import Mailer, AsyncMailer, Message
|
|
391
|
+
|
|
392
|
+
# Synchronous mailer
|
|
393
|
+
mailer = Mailer(host="smtp.example.com", port=587)
|
|
394
|
+
message = Message(
|
|
395
|
+
From="sender@example.com",
|
|
396
|
+
To="recipient@example.com",
|
|
397
|
+
Subject="Direct Message",
|
|
398
|
+
Body="Hello from low-level mailer!"
|
|
399
|
+
)
|
|
400
|
+
mailer.send(message)
|
|
401
|
+
|
|
402
|
+
# Asynchronous mailer
|
|
403
|
+
async def async_send():
|
|
404
|
+
mailer = AsyncMailer(host="smtp.example.com", port=587)
|
|
405
|
+
await mailer.send(message)
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
## Configuration
|
|
409
|
+
|
|
410
|
+
### Email Configuration
|
|
411
|
+
|
|
412
|
+
| Parameter | Type | Default | Description |
|
|
413
|
+
|-----------|------|---------|-------------|
|
|
414
|
+
| `host` | str | "localhost" | SMTP server host |
|
|
415
|
+
| `port` | int | 0 | SMTP server port |
|
|
416
|
+
| `use_tls` | bool | False | Enable TLS encryption |
|
|
417
|
+
| `use_ssl` | bool | False | Enable SSL encryption |
|
|
418
|
+
| `username` | str | None | SMTP username |
|
|
419
|
+
| `password` | str | None | SMTP password |
|
|
420
|
+
| `reopen_mail_session` | bool | True | Recreate connection for each send |
|
|
421
|
+
|
|
422
|
+
### Telegram Configuration
|
|
423
|
+
|
|
424
|
+
| Parameter | Type | Default | Description |
|
|
425
|
+
|-----------|------|---------|-------------|
|
|
426
|
+
| `token` | str | Required | Bot token from BotFather |
|
|
427
|
+
| `base_url` | str | "https://api.telegram.org/bot" | Telegram API base URL |
|
|
428
|
+
| `proxy` | dict | None | Proxy configuration |
|
|
429
|
+
|
|
430
|
+
### Common Parameters
|
|
431
|
+
|
|
432
|
+
All senders support:
|
|
433
|
+
- `logger_instance`: Custom logger instance
|
|
434
|
+
- `metrics_instance`: Metrics collector instance
|
|
435
|
+
|
|
436
|
+
## Exception Types
|
|
437
|
+
|
|
438
|
+
| Exception | Description |
|
|
439
|
+
|-----------|-------------|
|
|
440
|
+
| `DGSenderError` | Base exception for all sender errors |
|
|
441
|
+
| `EmailSendError` | Email sending related errors |
|
|
442
|
+
| `TelegramSendError` | Telegram sending related errors |
|
|
443
|
+
| `SlackSendError` | Slack/Mattermost sending related errors |
|
|
444
|
+
| `ZabbixSendError` | Zabbix data submission errors |
|
|
445
|
+
|
|
446
|
+
## SSL/TLS Configuration
|
|
447
|
+
|
|
448
|
+
### SSL for Requests-based Senders (Telegram, Slack)
|
|
449
|
+
|
|
450
|
+
```python
|
|
451
|
+
from dgsender import TelegramSender, SlackSender
|
|
452
|
+
|
|
453
|
+
# Disable SSL verification (not recommended for production)
|
|
454
|
+
tg_sender = TelegramSender(
|
|
455
|
+
token="your_bot_token",
|
|
456
|
+
verify_ssl=False # Disable certificate verification
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
# Use client certificate
|
|
460
|
+
tg_sender = TelegramSender(
|
|
461
|
+
token="your_bot_token",
|
|
462
|
+
ssl_cert=("/path/to/client.crt", "/path/to/client.key") # Client certificate
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
# For Slack
|
|
466
|
+
slack_sender = SlackSender(
|
|
467
|
+
webhook_url="your_webhook",
|
|
468
|
+
verify_ssl=False # Disable verification
|
|
469
|
+
)
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### SSL for Async Senders (aiohttp-based)
|
|
473
|
+
|
|
474
|
+
```python
|
|
475
|
+
import ssl
|
|
476
|
+
from dgsender import AsyncTelegramSender, AsyncSlackSender
|
|
477
|
+
|
|
478
|
+
# Disable SSL verification
|
|
479
|
+
async_tg_sender = AsyncTelegramSender(
|
|
480
|
+
token="your_bot_token",
|
|
481
|
+
verify_ssl=False
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
# Use custom SSL context
|
|
485
|
+
ssl_context = ssl.create_default_context()
|
|
486
|
+
ssl_context.load_verify_locations(cafile="/path/to/ca-bundle.crt")
|
|
487
|
+
|
|
488
|
+
async_tg_sender = AsyncTelegramSender(
|
|
489
|
+
token="your_bot_token",
|
|
490
|
+
ssl_context=ssl_context
|
|
491
|
+
)
|
|
492
|
+
|
|
493
|
+
# Use client certificate
|
|
494
|
+
async_tg_sender = AsyncTelegramSender(
|
|
495
|
+
token="your_bot_token",
|
|
496
|
+
client_cert="/path/to/client.crt",
|
|
497
|
+
client_key="/path/to/client.key"
|
|
498
|
+
)
|
|
499
|
+
|
|
500
|
+
# For Slack
|
|
501
|
+
async_slack_sender = AsyncSlackSender(
|
|
502
|
+
webhook_url="your_webhook",
|
|
503
|
+
verify_ssl=True,
|
|
504
|
+
client_cert="/path/to/client.crt",
|
|
505
|
+
client_key="/path/to/client.key"
|
|
506
|
+
)
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
### Advanced SSL Configuration
|
|
510
|
+
|
|
511
|
+
```python
|
|
512
|
+
import ssl
|
|
513
|
+
from dgsender import AsyncTelegramSender
|
|
514
|
+
|
|
515
|
+
# Create custom SSL context with specific settings
|
|
516
|
+
ssl_context = ssl.create_default_context()
|
|
517
|
+
ssl_context.check_hostname = True
|
|
518
|
+
ssl_context.verify_mode = ssl.CERT_REQUIRED
|
|
519
|
+
ssl_context.load_default_certs()
|
|
520
|
+
ssl_context.load_verify_locations(cafile="/path/to/custom-ca-bundle.crt")
|
|
521
|
+
|
|
522
|
+
sender = AsyncTelegramSender(
|
|
523
|
+
token="your_bot_token",
|
|
524
|
+
ssl_context=ssl_context
|
|
525
|
+
)
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
## SSL Configuration Parameters
|
|
529
|
+
|
|
530
|
+
### For Requests-based Senders:
|
|
531
|
+
- `verify_ssl`: bool - Enable/disable SSL certificate verification (default: True)
|
|
532
|
+
- `ssl_cert`: str or tuple - Path to client certificate file, or tuple (cert, key)
|
|
533
|
+
|
|
534
|
+
### For Async Senders (aiohttp):
|
|
535
|
+
- `verify_ssl`: bool - Enable/disable SSL certificate verification (default: True)
|
|
536
|
+
- `ssl_context`: ssl.SSLContext - Custom SSL context
|
|
537
|
+
- `client_cert`: str - Path to client certificate file
|
|
538
|
+
- `client_key`: str - Path to client private key file
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
## ΠΡΠΈΠΌΠ΅ΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ SSL:
|
|
542
|
+
|
|
543
|
+
### ΠΠ°Π·ΠΎΠ²ΠΎΠ΅ ΠΎΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΏΡΠΎΠ²Π΅ΡΠΊΠΈ SSL:
|
|
544
|
+
```python
|
|
545
|
+
from dgsender import TelegramSender
|
|
546
|
+
|
|
547
|
+
# ΠΠ»Ρ ΡΠ΅ΡΡΠΎΠ²ΡΡ
ΡΡΠ΅Π΄ ΠΈΠ»ΠΈ ΡΠ°ΠΌΠΎΠΏΠΎΠ΄ΠΏΠΈΡΠ°Π½Π½ΡΡ
ΡΠ΅ΡΡΠΈΡΠΈΠΊΠ°ΡΠΎΠ²
|
|
548
|
+
tg = TelegramSender(
|
|
549
|
+
token="your_bot_token",
|
|
550
|
+
verify_ssl=False
|
|
551
|
+
)
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
### ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊΠ»ΠΈΠ΅Π½ΡΡΠΊΠΎΠ³ΠΎ ΡΠ΅ΡΡΠΈΡΠΈΠΊΠ°ΡΠ°:
|
|
555
|
+
```python
|
|
556
|
+
from dgsender import TelegramSender
|
|
557
|
+
|
|
558
|
+
# ΠΠ»Ρ ΡΠ΅ΡΠ²Π΅ΡΠΎΠ², ΡΡΠ΅Π±ΡΡΡΠΈΡ
ΠΊΠ»ΠΈΠ΅Π½ΡΡΠΊΡΡ Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ
|
|
559
|
+
tg = TelegramSender(
|
|
560
|
+
token="your_bot_token",
|
|
561
|
+
ssl_cert=("/path/to/client.crt", "/path/to/client.key")
|
|
562
|
+
)
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
### ΠΡΠΎΠ΄Π²ΠΈΠ½ΡΡΠ°Ρ SSL ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ Π΄Π»Ρ async:
|
|
566
|
+
```python
|
|
567
|
+
import ssl
|
|
568
|
+
from dgsender import AsyncTelegramSender
|
|
569
|
+
|
|
570
|
+
# Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΊΠ°ΡΡΠΎΠΌΠ½ΠΎΠ³ΠΎ SSL ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ°
|
|
571
|
+
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
|
|
572
|
+
context.load_cert_chain(
|
|
573
|
+
certfile="/path/to/client.crt",
|
|
574
|
+
keyfile="/path/to/client.key"
|
|
575
|
+
)
|
|
576
|
+
context.load_verify_locations(cafile="/path/to/ca-bundle.crt")
|
|
577
|
+
|
|
578
|
+
sender = AsyncTelegramSender(
|
|
579
|
+
token="your_bot_token",
|
|
580
|
+
ssl_context=context
|
|
581
|
+
)
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
## Performance Tips
|
|
586
|
+
|
|
587
|
+
### Use Async Senders for High Throughput
|
|
588
|
+
|
|
589
|
+
```python
|
|
590
|
+
import asyncio
|
|
591
|
+
from dgsender import AsyncEmailSender
|
|
592
|
+
|
|
593
|
+
async def send_bulk_emails(messages):
|
|
594
|
+
sender = AsyncEmailSender(host="smtp.example.com")
|
|
595
|
+
tasks = []
|
|
596
|
+
|
|
597
|
+
for msg_data in messages:
|
|
598
|
+
task = sender.send(**msg_data)
|
|
599
|
+
tasks.append(task)
|
|
600
|
+
|
|
601
|
+
# Send all emails concurrently
|
|
602
|
+
await asyncio.gather(*tasks, return_exceptions=True)
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
### Reuse Sender Instances
|
|
606
|
+
|
|
607
|
+
```python
|
|
608
|
+
# Good: Reuse sender instance
|
|
609
|
+
sender = EmailSender(host="smtp.example.com")
|
|
610
|
+
for message in messages:
|
|
611
|
+
sender.send(**message)
|
|
612
|
+
|
|
613
|
+
# Avoid: Creating new sender for each message
|
|
614
|
+
for message in messages:
|
|
615
|
+
sender = EmailSender(host="smtp.example.com") # Inefficient
|
|
616
|
+
sender.send(**message)
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
## Testing
|
|
620
|
+
|
|
621
|
+
```python
|
|
622
|
+
from dgsender import EmailSender
|
|
623
|
+
import unittest
|
|
624
|
+
from unittest.mock import Mock
|
|
625
|
+
|
|
626
|
+
class TestEmailSender(unittest.TestCase):
|
|
627
|
+
def setUp(self):
|
|
628
|
+
self.sender = EmailSender(host="localhost", port=1025) # Test SMTP
|
|
629
|
+
|
|
630
|
+
def test_send_email(self):
|
|
631
|
+
# Test email sending logic
|
|
632
|
+
result = self.sender.send(
|
|
633
|
+
msg="Test message",
|
|
634
|
+
subject="Test",
|
|
635
|
+
to=["test@example.com"]
|
|
636
|
+
)
|
|
637
|
+
# Add your assertions here
|
|
638
|
+
|
|
639
|
+
if __name__ == "__main__":
|
|
640
|
+
unittest.main()
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
## Contributing
|
|
644
|
+
|
|
645
|
+
1. Fork the repository
|
|
646
|
+
2. Create a feature branch
|
|
647
|
+
3. Make your changes
|
|
648
|
+
4. Add tests
|
|
649
|
+
5. Submit a pull request
|
|
650
|
+
|
|
651
|
+
## License
|
|
652
|
+
|
|
653
|
+
MIT License - see LICENSE file for details.
|
|
654
|
+
|
|
655
|
+
## Support
|
|
656
|
+
|
|
657
|
+
For issues and questions:
|
|
658
|
+
- Create an issue on GitHub
|
|
659
|
+
- Check existing documentation
|
|
660
|
+
- Review example code in the repository
|
|
661
|
+
|
|
662
|
+
## Changelog
|
|
663
|
+
|
|
664
|
+
### v1.0.0
|
|
665
|
+
- Initial release
|
|
666
|
+
- Email, Telegram, Slack, Zabbix senders
|
|
667
|
+
- Async support
|
|
668
|
+
- Metrics integration
|
|
669
|
+
- Custom logging support
|
|
670
|
+
```
|