densend
The official Python client for DenSend.
pip install densend
Requires Python 3.8 or newer.
Sending
import densend
densend.api_key = "your DENSEND_API_KEY"
email = densend.Emails.send({
"from": "You <hello@yourdomain.com>",
"to": "someone@example.com",
"subject": "Hello from DenSend",
"html": "<p>Your order has shipped.</p>",
})
print(email["id"])
from has to be on a domain you have added and verified.
densend.api_key also reads from the DENSEND_API_KEY environment
variable, so setting it explicitly is only needed when you want to
override that.
Multiple recipients get one id each, because a bounce belongs to exactly one address:
email = densend.Emails.send({
"from": "You <hello@yourdomain.com>",
"to": ["first@example.com", "second@example.com"],
"cc": ["copied@example.com"],
"reply_to": "support@yourdomain.com",
"subject": "Your receipt",
"text": "Thanks for your order.",
})
print(email["ids"])
Scheduling
Pass a datetime or an ISO 8601 string. Anything in the past sends
immediately.
from datetime import datetime, timedelta, timezone
densend.Emails.send({
"from": "You <hello@yourdomain.com>",
"to": "someone@example.com",
"subject": "A reminder",
"text": "This was scheduled.",
"scheduled_at": datetime.now(timezone.utc) + timedelta(hours=1),
})
Attachments
with open("invoice.pdf", "rb") as f:
content = f.read()
densend.Emails.send({
"from": "You <hello@yourdomain.com>",
"to": "someone@example.com",
"subject": "Your invoice",
"text": "Attached.",
"attachments": [
{"filename": "invoice.pdf", "content": content, "content_type": "application/pdf"},
],
})
content can be bytes (encoded automatically) or a str you have
already base64-encoded yourself. 7MB total across all attachments,
combined. Going over raises a DenSendError naming the actual size, not a
generic failure.
Reading
email = densend.Emails.get(email_id)
print(email["status"], email["opens"], email["clicks"])
recent = densend.Emails.list(limit=20)
Errors
Every non-2xx response raises a DenSendError carrying the status, so you
can tell a bad key from a spent quota without parsing strings.
from densend import DenSendError
try:
densend.Emails.send({...})
except DenSendError as error:
if error.status == 401:
raise RuntimeError("Check DENSEND_API_KEY") from error
if error.is_retryable:
queue_for_later()
else:
raise
is_retryable is true for 429 and 5xx. A 422 means the payload was wrong
and retrying it unchanged will fail the same way.
Options
densend.base_url = "https://api.densend.com/v1" # override when self-hosting
base_url also reads from the DENSEND_BASE_URL environment variable.
Sending is asynchronous
send returns once DenSend has accepted the message, not once it has
landed. The returned id is how you follow it afterwards, through
Emails.get or a webhook.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file densend-0.1.0.tar.gz.
File metadata
- Download URL: densend-0.1.0.tar.gz
- Upload date:
- Size: 6.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7bde71f9ec584e6b2aa8e9be35737d34d599d789e90b9ceeb1eed9589849d608
|
|
| MD5 |
5865271efa893c5b08dac4359123443d
|
|
| BLAKE2b-256 |
8df98929f510362a9ce808a441ff1903832f4ca25f9ec0c05480ce83fb9640ff
|
File details
Details for the file densend-0.1.0-py3-none-any.whl.
File metadata
- Download URL: densend-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
469fd0f575ff8f6dd50aa639a362cc8338fdee929c71ace0709da60309289c58
|
|
| MD5 |
ad5659ccd1cb2099d6cfe1bbfc8aef22
|
|
| BLAKE2b-256 |
bde70c51b8fb10d5865f2a1c8e5f82f6e47712bc37bcaf7714d9caf8278dfd55
|