Skip to main content

solvemail

A simple Gmail / Google Workspace email client built on the official Gmail API, using the fastai/fastcore coding style.

Install

pip install solvemail

Or for development:

pip install -e .

OAuth setup

For detailed instructions on setting up Google Cloud credentials, see ezgmail's excellent documentation.

In brief:

  1. Create an OAuth Client ID (Desktop app) in Google Cloud Console and enable the Gmail API
  2. Download the client secrets JSON as credentials.json
  3. Put credentials.json next to your script (or pass its path)

On first run, solvemail will open a browser to authorize and will save token.json.

Quick start

import solvemail

solvemail.init()  # reads credentials.json + token.json in cwd

# For multiple accounts, use separate token files:
# solvemail.init(token_path='work.json')    # first run opens browser to auth
# solvemail.init(token_path='personal.json') # switch account without re-auth

# Check which account you're using
solvemail.profile().email

# solvemail exports the key API functionality through wildcard import
from solvemail import *

# Search for threads
threads = search_threads('is:unread newer_than:7d', max_results=10)

# Get thread details
t = threads[0]
for m in t.msgs():
    print(m.frm, '|', m.subj)

# Read a message
m = t.msgs()[0]
m.subj, m.frm, m.snip, m.text()

# Send an email
send(to='someone@example.com', subj='Hello', body='Hi there!')

# Create and send a reply
draft = t.reply_draft(body='Thanks!')
draft.send()

Features

Searching

# Search threads (conversations)
search_threads('from:boss@company.com', max_results=20)

# Search individual messages
search_msgs('has:attachment filename:pdf', max_results=100)

Messages

m = msg(id)           # Fetch by id
m.subj, m.frm, m.to             # Headers
m.text(), m.html()              # Body content
m.mark_read(), m.mark_unread()  # Read status
m.star(), m.unstar()            # Starred
m.archive()                     # Remove from inbox
m.trash(), m.untrash()          # Trash
m.add_labels('MyLabel')         # Add labels
m.rm_labels('INBOX')            # Remove labels

Threads

t = thread(id)        # Fetch by id
t.msgs()                        # List messages
t[0], t[-1]                     # Index into messages
t.reply_draft(body='...')       # Create reply draft
t.reply(body='...')             # Send reply directly

# Batch fetch multiple threads efficiently (one HTTP call)
threads = search_threads('in:inbox', max_results=50)
threads = get_threads(threads)

Message display

Messages render nicely in Jupyter notebooks (quotes and signatures stripped automatically).

m = t[-1]
m.body()   # Cleaned text (no quotes/signatures)
m.html()   # HTML body (falls back to text wrapped in <pre>)

# View message with headers (as dict or plain text)
view_msg(m.id)                      # Returns dict with headers + body
view_msg(m.id, as_json=False)       # Returns formatted text

# View full thread
view_thread(t.id)                   # Dict of msgid -> msg dict
view_thread(t.id, as_json=False)    # Concatenated text with separators

Inbox helpers

view_inbox(max_msgs=20)             # Batch fetch inbox messages
view_inbox_threads(max_threads=20)  # Batch fetch inbox threads
view_inbox(unread=True)             # Only unread

Labels

labels()                        # List all labels
label('INBOX')                  # Get by name or id
find_labels('project')          # Search labels
create_label('My Label')        # Create new label

Drafts

drafts()                        # List drafts
create_draft(to='...', subj='...', body='...')
reply_to_thread(thread_id, body='...')

Bulk operations

# Batch modify labels (auto-chunks, no 1000 message limit)
ids = [m.id for m in search_msgs('in:inbox')]
batch_label(ids, add=['SPAM'], rm=['INBOX'])

# Trash multiple messages
trash_msgs(ids)

# Permanently delete (requires full mail scope)
batch_delete(ids)

Testing

Set these env vars to run e2e tests against a throwaway Gmail/Workspace account:

  • GMAILX_CREDS — path to credentials.json
  • GMAILX_TOKEN — path to token.json (will be created if missing)
  • GMAILX_E2E — set to 1 to enable e2e tests
pytest -q

Development

This is a fastship project. Use ship-* commands to manage.

Credits

Inspired by ezgmail by Al Sweigart — thanks Al for the great work! The ezgmail repo also has excellent documentation on setting up Gmail API credentials.

Release files for solvemail 0.1.9

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

Source distribution (sdist)

Source distribution for solvemail 0.1.9
File Size Uploaded
solvemail-0.1.9.tar.gz 18.4 kB Details

Built distribution (wheel)

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

Total release size: 33.7 kB

Release files / solvemail-0.1.9.tar.gz

Download URL solvemail-0.1.9.tar.gz
Size 18.4 kB
Tags Source
SHA-256 checksum
How to use checksums
8701bc0603fa03261c1a4e3f1bb52591c1d8ee40d8a21a6bf6f483ef64858899
BLAKE2b-256 checksum
How to use checksums
4821a03aeb59956c1ffda65fe1c1f6efaf7d79091558a334b9ab8337a7950642
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.0

Release files / solvemail-0.1.9-py3-none-any.whl

Download URL solvemail-0.1.9-py3-none-any.whl
Size 15.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
67a913b7a81fd2cf0bdbb796efdf6de44148be8957688b619ebe015247aa109a
BLAKE2b-256 checksum
How to use checksums
3e6f500965b06f3f7f727f175bd26372d60c020c6b463602997ba4a0075edc97
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.0

Release history Release notifications | RSS feed

This release

0.1.9 This release

2 release files

0.1.8

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.0

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