Skip to main content

temail

A terminal UI for disposable/temporary email providers. Generates a throwaway address and displays incoming mail without leaving the terminal.

SC

Top bar: message count, current selection, keybinds. Status line underneath. Body shows the selected message. Bottom bar shows PROVIDER | address, so the active mailbox is always visible.

Install

From PyPI:

pip install temail

From source:

git clone https://github.com/0xbad4/temail
cd temail
pip install -e .

Or install just the dependencies and run the module directly:

pip install -r requirements.txt
python3 -m temail

Windows also needs windows-curses; it's declared as a platform-conditional dependency, so both install methods above pull it in automatically without adding anything to Linux/macOS installs.

Usage

temail                          # uses the default provider (mailtm)
temail -p 1secmail              # pick a specific provider
temail --provider guerrillamail
temail -lp                      # list all supported providers
temail --refresh 10             # poll every 10s instead of the default 20s

If you installed from source without pip install -e ., run python3 -m temail instead of temail.

Keybindings

Key Action
LEFT/RIGHT switch between messages
UP/DOWN scroll a long message body
r force a refresh
q / ESC quit

The inbox also refreshes automatically in the background on the interval set by --refresh (default 20s), so leaving temail open is enough to catch new mail as it arrives.

Supported providers

Key Service API key required
mailtm Mail.tm (API docs) No
1secmail 1secMail (API docs) No
guerrillamail Guerrilla Mail (API docs) No
tempmailio temp-mail.io (API docs) Yes - paid account, see below

All credit for the underlying mail infrastructure goes to these services; temail is a terminal client built on top of their public APIs. Please respect each provider's terms of use (rate limits, no reselling their API, and so on) - see the linked docs.

tempmailio is included as a worked example of a key-based provider (see below), not because it's free - it currently requires an active paid plan to obtain an API key. Use one of the other three for something that works out of the box.

API keys / environment variables

None of the free providers require a key. For providers that do, the key is always read from an environment variable, never passed as a CLI argument, and never stored anywhere by this tool.

Provider Env var Where to get a key
tempmailio TEMPMAILIO_API_KEY https://temp-mail.io/profile/api (paid)
export TEMPMAILIO_API_KEY="your-key-here"
temail -p tempmailio

temail -lp always shows the current list of providers along with which env var, if any, each one expects.

Adding your own provider

Providers are plain classes implementing a three-method interface, so adding a new one requires no changes to the UI.

  1. Create a file in src/temail/providers/, e.g. myservice.py:

    from __future__ import annotations
    
    import os
    from typing import List
    
    import requests
    
    from .base import Message, TempMailProvider
    
    API = "https://api.myservice.example"
    
    
    class MyServiceProvider(TempMailProvider):
        # shown to the user via --provider/-p and --list-provider
        key = "myservice"
        display_name = "MyService"
        # informational only - listed by --list-provider so users know
        # what to set. Leave empty if no key is needed.
        env_vars: List[str] = ["MYSERVICE_API_KEY"]
        # True if the provider needs a paid/registered key
        requires_key = True
    
        def __init__(self) -> None:
            super().__init__()
            api_key = os.environ.get("MYSERVICE_API_KEY")
            if self.requires_key and not api_key:
                raise RuntimeError(
                    "MyService requires an API key - set MYSERVICE_API_KEY"
                )
            self.session = requests.Session()
            if api_key:
                self.session.headers.update({"Authorization": f"Bearer {api_key}"})
    
        def create_inbox(self) -> str:
            """Create or claim a mailbox, set self.address, and return it."""
            r = self.session.post(f"{API}/inboxes", timeout=10)
            r.raise_for_status()
            self.address = r.json()["address"]
            return self.address
    
        def fetch_messages(self) -> List[Message]:
            """Return the current message list. Leave `body` empty here;
            it is loaded lazily by fetch_body, only for the message that's
            currently on screen."""
            r = self.session.get(f"{API}/inboxes/{self.address}/messages", timeout=10)
            r.raise_for_status()
            return [
                Message(
                    id=str(item["id"]),
                    sender=item["from"],
                    subject=item.get("subject") or "(no subject)",
                    date=item.get("date", ""),
                )
                for item in r.json()
            ]
    
        def fetch_body(self, message: Message) -> str:
            """Return the full plain-text body for one message."""
            r = self.session.get(f"{API}/messages/{message.id}", timeout=10)
            r.raise_for_status()
            return r.json().get("text", "(empty message)")
    
  2. Register it in src/temail/providers/__init__.py:

    from .myservice import MyServiceProvider
    
    PROVIDERS = {
        MailTmProvider.key: MailTmProvider,
        OneSecMailProvider.key: OneSecMailProvider,
        GuerrillaMailProvider.key: GuerrillaMailProvider,
        TempMailIoProvider.key: TempMailIoProvider,
        MyServiceProvider.key: MyServiceProvider,   # include here
    }
    
  3. Done. temail -p myservice now works, and myservice appears in temail -lp along with its env var requirement.

Notes:

  • The base class lives in src/temail/providers/base.py. TempMailProvider is an ABC with three abstract methods (create_inbox, fetch_messages, fetch_body) and a Message dataclass (id, sender, subject, date, body, snippet).
  • Raise on unrecoverable errors (bad or missing key, service down) in __init__ or create_inbox; the CLI catches these and prints them cleanly before the UI starts.
  • Errors raised from fetch_messages/fetch_body during the run loop are also caught and shown in the status line, so a transient network blip won't crash the session.
  • The layout in cli.py (top bar / status / body / bottom bar) is provider-agnostic by design, but nothing prevents a provider-specific tweak if a given service needs a different shape - draw and build_body_lines are plain functions you're free to extend.

License

MIT - see LICENSE.

Release files for temail 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for temail 0.1.0
File Size Uploaded
temail-0.1.0.tar.gz 16.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for temail 0.1.0
File Interpreter ABI Platform
temail-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 32.7 kB

Release files / temail-0.1.0.tar.gz

Download URL temail-0.1.0.tar.gz
Size 16.5 kB
Tags Source
SHA-256 checksum
How to use checksums
4a025958f4b4a3e4e4943782654362c2d418c8d52a3b4b8bab5d937ad1694cfe
BLAKE2b-256 checksum
How to use checksums
aa6c14fa43522a64dd60a4949d286ba9beeff8cd7216652a5eb85ec4dcfb6a14
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 18, 2026.

Transparency log

Release files / temail-0.1.0-py3-none-any.whl

Download URL temail-0.1.0-py3-none-any.whl
Size 16.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6d2ee119d45faa557373c355a1790697abf0c96f1a0051351f43d4573543806b
BLAKE2b-256 checksum
How to use checksums
5d659b7a1d634aa70e968b9f3af4e397a55e5f0e9f3057d84747b70a33b87764
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 18, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page