A cross-platform terminal UI for disposable / temporary email providers
Project description
temail
A terminal UI for disposable/temporary email providers. Generates a throwaway address and displays incoming mail without leaving the terminal.
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.
-
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)")
-
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 }
-
Done.
temail -p myservicenow works, andmyserviceappears intemail -lpalong with its env var requirement.
Notes:
- The base class lives in
src/temail/providers/base.py.TempMailProvideris an ABC with three abstract methods (create_inbox,fetch_messages,fetch_body) and aMessagedataclass (id,sender,subject,date,body,snippet). - Raise on unrecoverable errors (bad or missing key, service down) in
__init__orcreate_inbox; the CLI catches these and prints them cleanly before the UI starts. - Errors raised from
fetch_messages/fetch_bodyduring 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 -drawandbuild_body_linesare plain functions you're free to extend.
License
MIT - see LICENSE.
Project details
Release history Release notifications | RSS feed
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 temail-0.1.0.tar.gz.
File metadata
- Download URL: temail-0.1.0.tar.gz
- Upload date:
- Size: 16.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a025958f4b4a3e4e4943782654362c2d418c8d52a3b4b8bab5d937ad1694cfe
|
|
| MD5 |
ea3252add861ab6dee136e44858f76ba
|
|
| BLAKE2b-256 |
aa6c14fa43522a64dd60a4949d286ba9beeff8cd7216652a5eb85ec4dcfb6a14
|
Provenance
The following attestation bundles were made for temail-0.1.0.tar.gz:
Publisher:
publish.yml on 0xbad4/temail
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
temail-0.1.0.tar.gz -
Subject digest:
4a025958f4b4a3e4e4943782654362c2d418c8d52a3b4b8bab5d937ad1694cfe - Sigstore transparency entry: 2194996394
- Sigstore integration time:
-
Permalink:
0xbad4/temail@065a3d6a16e846c794ce8776364d540c27320745 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/0xbad4
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@065a3d6a16e846c794ce8776364d540c27320745 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file temail-0.1.0-py3-none-any.whl.
File metadata
- Download URL: temail-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6d2ee119d45faa557373c355a1790697abf0c96f1a0051351f43d4573543806b
|
|
| MD5 |
802176d922b5f8bde4b17144604e9591
|
|
| BLAKE2b-256 |
5d659b7a1d634aa70e968b9f3af4e397a55e5f0e9f3057d84747b70a33b87764
|
Provenance
The following attestation bundles were made for temail-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on 0xbad4/temail
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
temail-0.1.0-py3-none-any.whl -
Subject digest:
6d2ee119d45faa557373c355a1790697abf0c96f1a0051351f43d4573543806b - Sigstore transparency entry: 2194996397
- Sigstore integration time:
-
Permalink:
0xbad4/temail@065a3d6a16e846c794ce8776364d540c27320745 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/0xbad4
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@065a3d6a16e846c794ce8776364d540c27320745 -
Trigger Event:
workflow_dispatch
-
Statement type: