kawaa 0.1.0__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.
- kawaa-0.1.0/.gitignore +38 -0
- kawaa-0.1.0/PKG-INFO +362 -0
- kawaa-0.1.0/README.md +328 -0
- kawaa-0.1.0/examples/async_usage.py +137 -0
- kawaa-0.1.0/examples/basic_usage.py +165 -0
- kawaa-0.1.0/kawaa/__init__.py +79 -0
- kawaa-0.1.0/kawaa/client.py +782 -0
- kawaa-0.1.0/kawaa/exceptions.py +132 -0
- kawaa-0.1.0/kawaa/models.py +279 -0
- kawaa-0.1.0/kawaa/webhooks.py +212 -0
- kawaa-0.1.0/pyproject.toml +68 -0
- kawaa-0.1.0/tests/__init__.py +1 -0
- kawaa-0.1.0/tests/test_client.py +347 -0
- kawaa-0.1.0/tests/test_webhooks.py +159 -0
kawaa-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Rust
|
|
2
|
+
/target/
|
|
3
|
+
Cargo.lock
|
|
4
|
+
|
|
5
|
+
# Environment
|
|
6
|
+
.env
|
|
7
|
+
*.env.local
|
|
8
|
+
*.env.production
|
|
9
|
+
|
|
10
|
+
# IDE
|
|
11
|
+
.idea/
|
|
12
|
+
.vscode/
|
|
13
|
+
*.swp
|
|
14
|
+
*.swo
|
|
15
|
+
|
|
16
|
+
# OS
|
|
17
|
+
.DS_Store
|
|
18
|
+
Thumbs.db
|
|
19
|
+
|
|
20
|
+
# Logs
|
|
21
|
+
*.log
|
|
22
|
+
logs/
|
|
23
|
+
|
|
24
|
+
# Terraform
|
|
25
|
+
.terraform/
|
|
26
|
+
terraform.tfstate*
|
|
27
|
+
tfplan
|
|
28
|
+
*.tfplan
|
|
29
|
+
**/*.tfplan
|
|
30
|
+
|
|
31
|
+
# Dashboard build artifacts
|
|
32
|
+
dashboard/.next/
|
|
33
|
+
dashboard/out/
|
|
34
|
+
|
|
35
|
+
# Lambda dependencies
|
|
36
|
+
lambda/node_modules/
|
|
37
|
+
__pycache__/
|
|
38
|
+
.cargo/
|
kawaa-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kawaa
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official Python SDK for Kawaa Email Verification API
|
|
5
|
+
Project-URL: Homepage, https://kawaa.com
|
|
6
|
+
Project-URL: Documentation, https://docs.kawaa.com
|
|
7
|
+
Project-URL: Repository, https://github.com/kawaa/kawaa-python
|
|
8
|
+
Project-URL: Changelog, https://github.com/kawaa/kawaa-python/blob/main/CHANGELOG.md
|
|
9
|
+
Author-email: Kawaa <support@kawaa.com>
|
|
10
|
+
License: MIT
|
|
11
|
+
Keywords: api,email,kawaa,validation,verification
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Communications :: Email
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.8
|
|
26
|
+
Requires-Dist: httpx>=0.24.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-httpx>=0.22.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# Kawaa Python SDK
|
|
36
|
+
|
|
37
|
+
Official Python SDK for [Kawaa](https://kawaa.com) Email Verification API.
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
- Verify single emails or batch lists
|
|
42
|
+
- Automatic retry with exponential backoff
|
|
43
|
+
- Both sync and async clients
|
|
44
|
+
- Full type hints for IDE support
|
|
45
|
+
- Webhook signature verification
|
|
46
|
+
- Framework integrations (Flask, FastAPI)
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install kawaa
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Quick Start
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from kawaa import Kawaa
|
|
58
|
+
|
|
59
|
+
# Create client with your API key
|
|
60
|
+
client = Kawaa("your-api-key")
|
|
61
|
+
|
|
62
|
+
# Verify a single email
|
|
63
|
+
result = client.verify("john@example.com")
|
|
64
|
+
print(f"Status: {result.status}") # valid, invalid, risky, or unknown
|
|
65
|
+
print(f"Score: {result.score}") # 0-100 quality score
|
|
66
|
+
|
|
67
|
+
if result.is_valid:
|
|
68
|
+
print("Email is valid!")
|
|
69
|
+
|
|
70
|
+
if result.flags.disposable:
|
|
71
|
+
print("Warning: disposable email")
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Single Email Verification
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from kawaa import Kawaa
|
|
78
|
+
|
|
79
|
+
client = Kawaa("your-api-key")
|
|
80
|
+
|
|
81
|
+
# Basic verification
|
|
82
|
+
result = client.verify("user@example.com")
|
|
83
|
+
|
|
84
|
+
# Access results
|
|
85
|
+
print(f"Email: {result.email}")
|
|
86
|
+
print(f"Status: {result.status}") # VerificationStatus enum
|
|
87
|
+
print(f"Score: {result.score}") # 0-100
|
|
88
|
+
print(f"Disposable: {result.flags.disposable}")
|
|
89
|
+
print(f"Role account: {result.flags.role}")
|
|
90
|
+
print(f"Free provider: {result.flags.free_provider}")
|
|
91
|
+
print(f"Catch-all: {result.flags.catch_all}")
|
|
92
|
+
|
|
93
|
+
# AI-suggested correction (if typo detected)
|
|
94
|
+
if result.suggestion:
|
|
95
|
+
print(f"Did you mean: {result.suggestion}")
|
|
96
|
+
|
|
97
|
+
# Customize verification options
|
|
98
|
+
result = client.verify(
|
|
99
|
+
"user@example.com",
|
|
100
|
+
check_mx=True, # Check MX records
|
|
101
|
+
check_smtp=True, # Perform SMTP verification
|
|
102
|
+
check_catch_all=True, # Detect catch-all domains
|
|
103
|
+
use_ai=True, # Use AI for typo detection
|
|
104
|
+
)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Batch Verification
|
|
108
|
+
|
|
109
|
+
For verifying many emails at once:
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from kawaa import Kawaa
|
|
113
|
+
|
|
114
|
+
client = Kawaa("your-api-key")
|
|
115
|
+
|
|
116
|
+
emails = [
|
|
117
|
+
"john@example.com",
|
|
118
|
+
"jane@example.com",
|
|
119
|
+
"invalid@",
|
|
120
|
+
"john@example.com", # duplicate - will be removed
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
# Start batch job
|
|
124
|
+
job = client.verify_batch(emails)
|
|
125
|
+
print(f"Job ID: {job.job_id}")
|
|
126
|
+
print(f"Duplicates removed: {job.duplicates_removed}")
|
|
127
|
+
print(f"Credits used: {job.credits_used}")
|
|
128
|
+
|
|
129
|
+
# Poll for completion
|
|
130
|
+
result = client.wait_for_job(job.job_id, timeout=300)
|
|
131
|
+
print(f"Valid: {result.valid_count}")
|
|
132
|
+
print(f"Invalid: {result.invalid_count}")
|
|
133
|
+
print(f"Risky: {result.risky_count}")
|
|
134
|
+
|
|
135
|
+
# Access individual results
|
|
136
|
+
for r in result.results:
|
|
137
|
+
print(f"{r.email}: {r.status} (score: {r.score})")
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### One-liner with wait
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
# Start job and wait for completion in one call
|
|
144
|
+
result = client.verify_batch_and_wait(
|
|
145
|
+
emails,
|
|
146
|
+
poll_interval=2.0, # Check every 2 seconds
|
|
147
|
+
timeout=600, # Wait up to 10 minutes
|
|
148
|
+
)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Using webhooks
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
# Get notified when job completes
|
|
155
|
+
job = client.verify_batch(
|
|
156
|
+
emails,
|
|
157
|
+
webhook_url="https://your-server.com/webhook",
|
|
158
|
+
webhook_secret="your-secret", # Optional, for signature verification
|
|
159
|
+
)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Download Results
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
# Download as JSON
|
|
166
|
+
results = client.download_results(job_id)
|
|
167
|
+
for r in results.results:
|
|
168
|
+
print(f"{r.email}: {r.status}")
|
|
169
|
+
|
|
170
|
+
# Download as CSV
|
|
171
|
+
csv_data = client.download_results(job_id, format="csv")
|
|
172
|
+
print(csv_data) # CSV string
|
|
173
|
+
|
|
174
|
+
# For large result sets, you'll get a presigned URL
|
|
175
|
+
if results.download_url:
|
|
176
|
+
print(f"Download from: {results.download_url}")
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Async Client
|
|
180
|
+
|
|
181
|
+
For async/await support:
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
import asyncio
|
|
185
|
+
from kawaa import AsyncKawaa
|
|
186
|
+
|
|
187
|
+
async def main():
|
|
188
|
+
async with AsyncKawaa("your-api-key") as client:
|
|
189
|
+
# Single verification
|
|
190
|
+
result = await client.verify("user@example.com")
|
|
191
|
+
print(f"Status: {result.status}")
|
|
192
|
+
|
|
193
|
+
# Batch verification
|
|
194
|
+
job = await client.verify_batch(emails)
|
|
195
|
+
result = await client.wait_for_job(job.job_id)
|
|
196
|
+
print(f"Valid: {result.valid_count}")
|
|
197
|
+
|
|
198
|
+
asyncio.run(main())
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Webhook Handling
|
|
202
|
+
|
|
203
|
+
Verify webhook signatures and parse events:
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
from kawaa.webhooks import parse_webhook, verify_signature
|
|
207
|
+
|
|
208
|
+
# Verify signature
|
|
209
|
+
is_valid = verify_signature(
|
|
210
|
+
payload=request.body,
|
|
211
|
+
signature=request.headers["X-Kawaa-Signature"],
|
|
212
|
+
secret="your-webhook-secret",
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
# Parse webhook event
|
|
216
|
+
event = parse_webhook(
|
|
217
|
+
payload=request.body,
|
|
218
|
+
signature=request.headers.get("X-Kawaa-Signature"),
|
|
219
|
+
secret="your-webhook-secret", # Optional
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
print(f"Job {event.job_id} completed!")
|
|
223
|
+
print(f"Valid: {event.valid}, Invalid: {event.invalid}")
|
|
224
|
+
print(f"Download: {event.download_url}")
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Flask Integration
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
from flask import Flask
|
|
231
|
+
from kawaa.webhooks import flask_webhook_handler
|
|
232
|
+
|
|
233
|
+
app = Flask(__name__)
|
|
234
|
+
|
|
235
|
+
@app.route("/webhook", methods=["POST"])
|
|
236
|
+
@flask_webhook_handler("your-webhook-secret")
|
|
237
|
+
def handle_webhook(event):
|
|
238
|
+
print(f"Job {event.job_id} completed!")
|
|
239
|
+
return "", 200
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### FastAPI Integration
|
|
243
|
+
|
|
244
|
+
```python
|
|
245
|
+
from fastapi import FastAPI, Depends
|
|
246
|
+
from kawaa.webhooks import fastapi_webhook_handler, WebhookEvent
|
|
247
|
+
|
|
248
|
+
app = FastAPI()
|
|
249
|
+
get_event = fastapi_webhook_handler("your-webhook-secret")
|
|
250
|
+
|
|
251
|
+
@app.post("/webhook")
|
|
252
|
+
async def handle_webhook(event: WebhookEvent = Depends(get_event)):
|
|
253
|
+
print(f"Job {event.job_id} completed!")
|
|
254
|
+
return {"status": "ok"}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Account Information
|
|
258
|
+
|
|
259
|
+
```python
|
|
260
|
+
account = client.get_account()
|
|
261
|
+
print(f"Credits remaining: {account.credits_remaining}")
|
|
262
|
+
print(f"Plan: {account.plan}")
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Error Handling
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
from kawaa import Kawaa
|
|
269
|
+
from kawaa import (
|
|
270
|
+
KawaaError,
|
|
271
|
+
AuthenticationError,
|
|
272
|
+
RateLimitError,
|
|
273
|
+
InsufficientCreditsError,
|
|
274
|
+
ValidationError,
|
|
275
|
+
NotFoundError,
|
|
276
|
+
TimeoutError,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
client = Kawaa("your-api-key")
|
|
280
|
+
|
|
281
|
+
try:
|
|
282
|
+
result = client.verify("user@example.com")
|
|
283
|
+
except AuthenticationError:
|
|
284
|
+
print("Invalid API key")
|
|
285
|
+
except RateLimitError as e:
|
|
286
|
+
print(f"Rate limited. Retry after {e.retry_after}s")
|
|
287
|
+
except InsufficientCreditsError:
|
|
288
|
+
print("Not enough credits")
|
|
289
|
+
except ValidationError as e:
|
|
290
|
+
print(f"Invalid request: {e.message}")
|
|
291
|
+
except TimeoutError:
|
|
292
|
+
print("Request timed out")
|
|
293
|
+
except KawaaError as e:
|
|
294
|
+
print(f"API error: {e.message}")
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Configuration
|
|
298
|
+
|
|
299
|
+
```python
|
|
300
|
+
client = Kawaa(
|
|
301
|
+
api_key="your-api-key",
|
|
302
|
+
base_url="https://api.kawaa.com", # Custom API URL
|
|
303
|
+
timeout=30.0, # Request timeout in seconds
|
|
304
|
+
max_retries=3, # Max retry attempts
|
|
305
|
+
)
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## Context Manager
|
|
309
|
+
|
|
310
|
+
The client can be used as a context manager for automatic cleanup:
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
with Kawaa("your-api-key") as client:
|
|
314
|
+
result = client.verify("user@example.com")
|
|
315
|
+
# Connection closed automatically
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## Models Reference
|
|
319
|
+
|
|
320
|
+
### VerificationResult
|
|
321
|
+
|
|
322
|
+
| Field | Type | Description |
|
|
323
|
+
|-------|------|-------------|
|
|
324
|
+
| `email` | str | The verified email |
|
|
325
|
+
| `status` | VerificationStatus | valid, invalid, risky, unknown |
|
|
326
|
+
| `score` | int | Quality score 0-100 |
|
|
327
|
+
| `flags` | VerificationFlags | Email characteristics |
|
|
328
|
+
| `suggestion` | str | AI-suggested correction |
|
|
329
|
+
| `verification` | VerificationDetails | Technical details |
|
|
330
|
+
|
|
331
|
+
### VerificationFlags
|
|
332
|
+
|
|
333
|
+
| Field | Type | Description |
|
|
334
|
+
|-------|------|-------------|
|
|
335
|
+
| `disposable` | bool | Temporary email service |
|
|
336
|
+
| `role` | bool | Role account (info@, support@) |
|
|
337
|
+
| `free_provider` | bool | Free email provider |
|
|
338
|
+
| `catch_all` | bool | Domain accepts all emails |
|
|
339
|
+
|
|
340
|
+
### JobStatusResult
|
|
341
|
+
|
|
342
|
+
| Field | Type | Description |
|
|
343
|
+
|-------|------|-------------|
|
|
344
|
+
| `job_id` | str | Unique job identifier |
|
|
345
|
+
| `status` | JobStatus | pending, processing, completed, failed |
|
|
346
|
+
| `total_emails` | int | Total emails in job |
|
|
347
|
+
| `processed_emails` | int | Emails processed so far |
|
|
348
|
+
| `valid_count` | int | Valid email count |
|
|
349
|
+
| `invalid_count` | int | Invalid email count |
|
|
350
|
+
| `risky_count` | int | Risky email count |
|
|
351
|
+
| `progress_percent` | float | Completion percentage |
|
|
352
|
+
| `results` | List[VerificationResult] | Individual results |
|
|
353
|
+
|
|
354
|
+
## License
|
|
355
|
+
|
|
356
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
357
|
+
|
|
358
|
+
## Support
|
|
359
|
+
|
|
360
|
+
- Documentation: https://docs.kawaa.com
|
|
361
|
+
- Email: support@kawaa.com
|
|
362
|
+
- Issues: https://github.com/kawaa/kawaa-python/issues
|
kawaa-0.1.0/README.md
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# Kawaa Python SDK
|
|
2
|
+
|
|
3
|
+
Official Python SDK for [Kawaa](https://kawaa.com) Email Verification API.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Verify single emails or batch lists
|
|
8
|
+
- Automatic retry with exponential backoff
|
|
9
|
+
- Both sync and async clients
|
|
10
|
+
- Full type hints for IDE support
|
|
11
|
+
- Webhook signature verification
|
|
12
|
+
- Framework integrations (Flask, FastAPI)
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install kawaa
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```python
|
|
23
|
+
from kawaa import Kawaa
|
|
24
|
+
|
|
25
|
+
# Create client with your API key
|
|
26
|
+
client = Kawaa("your-api-key")
|
|
27
|
+
|
|
28
|
+
# Verify a single email
|
|
29
|
+
result = client.verify("john@example.com")
|
|
30
|
+
print(f"Status: {result.status}") # valid, invalid, risky, or unknown
|
|
31
|
+
print(f"Score: {result.score}") # 0-100 quality score
|
|
32
|
+
|
|
33
|
+
if result.is_valid:
|
|
34
|
+
print("Email is valid!")
|
|
35
|
+
|
|
36
|
+
if result.flags.disposable:
|
|
37
|
+
print("Warning: disposable email")
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Single Email Verification
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from kawaa import Kawaa
|
|
44
|
+
|
|
45
|
+
client = Kawaa("your-api-key")
|
|
46
|
+
|
|
47
|
+
# Basic verification
|
|
48
|
+
result = client.verify("user@example.com")
|
|
49
|
+
|
|
50
|
+
# Access results
|
|
51
|
+
print(f"Email: {result.email}")
|
|
52
|
+
print(f"Status: {result.status}") # VerificationStatus enum
|
|
53
|
+
print(f"Score: {result.score}") # 0-100
|
|
54
|
+
print(f"Disposable: {result.flags.disposable}")
|
|
55
|
+
print(f"Role account: {result.flags.role}")
|
|
56
|
+
print(f"Free provider: {result.flags.free_provider}")
|
|
57
|
+
print(f"Catch-all: {result.flags.catch_all}")
|
|
58
|
+
|
|
59
|
+
# AI-suggested correction (if typo detected)
|
|
60
|
+
if result.suggestion:
|
|
61
|
+
print(f"Did you mean: {result.suggestion}")
|
|
62
|
+
|
|
63
|
+
# Customize verification options
|
|
64
|
+
result = client.verify(
|
|
65
|
+
"user@example.com",
|
|
66
|
+
check_mx=True, # Check MX records
|
|
67
|
+
check_smtp=True, # Perform SMTP verification
|
|
68
|
+
check_catch_all=True, # Detect catch-all domains
|
|
69
|
+
use_ai=True, # Use AI for typo detection
|
|
70
|
+
)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Batch Verification
|
|
74
|
+
|
|
75
|
+
For verifying many emails at once:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from kawaa import Kawaa
|
|
79
|
+
|
|
80
|
+
client = Kawaa("your-api-key")
|
|
81
|
+
|
|
82
|
+
emails = [
|
|
83
|
+
"john@example.com",
|
|
84
|
+
"jane@example.com",
|
|
85
|
+
"invalid@",
|
|
86
|
+
"john@example.com", # duplicate - will be removed
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
# Start batch job
|
|
90
|
+
job = client.verify_batch(emails)
|
|
91
|
+
print(f"Job ID: {job.job_id}")
|
|
92
|
+
print(f"Duplicates removed: {job.duplicates_removed}")
|
|
93
|
+
print(f"Credits used: {job.credits_used}")
|
|
94
|
+
|
|
95
|
+
# Poll for completion
|
|
96
|
+
result = client.wait_for_job(job.job_id, timeout=300)
|
|
97
|
+
print(f"Valid: {result.valid_count}")
|
|
98
|
+
print(f"Invalid: {result.invalid_count}")
|
|
99
|
+
print(f"Risky: {result.risky_count}")
|
|
100
|
+
|
|
101
|
+
# Access individual results
|
|
102
|
+
for r in result.results:
|
|
103
|
+
print(f"{r.email}: {r.status} (score: {r.score})")
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### One-liner with wait
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
# Start job and wait for completion in one call
|
|
110
|
+
result = client.verify_batch_and_wait(
|
|
111
|
+
emails,
|
|
112
|
+
poll_interval=2.0, # Check every 2 seconds
|
|
113
|
+
timeout=600, # Wait up to 10 minutes
|
|
114
|
+
)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Using webhooks
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
# Get notified when job completes
|
|
121
|
+
job = client.verify_batch(
|
|
122
|
+
emails,
|
|
123
|
+
webhook_url="https://your-server.com/webhook",
|
|
124
|
+
webhook_secret="your-secret", # Optional, for signature verification
|
|
125
|
+
)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Download Results
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
# Download as JSON
|
|
132
|
+
results = client.download_results(job_id)
|
|
133
|
+
for r in results.results:
|
|
134
|
+
print(f"{r.email}: {r.status}")
|
|
135
|
+
|
|
136
|
+
# Download as CSV
|
|
137
|
+
csv_data = client.download_results(job_id, format="csv")
|
|
138
|
+
print(csv_data) # CSV string
|
|
139
|
+
|
|
140
|
+
# For large result sets, you'll get a presigned URL
|
|
141
|
+
if results.download_url:
|
|
142
|
+
print(f"Download from: {results.download_url}")
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Async Client
|
|
146
|
+
|
|
147
|
+
For async/await support:
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
import asyncio
|
|
151
|
+
from kawaa import AsyncKawaa
|
|
152
|
+
|
|
153
|
+
async def main():
|
|
154
|
+
async with AsyncKawaa("your-api-key") as client:
|
|
155
|
+
# Single verification
|
|
156
|
+
result = await client.verify("user@example.com")
|
|
157
|
+
print(f"Status: {result.status}")
|
|
158
|
+
|
|
159
|
+
# Batch verification
|
|
160
|
+
job = await client.verify_batch(emails)
|
|
161
|
+
result = await client.wait_for_job(job.job_id)
|
|
162
|
+
print(f"Valid: {result.valid_count}")
|
|
163
|
+
|
|
164
|
+
asyncio.run(main())
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Webhook Handling
|
|
168
|
+
|
|
169
|
+
Verify webhook signatures and parse events:
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
from kawaa.webhooks import parse_webhook, verify_signature
|
|
173
|
+
|
|
174
|
+
# Verify signature
|
|
175
|
+
is_valid = verify_signature(
|
|
176
|
+
payload=request.body,
|
|
177
|
+
signature=request.headers["X-Kawaa-Signature"],
|
|
178
|
+
secret="your-webhook-secret",
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# Parse webhook event
|
|
182
|
+
event = parse_webhook(
|
|
183
|
+
payload=request.body,
|
|
184
|
+
signature=request.headers.get("X-Kawaa-Signature"),
|
|
185
|
+
secret="your-webhook-secret", # Optional
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
print(f"Job {event.job_id} completed!")
|
|
189
|
+
print(f"Valid: {event.valid}, Invalid: {event.invalid}")
|
|
190
|
+
print(f"Download: {event.download_url}")
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Flask Integration
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
from flask import Flask
|
|
197
|
+
from kawaa.webhooks import flask_webhook_handler
|
|
198
|
+
|
|
199
|
+
app = Flask(__name__)
|
|
200
|
+
|
|
201
|
+
@app.route("/webhook", methods=["POST"])
|
|
202
|
+
@flask_webhook_handler("your-webhook-secret")
|
|
203
|
+
def handle_webhook(event):
|
|
204
|
+
print(f"Job {event.job_id} completed!")
|
|
205
|
+
return "", 200
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### FastAPI Integration
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
from fastapi import FastAPI, Depends
|
|
212
|
+
from kawaa.webhooks import fastapi_webhook_handler, WebhookEvent
|
|
213
|
+
|
|
214
|
+
app = FastAPI()
|
|
215
|
+
get_event = fastapi_webhook_handler("your-webhook-secret")
|
|
216
|
+
|
|
217
|
+
@app.post("/webhook")
|
|
218
|
+
async def handle_webhook(event: WebhookEvent = Depends(get_event)):
|
|
219
|
+
print(f"Job {event.job_id} completed!")
|
|
220
|
+
return {"status": "ok"}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Account Information
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
account = client.get_account()
|
|
227
|
+
print(f"Credits remaining: {account.credits_remaining}")
|
|
228
|
+
print(f"Plan: {account.plan}")
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Error Handling
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
from kawaa import Kawaa
|
|
235
|
+
from kawaa import (
|
|
236
|
+
KawaaError,
|
|
237
|
+
AuthenticationError,
|
|
238
|
+
RateLimitError,
|
|
239
|
+
InsufficientCreditsError,
|
|
240
|
+
ValidationError,
|
|
241
|
+
NotFoundError,
|
|
242
|
+
TimeoutError,
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
client = Kawaa("your-api-key")
|
|
246
|
+
|
|
247
|
+
try:
|
|
248
|
+
result = client.verify("user@example.com")
|
|
249
|
+
except AuthenticationError:
|
|
250
|
+
print("Invalid API key")
|
|
251
|
+
except RateLimitError as e:
|
|
252
|
+
print(f"Rate limited. Retry after {e.retry_after}s")
|
|
253
|
+
except InsufficientCreditsError:
|
|
254
|
+
print("Not enough credits")
|
|
255
|
+
except ValidationError as e:
|
|
256
|
+
print(f"Invalid request: {e.message}")
|
|
257
|
+
except TimeoutError:
|
|
258
|
+
print("Request timed out")
|
|
259
|
+
except KawaaError as e:
|
|
260
|
+
print(f"API error: {e.message}")
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Configuration
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
client = Kawaa(
|
|
267
|
+
api_key="your-api-key",
|
|
268
|
+
base_url="https://api.kawaa.com", # Custom API URL
|
|
269
|
+
timeout=30.0, # Request timeout in seconds
|
|
270
|
+
max_retries=3, # Max retry attempts
|
|
271
|
+
)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## Context Manager
|
|
275
|
+
|
|
276
|
+
The client can be used as a context manager for automatic cleanup:
|
|
277
|
+
|
|
278
|
+
```python
|
|
279
|
+
with Kawaa("your-api-key") as client:
|
|
280
|
+
result = client.verify("user@example.com")
|
|
281
|
+
# Connection closed automatically
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Models Reference
|
|
285
|
+
|
|
286
|
+
### VerificationResult
|
|
287
|
+
|
|
288
|
+
| Field | Type | Description |
|
|
289
|
+
|-------|------|-------------|
|
|
290
|
+
| `email` | str | The verified email |
|
|
291
|
+
| `status` | VerificationStatus | valid, invalid, risky, unknown |
|
|
292
|
+
| `score` | int | Quality score 0-100 |
|
|
293
|
+
| `flags` | VerificationFlags | Email characteristics |
|
|
294
|
+
| `suggestion` | str | AI-suggested correction |
|
|
295
|
+
| `verification` | VerificationDetails | Technical details |
|
|
296
|
+
|
|
297
|
+
### VerificationFlags
|
|
298
|
+
|
|
299
|
+
| Field | Type | Description |
|
|
300
|
+
|-------|------|-------------|
|
|
301
|
+
| `disposable` | bool | Temporary email service |
|
|
302
|
+
| `role` | bool | Role account (info@, support@) |
|
|
303
|
+
| `free_provider` | bool | Free email provider |
|
|
304
|
+
| `catch_all` | bool | Domain accepts all emails |
|
|
305
|
+
|
|
306
|
+
### JobStatusResult
|
|
307
|
+
|
|
308
|
+
| Field | Type | Description |
|
|
309
|
+
|-------|------|-------------|
|
|
310
|
+
| `job_id` | str | Unique job identifier |
|
|
311
|
+
| `status` | JobStatus | pending, processing, completed, failed |
|
|
312
|
+
| `total_emails` | int | Total emails in job |
|
|
313
|
+
| `processed_emails` | int | Emails processed so far |
|
|
314
|
+
| `valid_count` | int | Valid email count |
|
|
315
|
+
| `invalid_count` | int | Invalid email count |
|
|
316
|
+
| `risky_count` | int | Risky email count |
|
|
317
|
+
| `progress_percent` | float | Completion percentage |
|
|
318
|
+
| `results` | List[VerificationResult] | Individual results |
|
|
319
|
+
|
|
320
|
+
## License
|
|
321
|
+
|
|
322
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
323
|
+
|
|
324
|
+
## Support
|
|
325
|
+
|
|
326
|
+
- Documentation: https://docs.kawaa.com
|
|
327
|
+
- Email: support@kawaa.com
|
|
328
|
+
- Issues: https://github.com/kawaa/kawaa-python/issues
|