Metadata-Version: 2.4
Name: canitsend-client
Version: 1.0.0
Summary: Client for the CanItSend API — SPF/DKIM/DMARC audit from live DNS, SPF flattening, and email validation.
Project-URL: Homepage, https://canitsend.com
Project-URL: Documentation, https://canitsend.com/docs
Project-URL: Changelog, https://canitsend.com/docs
Author: CanItSend
License: MIT
Keywords: deliverability,dkim,dmarc,dns,email,email-validation,smtp,spf
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Communications :: Email
Classifier: Topic :: Internet :: Name Service (DNS)
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# canitsend-client

Zero-dependency Python client for the [CanItSend API](https://canitsend.com). Two questions, one API.

```bash
pip install canitsend-client
```

Every endpoint needs an API key. The **free tier includes 100 audits/month** — instant and self-serve: https://canitsend.com/#pricing

```python
from canitsend import CanItSendClient
cis = CanItSendClient(api_key="snd_live_...")
```

## 1. Can my domain send?

```python
a = cis.check("acme.com")          # also accepts "you@acme.com" or a URL
print(a["grade"], a["score"])      # F 40

# Plain-language answer to "but my email works!"
print(a["explanation"]["headline"])
# -> "Your mail works — but you can't prove you sent it."

# The exact records to paste, chosen for YOUR detected mail provider
for r in a["suggestedRecords"]:
    print(r["type"], r["host"], r["value"])
# -> TXT @       v=spf1 include:_spf.google.com ~all
# -> TXT _dmarc  v=DMARC1; p=none; rua=mailto:dmarc@acme.com
```

### The SPF 10-lookup limit

Over 10 DNS lookups means **PermError — SPF fails entirely**, not partially.
We count it correctly: `mx` costs **1**, not one per MX host. Most tools get this wrong.

```python
spf = cis.spf_check("acme.com")
print(spf["lookupCount"], "/ 10", "PermError!" if spf["lookupLimitExceeded"] else "")

print(cis.spf_flatten("acme.com")["flattened"])   # zero include-lookups
```

## 2. Should I send to this address?

```python
v = cis.validate("jane@gmial.com")
print(v["verdict"])      # risky
print(v["didYouMean"])   # jane@gmail.com

cis.validate("test@mailinator.com")   # risky   - disposable
cis.validate("support@acme.com")      # risky   - role account
cis.validate("x@no-such.dev")         # invalid - no MX, will bounce
```

> **What we don't claim:** we do **not** verify the mailbox exists and do **not**
> detect catch-alls. Both require an SMTP probe on port 25, which we deliberately
> do not run. `mailboxVerified` is always `False`. The strongest verdict is
> `deliverable_domain` — the *domain* accepts mail.

**Bulk** (Agency+): `audit_bulk([...])` up to 100 domains · `validate_bulk([...])` up to 1,000 addresses.

Errors raise `CanItSendError` with `.status` and `.problem` (RFC 9457).
