Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

isitdisposable

Detect disposable, temporary, and burner email addresses in real time from Python, using the isitdisposable.com Application Programming Interface (API).

Install

pip install isitdisposable

or with uv:

uv add isitdisposable

You will need an API key from isitdisposable.com. A free tier is available, so you can try this out without a credit card.

Quick start: check an email address

from isitdisposable import Client

client = Client(api_key="isid_live_your_key_here")

result = client.check(email="someone@example.com")

if result.disposable:
    print("This looks like a disposable email address.")
else:
    print("This looks like a real, ongoing email address.")

api_key can also come from the ISITDISPOSABLE_API_KEY environment variable, so in most setups you can just write Client().

Example: block disposable signups in a Django form

# forms.py
from django import forms
from isitdisposable import Client

client = Client()  # reads ISITDISPOSABLE_API_KEY from the environment


class SignupForm(forms.Form):
    email = forms.EmailField()

    def clean_email(self):
        email = self.cleaned_data["email"]
        result = client.check(email=email)

        if result.disposable:
            raise forms.ValidationError(
                "Please sign up with an email address you check regularly. "
                "Disposable or throwaway addresses are not allowed."
            )

        return email

Example: block disposable signups in a FastAPI dependency

# dependencies.py
from fastapi import Depends, HTTPException
from isitdisposable import AsyncClient

async_client = AsyncClient()  # reads ISITDISPOSABLE_API_KEY from the environment


async def reject_disposable_email(email: str) -> str:
    result = await async_client.check(email=email)

    if result.disposable:
        raise HTTPException(
            status_code=400,
            detail="Please use an email address you check regularly, not a disposable one.",
        )

    return email


# In a route:
# @app.post("/signup")
# async def signup(email: str = Depends(reject_disposable_email)):
#     ...

Checking a batch

Check up to 100 emails or domains in a single request. Items can be plain strings (anything containing an "@" is treated as an email, everything else as a domain) or dicts:

result = client.check_batch(
    [
        "someone@example.com",
        "example.org",
        {"domain": "another-example.com"},
    ]
)

for item in result.results:
    print(item.domain, item.disposable, item.action)

print(f"Checked {result.count} items.")

Fail open by design

Signup forms and checkout flows should never break because of an email checking service having a bad moment. This client fails open by default: if the isitdisposable.com service cannot be reached, times out, is rate limiting you, or has an internal error, check() and check_batch() do not raise. Instead they return a result where checked is False, disposable is None, and action is "allow", and a warning is logged through the standard logging module under the logger name "isitdisposable". Your form keeps working; you can watch the warning logs to notice if this starts happening a lot.

If you would rather see failures as exceptions (for example in a background job where you want to retry later), turn this off:

client = Client(fail_open=False)

With fail_open=False, a connection problem raises NetworkError, a rate limit response raises RateLimitError, and a server error raises ServerError. Invalid requests (a missing or malformed API key, or a request that is missing both an email and a domain) always raise, in either mode, because those indicate something in your own code needs fixing rather than a temporary service problem.

Response fields

Every check returns a result with these fields. Any field can be None if the underlying signal was not evaluated for that request.

Field Type Meaning
checked bool Whether a real check was performed (False on a fail-open response).
normalized_email str or None The email address you sent, normalized.
domain str or None The domain that was evaluated.
disposable bool or None The core verdict: whether the domain is a disposable or throwaway email provider.
mx_valid bool or None Whether the domain has a working mail server.
role_account bool or None Whether the local part looks like a role address (for example support@).
relay bool or None Whether the domain is a mail relay or forwarding service.
public_domain bool or None Whether the domain is a large public provider (for example a well known free email service).
spam_risk bool or None Whether the domain appears on a spam or abuse reputation list. Only populated if your account has this signal enabled.
mx_masked bool or None Whether the domain's mail server is masked or hidden behind a routing service.
did_you_mean str or None A suggested correction if the domain looks like a likely typo.
mx_records list[str] or None The mail server records found for the domain.
action str The recommended action for your account's policy: "allow", "warn", or "block".
reason str or None A machine readable reason code. This set is open ended; treat unknown values as informational.
raw dict The full parsed response, including any fields not yet listed above, for forward compatibility.

Links

About

Python SDK for isitdisposable.com: detect disposable and throwaway email addresses

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages