Python library for viewing and sending emails through the JMAP protocol
Project description
JMAP Engine
Python library for email automation via JMAP protocol (RFC 8620, RFC 8621).
Build bots, integrations, and automation tools for email. Works with Fastmail, Cyrus, Stalwart, and other JMAP servers.
Installation
pip install jmap-engine
Quick Start
from jmap_engine import JMAPClient, Email, EmailAddress, EmailBodyPart
# Connect (auto-detects Fastmail API keys starting with 'fmu')
client = JMAPClient(
base_url='https://api.fastmail.com',
username='you@fastmail.com',
password='fmu1-your-api-key'
)
client.connect()
# List mailboxes
mailboxes = client.get_mailboxes()
for mb in mailboxes:
print(f"{mb['name']}: {mb.get('totalEmails', 0)} emails")
# Get inbox emails
inbox = next((mb for mb in mailboxes if mb['role'] == 'inbox'), None)
email_ids = client.query_emails(
filter={'inMailbox': inbox['id']},
limit=10
)
emails = client.get_emails(email_ids, properties=['subject', 'from', 'preview'])
for email in emails:
print(f"{email['subject']} - {email['from'][0]['email']}")
# Send email
email = Email(
from_=[EmailAddress(email='you@fastmail.com', name='Your Name')],
to=[EmailAddress(email='recipient@example.com')],
subject='Test Email',
text_body=[EmailBodyPart(type='text/plain', value='Hello!')],
html_body=[EmailBodyPart(type='text/html', value='<p>Hello!</p>')]
)
submission = client.send_email(email.to_dict())
print(f"Sent! ID: {submission['id']}")
Features
Core Operations:
- View and query emails with filters
- Send emails (auto-detects sender identity)
- Manage mailboxes and folders
- Navigate mailbox hierarchies
JMAP Protocol:
- RFC 8620 (JMAP Core)
- RFC 8621 (JMAP Mail)
- Bearer token auth (Fastmail API keys)
- Session discovery
Common Operations
Get Available Identities
identities = client.get_identities()
for identity in identities:
print(f"{identity['name']} <{identity['email']}>")
Query Emails with Filters
from jmap_engine import EmailQuery
from datetime import datetime, timedelta
query = EmailQuery(
in_mailbox='inbox-id',
after=datetime.now() - timedelta(days=7),
has_keyword='$seen',
from_='important@example.com'
)
email_ids = client.query_emails(filter=query.to_dict(), limit=50)
Navigate Mailbox Tree
tree = client.get_mailbox_tree()
tree.print_tree()
# Output:
# 📥 Inbox [150 total, 5 unread]
# └─ 📂 Projects [20 total, 2 unread]
inbox = tree.get_by_role('inbox')
print(f"{inbox.total_emails} emails, {inbox.unread_emails} unread")
Check API Key Permissions
client.print_permissions()
# Shows what your API key can access:
# ✅ CAN 📧 Read emails
# ✅ CAN 📤 Send emails
# ❌ CANNOT 📅 Manage calendars
Fastmail Setup
- Generate API token: https://app.fastmail.com/settings/security/tokens
- Select permissions (Read mail, Write mail, etc.)
- Copy token (starts with
fmu1-)
client = JMAPClient(
base_url='https://api.fastmail.com',
username='you@fastmail.com',
password='fmu1-your-token' # Auto-detected as Bearer auth
)
Use Cases
- Automation: Auto-respond, filter, organize emails
- Bots: Process incoming emails, extract data
- Integrations: Connect email to Slack, Discord, databases
- Analytics: Analyze patterns, extract metrics
- Monitoring: Trigger alerts for specific emails
- Backup: Archive emails to JSON/database
- Testing: Verify emails in test suites
API Reference
JMAPClient
client = JMAPClient(base_url, username, password, timeout=30)
client.connect() # Discover session
# Mailboxes
mailboxes = client.get_mailboxes(account_id=None)
tree = client.get_mailbox_tree(account_id=None)
# Identities
identities = client.get_identities(account_id=None)
# Query emails
email_ids = client.query_emails(filter=None, sort=None, limit=None, account_id=None)
# Get emails
emails = client.get_emails(ids, properties=None, account_id=None)
# Send email
submission = client.send_email(email_dict, identity_id=None, account_id=None)
# Permissions
perms = client.get_permissions()
client.print_permissions()
Email Models
from jmap_engine import Email, EmailAddress, EmailBodyPart, EmailQuery
# Create email
email = Email(
from_=[EmailAddress(email='sender@example.com', name='Sender')],
to=[EmailAddress(email='recipient@example.com')],
cc=[...],
bcc=[...],
subject='Subject',
text_body=[EmailBodyPart(type='text/plain', value='Text content')],
html_body=[EmailBodyPart(type='text/html', value='<p>HTML</p>')],
mailbox_ids={'mailbox-id': True}, # Optional, auto-detects Sent folder
keywords={'$seen': True, '$flagged': True}
)
# Use email
email_dict = email.to_dict()
email_obj = Email.from_dict(email_dict)
text = email.get_text_content()
is_unread = email.is_unread()
JMAP Servers
- Fastmail - Commercial (JMAP creators)
- Cyrus IMAP - Open source
- Stalwart - Modern open source
- Apache James - Enterprise
Development
git clone https://github.com/cocdeshijie/jmap-engine.git
cd jmap-engine
pip install -e ".[dev]"
pytest tests/
Resources
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 jmap_engine-0.3.0.tar.gz.
File metadata
- Download URL: jmap_engine-0.3.0.tar.gz
- Upload date:
- Size: 21.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cb8c7cc55786d5b75d9b9968bf5337d9eef74d787b707caebf825d5a7a25f682
|
|
| MD5 |
dcc87cc7147a81aed10627f07bc47209
|
|
| BLAKE2b-256 |
8e905c802c57dd0a9ba81dce229313c9cfb4ebf1c41666a0b9843154e40eeba9
|
File details
Details for the file jmap_engine-0.3.0-py3-none-any.whl.
File metadata
- Download URL: jmap_engine-0.3.0-py3-none-any.whl
- Upload date:
- Size: 17.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9dfce5f353edd8e15ab4b2cb094dd1572725bc4bad66a4e2d3d8d67edba18061
|
|
| MD5 |
533ff7d9043c4e619207ef13b2456e02
|
|
| BLAKE2b-256 |
503f5b809c1861e0a3c5225e0ef4957c55de14256fa486928e06407d4ab9d27f
|