A Python library to interact with local Mozilla Thunderbird profiles and mail client data on Linux.
Project description
pythonbird
A lightweight, zero-dependency Python library for interacting with local Mozilla Thunderbird profiles, mailboxes, address books, and native compose windows on Linux.
Features
- Profile Auto-Detection: Detects standard, Snap, and Flatpak Thunderbird profile directories.
- Manual Profile Selection: Allows applications to work with a specific profile or a backed-up profile directory.
- Preference Parsing: Reads configured email accounts and supported values from
prefs.js. - Local Mail Reader: Reads messages from Thunderbird Mbox files.
- Folder Discovery: Lists and resolves local and account mail folders.
- Message Search: Filters by sender, recipient, subject, content, date, and attachments.
- Typed Models: Returns
Message,Attachment, andContactobjects. - Attachment Extraction: Inspects and saves files attached to messages.
- Export: Saves messages as EML or exports folders to JSON.
- High-Level API: Groups profile, mail, contacts, search, compose, and export operations in
Thunderbird. - Memory-Efficient Iteration: Supports reading large mailboxes without loading every message into memory.
- MIME Decoding: Decodes encoded headers, declared character sets, plain-text bodies, and HTML bodies.
- Address Book Access: Reads contacts from Thunderbird SQLite address books in read-only mode.
- Native Compose Window: Opens a Thunderbird compose window with a recipient, subject, body, and optional attachment.
- Safe Process Launching: Starts Thunderbird without passing message fields through a system shell.
Documentation
See the complete Developer Guide and API Reference.
Release history is available in CHANGELOG.md.
Requirements
- Linux
- Python 3.9 or newer
- Mozilla Thunderbird for compose-window functionality
Reading an explicitly supplied profile directory does not require Thunderbird to be installed. Opening a compose window requires an available Thunderbird command.
Installation
Using Poetry
poetry add pythonbird
Using pip
pip install pythonbird
Quick Start
The recommended API in version 0.2.0 uses one high-level object:
from pythonbird import Thunderbird
tb = Thunderbird()
print(tb.accounts())
print(tb.folders())
for message in tb.messages("Inbox", limit=20):
print(message.subject, message.sender)
results = tb.search(
"Inbox",
subject="report",
has_attachments=True,
)
for attachment in results[0].attachments:
attachment.save("downloads/")
tb.export_json("inbox.json", folder="Inbox")
The low-level ThunderbirdLinux, ThunderbirdMail, and
ThunderbirdContacts APIs from version 0.1.x remain available.
from pythonbird import (
ThunderbirdContacts,
ThunderbirdLinux,
ThunderbirdMail,
)
# Automatically detect the active Thunderbird profile.
tb = ThunderbirdLinux()
print(f"Active profile: {tb.profile_dir}")
print(f"Configured accounts: {tb.get_mail_accounts()}")
# Read up to 100 messages from the local Inbox.
mail_manager = ThunderbirdMail(tb)
messages = mail_manager.get_local_inbox_messages(limit=100)
for message in messages:
print(f"From: {message['from']}")
print(f"Subject: {message['subject']}")
print(f"Body: {message['body'][:100]}")
print()
# Read contacts from abook.sqlite.
contact_manager = ThunderbirdContacts(tb)
contacts = contact_manager.get_all_contacts()
for contact in contacts:
print(f"{contact['name']}: {contact['email']}")
# Open a native Thunderbird compose window.
tb.open_compose_window(
to="developer@example.com",
subject="Draft created with pythonbird",
body="Hello from pythonbird!",
)
Using a Specific Profile
Automatic profile detection is used by default:
tb = ThunderbirdLinux()
A profile can also be supplied explicitly:
tb = ThunderbirdLinux(
profile_dir="/home/user/.thunderbird/example.default-release",
)
This is useful when:
- multiple profiles exist;
- Thunderbird uses a custom profile location;
- a backed-up profile needs to be inspected;
- tests should not use the real user profile.
The launch command can also be supplied explicitly:
tb = ThunderbirdLinux(
profile_dir="/path/to/profile",
command=["flatpak", "run", "org.mozilla.Thunderbird"],
)
Reading Mail
Read the Local Inbox
mail_manager = ThunderbirdMail(tb)
messages = mail_manager.get_local_inbox_messages(limit=50)
Each message is returned as a dictionary:
{
"id": 0,
"from": "Sender <sender@example.com>",
"to": "Recipient <recipient@example.com>",
"subject": "Message subject",
"date": "Fri, 10 Jul 2026 12:00:00 +0300",
"body": "Preferred plain-text body",
"text_body": "Plain-text body",
"html_body": "<p>HTML body</p>",
}
Iterate Over a Large Inbox
for message in mail_manager.iter_local_inbox_messages():
print(message["subject"])
This avoids creating a list containing every message in memory.
Read Another Mbox File
messages = mail_manager.get_mbox_messages(
"/home/user/.thunderbird/profile/Mail/Local Folders/Sent",
limit=100,
)
An arbitrary Mbox file can also be iterated:
for message in mail_manager.iter_mbox_messages(
"/path/to/mailbox",
):
print(message["subject"])
Reading Contacts
contact_manager = ThunderbirdContacts(tb)
contacts = contact_manager.get_all_contacts()
By default, contacts are read from:
<profile>/abook.sqlite
A different database can be supplied:
contacts = contact_manager.get_all_contacts(
database_path="/path/to/address-book.sqlite",
)
Database and schema errors raise ThunderbirdContactsError by default.
To return an empty list instead:
contacts = contact_manager.get_all_contacts(strict=False)
Opening a Compose Window
tb.open_compose_window(
to="friend@example.com",
subject="Report",
body="The report is attached.",
attachment_path="/home/user/Documents/report.pdf",
)
The attachment must exist. Otherwise, FileNotFoundError is raised.
Thunderbird is launched without shell=True.
Error Handling
from pythonbird import (
ThunderbirdContacts,
ThunderbirdContactsError,
ThunderbirdLinux,
)
try:
tb = ThunderbirdLinux()
contacts = ThunderbirdContacts(tb).get_all_contacts()
except FileNotFoundError as error:
print(f"Required profile, executable, or file was not found: {error}")
except PermissionError as error:
print(f"Access was denied: {error}")
except ThunderbirdContactsError as error:
print(f"Address book could not be read: {error}")
Running Tests
If Poetry dependencies are already installed:
poetry run python -m pytest -v
If the Poetry environment is already activated:
python -m pytest -v
The tests use temporary mock profiles and do not read the user's real Thunderbird profile.
Development Checks
Format the code:
poetry run black .
Run linting:
poetry run flake8 pythonbird tests
Run tests:
poetry run python -m pytest -v
Build the package:
poetry build
Project Structure
pythonbird/
├── pythonbird/
│ ├── __init__.py
│ ├── core.py
│ ├── mail.py
│ └── contacts.py
├── tests/
│ ├── test_core.py
│ ├── test_compose.py
│ ├── test_contacts.py
│ └── test_mail_encoding.py
├── CHANGELOG.md
├── GUIDE.md
├── LICENSE
├── README.md
├── poetry.lock
└── pyproject.toml
Safety
Pythonbird is designed to avoid modifying Thunderbird profile data:
- SQLite address books are opened in read-only mode;
- mailbox messages are read without intentionally modifying their contents;
- Thunderbird is launched without
shell=True; - attachment paths are validated before opening the compose window.
Applications should still keep backups of important Thunderbird profiles. No library can guarantee zero risk when files may be changed concurrently by another process.
Version
Current version: 0.2.0
License
This project is licensed under the MIT 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 pythonbird-0.2.0.tar.gz.
File metadata
- Download URL: pythonbird-0.2.0.tar.gz
- Upload date:
- Size: 14.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
873d85bfebc3a6b84fe80a14cdeee617a3168eee7be10d504dac82d769696bb0
|
|
| MD5 |
9b739841a5cb8e2f99bf5762e6864e8b
|
|
| BLAKE2b-256 |
04e171798f19412c5160d8bc14297c79834c4a7dfe8f399f347d718485218fb1
|
File details
Details for the file pythonbird-0.2.0-py3-none-any.whl.
File metadata
- Download URL: pythonbird-0.2.0-py3-none-any.whl
- Upload date:
- Size: 14.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1e44f87211afabac04b3a37642e913685b375c38314c24b23f018393fa1eaa2f
|
|
| MD5 |
afb056246bd3b6f83f6228597781424e
|
|
| BLAKE2b-256 |
8185053c6407ff57a5d570f94b691320113312eb9a22ddf0f2c4b34c9663d7a6
|