notifyvia-email 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.
- notifyvia_email-0.1.0/PKG-INFO +149 -0
- notifyvia_email-0.1.0/README.md +141 -0
- notifyvia_email-0.1.0/pyproject.toml +20 -0
- notifyvia_email-0.1.0/pyproject.toml.orig +24 -0
- notifyvia_email-0.1.0/src/notifyvia_email/__init__.py +0 -0
- notifyvia_email-0.1.0/src/notifyvia_email/_base.py +112 -0
- notifyvia_email-0.1.0/src/notifyvia_email/v1/__init__.py +36 -0
- notifyvia_email-0.1.0/src/notifyvia_email/v2/__init__.py +39 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: notifyvia-email
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: The frontend Python library for notifyvia.email
|
|
5
|
+
Requires-Dist: requests>=2.34.2
|
|
6
|
+
Requires-Python: >=3.13
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
|
|
9
|
+
# notifyvia-email
|
|
10
|
+
|
|
11
|
+
The frontend Python library for [notifyvia.email](https://notifyvia.email/docs).
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install notifyvia-email
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
or with uv:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uv add notifyvia-email
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Requires Python 3.13+.
|
|
26
|
+
|
|
27
|
+
## Quick start
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from notifyvia_email.v2 import NotifyViaEmail, SendResult
|
|
31
|
+
|
|
32
|
+
client = NotifyViaEmail(api_key="your-api-key")
|
|
33
|
+
|
|
34
|
+
resp = client.send(
|
|
35
|
+
to="you@example.com",
|
|
36
|
+
subject="A message from your website",
|
|
37
|
+
text="Do you have any strawberry cheesecake?",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
if resp.ok:
|
|
41
|
+
print("Email queued for delivery")
|
|
42
|
+
else:
|
|
43
|
+
print(resp.result, resp.errors)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## API versions
|
|
47
|
+
|
|
48
|
+
Each API version has its own client with the same interface:
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from notifyvia_email.v1 import NotifyViaEmail # POST /api/v1/send
|
|
52
|
+
from notifyvia_email.v2 import NotifyViaEmail # POST /api/v2/send
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
v2 adds the `reply_to` parameter. Everything else is shared.
|
|
56
|
+
|
|
57
|
+
## Sending HTML
|
|
58
|
+
|
|
59
|
+
Provide `html`, `text`, or both. At least one is required, otherwise `send()` raises `ValueError`.
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
resp = client.send(
|
|
63
|
+
to="you@example.com",
|
|
64
|
+
subject="Welcome!",
|
|
65
|
+
html="<h1>Welcome</h1><p>Thanks for signing up.</p>",
|
|
66
|
+
text="Welcome! Thanks for signing up.",
|
|
67
|
+
reply_to="support@example.com", # v2 only
|
|
68
|
+
)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Spam checking and rate limiting
|
|
72
|
+
|
|
73
|
+
A typical contact form setup. The rate limiter needs the sender's IPv4 address.
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
resp = client.send(
|
|
77
|
+
to="owner@example.com",
|
|
78
|
+
subject="New contact form submission",
|
|
79
|
+
text=form_message,
|
|
80
|
+
enable_spam_checker=True,
|
|
81
|
+
enable_rate_limiter=True,
|
|
82
|
+
limit=3, # max requests...
|
|
83
|
+
within_seconds=300, # ...per 5 minutes, per IP
|
|
84
|
+
ipv4_address=request.remote_addr,
|
|
85
|
+
)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Choosing a service
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
resp = client.send(
|
|
92
|
+
to="you@example.com",
|
|
93
|
+
subject="Hello",
|
|
94
|
+
text="Sent via Postmark",
|
|
95
|
+
service="postmark", # "zepto" (default) or "postmark"
|
|
96
|
+
)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Handling the response
|
|
100
|
+
|
|
101
|
+
`send()` returns a `SendResponse` with:
|
|
102
|
+
|
|
103
|
+
- `result`: a `SendResult` enum member
|
|
104
|
+
- `errors`: the API's `errors` field (or `None`), e.g. per-field validation messages
|
|
105
|
+
- `ok`: `True` when the email was accepted for delivery
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
from notifyvia_email.v2 import SendResult
|
|
109
|
+
|
|
110
|
+
resp = client.send(to="not-an-email", subject="Hi", text="Hello")
|
|
111
|
+
|
|
112
|
+
match resp.result:
|
|
113
|
+
case SendResult.EMAIL_PROVISIONING:
|
|
114
|
+
print("Sent")
|
|
115
|
+
case SendResult.INVALID:
|
|
116
|
+
print("Validation failed:", resp.errors)
|
|
117
|
+
# {'to': ['Not a valid email address.']}
|
|
118
|
+
case SendResult.RATE_LIMIT_EXCEEDED:
|
|
119
|
+
print("Too many requests, try again later")
|
|
120
|
+
case SendResult.SPAM_DETECTED:
|
|
121
|
+
print("Message rejected as spam")
|
|
122
|
+
case SendResult.CONNECTION_ERROR:
|
|
123
|
+
print("Could not reach notifyvia.email:", resp.errors)
|
|
124
|
+
case _:
|
|
125
|
+
print("Failed:", resp.result.name, resp.errors)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
| `SendResult` | HTTP | Meaning |
|
|
129
|
+
|-----------------------------|------|--------------------------------------------------|
|
|
130
|
+
| `EMAIL_PROVISIONING` | 200 | Accepted and queued for delivery |
|
|
131
|
+
| `AUTHORIZATION_REQUIRED` | 401 | Missing or invalid API key |
|
|
132
|
+
| `RATE_LIMIT_EXCEEDED` | 429 | Too many requests from this IP in the window |
|
|
133
|
+
| `INVALID` | 460 | Request validation failed (see `errors`) |
|
|
134
|
+
| `INVALID_ACCOUNT` | 461 | API key accepted but no matching account |
|
|
135
|
+
| `INVALID_SERVICE` | 462 | `service` is not a supported provider |
|
|
136
|
+
| `INSUFFICIENT_CREDITS` | 463 | Not enough credits to send |
|
|
137
|
+
| `IPV4_ADDRESS_NOT_PROVIDED` | 464 | Rate limiter enabled without `ipv4_address` |
|
|
138
|
+
| `SPAM_DETECTED` | 465 | Body matched the spam dictionary |
|
|
139
|
+
| `SENDER_IPV4_BLOCKED` | 466 | Sender IP is on the global block list |
|
|
140
|
+
| `UNKNOWN_ERROR` | - | Unexpected status code from the API |
|
|
141
|
+
| `CONNECTION_ERROR` | - | Network failure or timeout; `errors` has details |
|
|
142
|
+
|
|
143
|
+
## Configuration
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
client = NotifyViaEmail(api_key="your-api-key", timeout=5.0) # seconds, default 10
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
See the [notifyvia.email docs](https://notifyvia.email/docs) for full API details.
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# notifyvia-email
|
|
2
|
+
|
|
3
|
+
The frontend Python library for [notifyvia.email](https://notifyvia.email/docs).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install notifyvia-email
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
or with uv:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
uv add notifyvia-email
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Requires Python 3.13+.
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from notifyvia_email.v2 import NotifyViaEmail, SendResult
|
|
23
|
+
|
|
24
|
+
client = NotifyViaEmail(api_key="your-api-key")
|
|
25
|
+
|
|
26
|
+
resp = client.send(
|
|
27
|
+
to="you@example.com",
|
|
28
|
+
subject="A message from your website",
|
|
29
|
+
text="Do you have any strawberry cheesecake?",
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
if resp.ok:
|
|
33
|
+
print("Email queued for delivery")
|
|
34
|
+
else:
|
|
35
|
+
print(resp.result, resp.errors)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## API versions
|
|
39
|
+
|
|
40
|
+
Each API version has its own client with the same interface:
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from notifyvia_email.v1 import NotifyViaEmail # POST /api/v1/send
|
|
44
|
+
from notifyvia_email.v2 import NotifyViaEmail # POST /api/v2/send
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
v2 adds the `reply_to` parameter. Everything else is shared.
|
|
48
|
+
|
|
49
|
+
## Sending HTML
|
|
50
|
+
|
|
51
|
+
Provide `html`, `text`, or both. At least one is required, otherwise `send()` raises `ValueError`.
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
resp = client.send(
|
|
55
|
+
to="you@example.com",
|
|
56
|
+
subject="Welcome!",
|
|
57
|
+
html="<h1>Welcome</h1><p>Thanks for signing up.</p>",
|
|
58
|
+
text="Welcome! Thanks for signing up.",
|
|
59
|
+
reply_to="support@example.com", # v2 only
|
|
60
|
+
)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Spam checking and rate limiting
|
|
64
|
+
|
|
65
|
+
A typical contact form setup. The rate limiter needs the sender's IPv4 address.
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
resp = client.send(
|
|
69
|
+
to="owner@example.com",
|
|
70
|
+
subject="New contact form submission",
|
|
71
|
+
text=form_message,
|
|
72
|
+
enable_spam_checker=True,
|
|
73
|
+
enable_rate_limiter=True,
|
|
74
|
+
limit=3, # max requests...
|
|
75
|
+
within_seconds=300, # ...per 5 minutes, per IP
|
|
76
|
+
ipv4_address=request.remote_addr,
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Choosing a service
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
resp = client.send(
|
|
84
|
+
to="you@example.com",
|
|
85
|
+
subject="Hello",
|
|
86
|
+
text="Sent via Postmark",
|
|
87
|
+
service="postmark", # "zepto" (default) or "postmark"
|
|
88
|
+
)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Handling the response
|
|
92
|
+
|
|
93
|
+
`send()` returns a `SendResponse` with:
|
|
94
|
+
|
|
95
|
+
- `result`: a `SendResult` enum member
|
|
96
|
+
- `errors`: the API's `errors` field (or `None`), e.g. per-field validation messages
|
|
97
|
+
- `ok`: `True` when the email was accepted for delivery
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from notifyvia_email.v2 import SendResult
|
|
101
|
+
|
|
102
|
+
resp = client.send(to="not-an-email", subject="Hi", text="Hello")
|
|
103
|
+
|
|
104
|
+
match resp.result:
|
|
105
|
+
case SendResult.EMAIL_PROVISIONING:
|
|
106
|
+
print("Sent")
|
|
107
|
+
case SendResult.INVALID:
|
|
108
|
+
print("Validation failed:", resp.errors)
|
|
109
|
+
# {'to': ['Not a valid email address.']}
|
|
110
|
+
case SendResult.RATE_LIMIT_EXCEEDED:
|
|
111
|
+
print("Too many requests, try again later")
|
|
112
|
+
case SendResult.SPAM_DETECTED:
|
|
113
|
+
print("Message rejected as spam")
|
|
114
|
+
case SendResult.CONNECTION_ERROR:
|
|
115
|
+
print("Could not reach notifyvia.email:", resp.errors)
|
|
116
|
+
case _:
|
|
117
|
+
print("Failed:", resp.result.name, resp.errors)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
| `SendResult` | HTTP | Meaning |
|
|
121
|
+
|-----------------------------|------|--------------------------------------------------|
|
|
122
|
+
| `EMAIL_PROVISIONING` | 200 | Accepted and queued for delivery |
|
|
123
|
+
| `AUTHORIZATION_REQUIRED` | 401 | Missing or invalid API key |
|
|
124
|
+
| `RATE_LIMIT_EXCEEDED` | 429 | Too many requests from this IP in the window |
|
|
125
|
+
| `INVALID` | 460 | Request validation failed (see `errors`) |
|
|
126
|
+
| `INVALID_ACCOUNT` | 461 | API key accepted but no matching account |
|
|
127
|
+
| `INVALID_SERVICE` | 462 | `service` is not a supported provider |
|
|
128
|
+
| `INSUFFICIENT_CREDITS` | 463 | Not enough credits to send |
|
|
129
|
+
| `IPV4_ADDRESS_NOT_PROVIDED` | 464 | Rate limiter enabled without `ipv4_address` |
|
|
130
|
+
| `SPAM_DETECTED` | 465 | Body matched the spam dictionary |
|
|
131
|
+
| `SENDER_IPV4_BLOCKED` | 466 | Sender IP is on the global block list |
|
|
132
|
+
| `UNKNOWN_ERROR` | - | Unexpected status code from the API |
|
|
133
|
+
| `CONNECTION_ERROR` | - | Network failure or timeout; `errors` has details |
|
|
134
|
+
|
|
135
|
+
## Configuration
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
client = NotifyViaEmail(api_key="your-api-key", timeout=5.0) # seconds, default 10
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
See the [notifyvia.email docs](https://notifyvia.email/docs) for full API details.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "notifyvia-email"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "The frontend Python library for notifyvia.email"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.13"
|
|
7
|
+
dependencies = ["requests>=2.34.2"]
|
|
8
|
+
|
|
9
|
+
[dependency-groups]
|
|
10
|
+
dev = ["pyqwe>=3.2.0"]
|
|
11
|
+
|
|
12
|
+
[tool.pyqwe]
|
|
13
|
+
sync = "*:uv run --env-file .index-notifyviaemail -- uv sync"
|
|
14
|
+
build = "*:uv build"
|
|
15
|
+
publish = "*:uv run --env-file .index-notifyviaemail -- uv publish --index uilix-forgejo"
|
|
16
|
+
uv = "*>:uv run --env-file .index-notifyviaemail -- uv"
|
|
17
|
+
|
|
18
|
+
[build-system]
|
|
19
|
+
requires = ["uv_build>=0.8.0,<0.12"]
|
|
20
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "notifyvia-email"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "The frontend Python library for notifyvia.email"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.13"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"requests>=2.34.2",
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
[dependency-groups]
|
|
12
|
+
dev = [
|
|
13
|
+
"pyqwe>=3.2.0",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[tool.pyqwe]
|
|
17
|
+
sync = "*:uv run --env-file .index-notifyviaemail -- uv sync"
|
|
18
|
+
build = "*:uv build"
|
|
19
|
+
publish = "*:uv run --env-file .index-notifyviaemail -- uv publish --index uilix-forgejo"
|
|
20
|
+
uv = "*>:uv run --env-file .index-notifyviaemail -- uv"
|
|
21
|
+
|
|
22
|
+
[build-system]
|
|
23
|
+
requires = ["uv_build>=0.8.0,<0.12"]
|
|
24
|
+
build-backend = "uv_build"
|
|
File without changes
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Any, Literal
|
|
4
|
+
|
|
5
|
+
import requests
|
|
6
|
+
|
|
7
|
+
BASE_URL = "https://notifyvia.email/api"
|
|
8
|
+
|
|
9
|
+
Service = Literal["zepto", "postmark"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SendResult(Enum):
|
|
13
|
+
"""Outcome of a send request, mapped from the API's HTTP status code."""
|
|
14
|
+
|
|
15
|
+
EMAIL_PROVISIONING = 200
|
|
16
|
+
RATE_LIMIT_EXCEEDED = 429
|
|
17
|
+
AUTHORIZATION_REQUIRED = 401
|
|
18
|
+
INVALID = 460
|
|
19
|
+
INVALID_ACCOUNT = 461
|
|
20
|
+
INVALID_SERVICE = 462
|
|
21
|
+
INSUFFICIENT_CREDITS = 463
|
|
22
|
+
IPV4_ADDRESS_NOT_PROVIDED = 464
|
|
23
|
+
SPAM_DETECTED = 465
|
|
24
|
+
SENDER_IPV4_BLOCKED = 466
|
|
25
|
+
UNKNOWN_ERROR = -1
|
|
26
|
+
CONNECTION_ERROR = -2
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def ok(self) -> bool:
|
|
30
|
+
return self is SendResult.EMAIL_PROVISIONING
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def from_status_code(cls, status_code: int) -> "SendResult":
|
|
34
|
+
try:
|
|
35
|
+
return cls(status_code)
|
|
36
|
+
except ValueError:
|
|
37
|
+
return cls.UNKNOWN_ERROR
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass(frozen=True)
|
|
41
|
+
class SendResponse:
|
|
42
|
+
"""The result enum plus the API's ``errors`` field (e.g. per-field messages on INVALID)."""
|
|
43
|
+
|
|
44
|
+
result: SendResult
|
|
45
|
+
errors: Any = None
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def ok(self) -> bool:
|
|
49
|
+
return self.result.ok
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class BaseNotifyViaEmail:
|
|
53
|
+
version: str
|
|
54
|
+
|
|
55
|
+
def __init__(self, api_key: str, timeout: float = 10.0):
|
|
56
|
+
self.api_key = api_key
|
|
57
|
+
self.timeout = timeout
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def url(self) -> str:
|
|
61
|
+
return f"{BASE_URL}/{self.version}/send"
|
|
62
|
+
|
|
63
|
+
def _post(self, payload: dict[str, Any]) -> SendResponse:
|
|
64
|
+
try:
|
|
65
|
+
response = requests.post(
|
|
66
|
+
self.url,
|
|
67
|
+
json=payload,
|
|
68
|
+
headers={"X-Api-Key": self.api_key},
|
|
69
|
+
timeout=self.timeout,
|
|
70
|
+
)
|
|
71
|
+
except requests.RequestException as e:
|
|
72
|
+
return SendResponse(SendResult.CONNECTION_ERROR, errors=str(e))
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
errors = response.json().get("errors")
|
|
76
|
+
except (ValueError, AttributeError):
|
|
77
|
+
errors = None
|
|
78
|
+
|
|
79
|
+
return SendResponse(SendResult.from_status_code(response.status_code), errors)
|
|
80
|
+
|
|
81
|
+
@staticmethod
|
|
82
|
+
def _build_payload(
|
|
83
|
+
to: str,
|
|
84
|
+
subject: str,
|
|
85
|
+
html: str | None,
|
|
86
|
+
text: str | None,
|
|
87
|
+
enable_spam_checker: bool,
|
|
88
|
+
enable_rate_limiter: bool,
|
|
89
|
+
limit: int,
|
|
90
|
+
within_seconds: int,
|
|
91
|
+
ipv4_address: str | None,
|
|
92
|
+
service: Service,
|
|
93
|
+
) -> dict[str, Any]:
|
|
94
|
+
if html is None and text is None:
|
|
95
|
+
raise ValueError("Either html or text must be provided")
|
|
96
|
+
|
|
97
|
+
payload: dict[str, Any] = {
|
|
98
|
+
"to": to,
|
|
99
|
+
"subject": subject,
|
|
100
|
+
"enable_spam_checker": enable_spam_checker,
|
|
101
|
+
"enable_rate_limiter": enable_rate_limiter,
|
|
102
|
+
"limit": limit,
|
|
103
|
+
"within_seconds": within_seconds,
|
|
104
|
+
"service": service,
|
|
105
|
+
}
|
|
106
|
+
if html is not None:
|
|
107
|
+
payload["html"] = html
|
|
108
|
+
if text is not None:
|
|
109
|
+
payload["text"] = text
|
|
110
|
+
if ipv4_address is not None:
|
|
111
|
+
payload["ipv4_address"] = ipv4_address
|
|
112
|
+
return payload
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from .._base import BaseNotifyViaEmail, SendResponse, SendResult, Service
|
|
2
|
+
|
|
3
|
+
__all__ = ["NotifyViaEmail", "SendResponse", "SendResult"]
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class NotifyViaEmail(BaseNotifyViaEmail):
|
|
7
|
+
"""Client for POST https://notifyvia.email/api/v1/send"""
|
|
8
|
+
|
|
9
|
+
version = "v1"
|
|
10
|
+
|
|
11
|
+
def send(
|
|
12
|
+
self,
|
|
13
|
+
to: str,
|
|
14
|
+
subject: str,
|
|
15
|
+
html: str | None = None,
|
|
16
|
+
text: str | None = None,
|
|
17
|
+
enable_spam_checker: bool = False,
|
|
18
|
+
enable_rate_limiter: bool = False,
|
|
19
|
+
limit: int = 3,
|
|
20
|
+
within_seconds: int = 300,
|
|
21
|
+
ipv4_address: str | None = None,
|
|
22
|
+
service: Service = "zepto",
|
|
23
|
+
) -> SendResponse:
|
|
24
|
+
payload = self._build_payload(
|
|
25
|
+
to=to,
|
|
26
|
+
subject=subject,
|
|
27
|
+
html=html,
|
|
28
|
+
text=text,
|
|
29
|
+
enable_spam_checker=enable_spam_checker,
|
|
30
|
+
enable_rate_limiter=enable_rate_limiter,
|
|
31
|
+
limit=limit,
|
|
32
|
+
within_seconds=within_seconds,
|
|
33
|
+
ipv4_address=ipv4_address,
|
|
34
|
+
service=service,
|
|
35
|
+
)
|
|
36
|
+
return self._post(payload)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from .._base import BaseNotifyViaEmail, SendResponse, SendResult, Service
|
|
2
|
+
|
|
3
|
+
__all__ = ["NotifyViaEmail", "SendResponse", "SendResult"]
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class NotifyViaEmail(BaseNotifyViaEmail):
|
|
7
|
+
"""Client for POST https://notifyvia.email/api/v2/send"""
|
|
8
|
+
|
|
9
|
+
version = "v2"
|
|
10
|
+
|
|
11
|
+
def send(
|
|
12
|
+
self,
|
|
13
|
+
to: str,
|
|
14
|
+
subject: str,
|
|
15
|
+
html: str | None = None,
|
|
16
|
+
text: str | None = None,
|
|
17
|
+
reply_to: str | None = None,
|
|
18
|
+
enable_spam_checker: bool = False,
|
|
19
|
+
enable_rate_limiter: bool = False,
|
|
20
|
+
limit: int = 3,
|
|
21
|
+
within_seconds: int = 300,
|
|
22
|
+
ipv4_address: str | None = None,
|
|
23
|
+
service: Service = "zepto",
|
|
24
|
+
) -> SendResponse:
|
|
25
|
+
payload = self._build_payload(
|
|
26
|
+
to=to,
|
|
27
|
+
subject=subject,
|
|
28
|
+
html=html,
|
|
29
|
+
text=text,
|
|
30
|
+
enable_spam_checker=enable_spam_checker,
|
|
31
|
+
enable_rate_limiter=enable_rate_limiter,
|
|
32
|
+
limit=limit,
|
|
33
|
+
within_seconds=within_seconds,
|
|
34
|
+
ipv4_address=ipv4_address,
|
|
35
|
+
service=service,
|
|
36
|
+
)
|
|
37
|
+
if reply_to is not None:
|
|
38
|
+
payload["reply_to"] = reply_to
|
|
39
|
+
return self._post(payload)
|