Skip to main content

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

  1. Generate API token: https://app.fastmail.com/settings/security/tokens
  2. Select permissions (Read mail, Write mail, etc.)
  3. 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

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jmap_engine-0.3.0.tar.gz (21.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jmap_engine-0.3.0-py3-none-any.whl (17.5 kB view details)

Uploaded Python 3

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

Hashes for jmap_engine-0.3.0.tar.gz
Algorithm Hash digest
SHA256 cb8c7cc55786d5b75d9b9968bf5337d9eef74d787b707caebf825d5a7a25f682
MD5 dcc87cc7147a81aed10627f07bc47209
BLAKE2b-256 8e905c802c57dd0a9ba81dce229313c9cfb4ebf1c41666a0b9843154e40eeba9

See more details on using hashes here.

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

Hashes for jmap_engine-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9dfce5f353edd8e15ab4b2cb094dd1572725bc4bad66a4e2d3d8d67edba18061
MD5 533ff7d9043c4e619207ef13b2456e02
BLAKE2b-256 503f5b809c1861e0a3c5225e0ef4957c55de14256fa486928e06407d4ab9d27f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page