Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
768 changes: 431 additions & 337 deletions CLAUDE.md

Large diffs are not rendered by default.

51 changes: 44 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@
[![Go Report Card](https://goreportcard.com/badge/github.com/taskinen/mailboxzero)](https://goreportcard.com/report/github.com/taskinen/mailboxzero)
[![Made with Go](https://img.shields.io/badge/Made%20with-Go-1f425f.svg)](https://go.dev/)

A Go-based web application that helps you clean up your Fastmail inbox by finding and archiving similar emails using JMAP protocol.
A Go-based web application that helps you clean up your email inbox by finding and archiving similar emails. Supports **JMAP** (Fastmail) and **IMAP** (Gmail, Outlook, etc.) protocols.

<img width="1457" height="1169" alt="SCR-20250827-psxl" src="https://github.com/user-attachments/assets/2f1fe630-5ba7-4c8a-a610-6f32388654b5" />

## Features

- **Multiple Protocols**: JMAP (Fastmail) ✅ and IMAP (Gmail, Outlook, etc.) ✅
- **Safe Operations**: Built-in dry run mode prevents accidental changes
- **Dual-pane Interface**: View inbox on left, grouped similar emails on right
- **Smart Similarity Matching**: Fuzzy matching based on subject, sender, and email content
- **Adjustable Similarity Threshold**: Fine-tune matching with a percentage slider
- **Selective Archiving**: Choose which emails to archive with confirmation dialog
- **Individual Email Selection**: Select specific emails to find similar matches
- **Mock Mode**: Test without any email account credentials

## Safety Features

Expand All @@ -30,8 +32,10 @@ A Go-based web application that helps you clean up your Fastmail inbox by findin
### Prerequisites

- Go 1.21 or later
- Fastmail account with JMAP access
- Fastmail API token (generated from account settings)
- Email account with one of:
- **JMAP**: Fastmail account with API token ✅
- **IMAP**: Gmail, Outlook, or any IMAP provider ✅
- Or use **Mock Mode** for testing (no account required)

### Installation

Expand All @@ -45,13 +49,43 @@ A Go-based web application that helps you clean up your Fastmail inbox by findin
cp config.yaml.example config.yaml
```

4. Edit `config.yaml` with your Fastmail API token:
4. Edit `config.yaml` with your email provider credentials:

**For JMAP (Fastmail):**
```yaml
protocol: "jmap"
jmap:
endpoint: "https://api.fastmail.com/jmap/session"
api_token: "your-api-token-here"

# IMPORTANT: Set to false only when ready for real changes
dry_run: true
```

**For IMAP (Gmail, Outlook, etc.):**
```yaml
protocol: "imap"
imap:
host: "imap.gmail.com"
port: 993
username: "your-email@gmail.com"
password: "your-app-password"
use_tls: true
archive_folder: "[Gmail]/All Mail"
dry_run: true
```

**For Mock Mode (no credentials needed):**
```yaml
# JMAP Mock Mode
protocol: "jmap"
mock_mode: true
dry_run: true
```

Or for IMAP mock mode:
```yaml
# IMAP Mock Mode
protocol: "imap"
mock_mode: true
dry_run: true
```

Expand Down Expand Up @@ -166,7 +200,10 @@ mailboxzero/
├── config.yaml # Configuration file
├── internal/
│ ├── config/ # Configuration handling
│ ├── jmap/ # JMAP client implementation
│ ├── protocol/ # Generic protocol abstraction layer
│ ├── providers/ # Email protocol implementations
│ │ ├── jmap/ # JMAP client (Fastmail)
│ │ └── imap/ # IMAP client (Gmail, Outlook, etc.)
│ ├── server/ # Web server and API handlers
│ └── similarity/ # Email similarity algorithms
└── web/
Expand Down
63 changes: 63 additions & 0 deletions config-imap.yaml.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Mailbox Zero IMAP Configuration Example
# This example shows how to configure Mailbox Zero to work with IMAP providers
# Copy this file to config.yaml and update with your settings

server:
port: 8080
host: "localhost"

# Protocol must be set to "imap"
protocol: "imap"

# IMAP Configuration
imap:
# Gmail IMAP settings
host: "imap.gmail.com"
port: 993
username: "your-email@gmail.com"
password: "your-app-password" # Generate at https://myaccount.google.com/apppasswords
use_tls: true
archive_folder: "[Gmail]/All Mail" # Gmail's archive folder

# Outlook/Office 365 settings (uncomment to use)
# host: "outlook.office365.com"
# port: 993
# username: "your-email@outlook.com"
# password: "your-password"
# use_tls: true
# archive_folder: "Archive"

# Generic IMAP settings (uncomment to use)
# host: "mail.example.com"
# port: 993
# username: "user@example.com"
# password: "password"
# use_tls: true
# archive_folder: "Archive"

# JMAP section not needed for IMAP
jmap:
endpoint: ""
api_token: ""

# IMPORTANT SAFETY FEATURE
# Set to false to enable actual archiving operations
# Keep as true for testing to prevent any modifications to your mailbox
dry_run: true

# Default similarity threshold (0-100)
default_similarity: 75

# MOCK MODE - Set to true to use sample data without connecting to real IMAP server
# Perfect for testing the application without credentials
mock_mode: false

# Notes:
# - Gmail requires app-specific passwords if 2FA is enabled
# - Some providers may use different archive folder names:
# - Gmail: "[Gmail]/All Mail"
# - Outlook: "Archive"
# - Generic: "Archive" or "Archived"
# - If your archive folder doesn't exist, create it in your email client first
# - Port 993 is standard for IMAP over TLS
# - Port 143 is for IMAP without TLS (not recommended)
30 changes: 25 additions & 5 deletions config-mock.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,38 @@ server:
port: 8080
host: "localhost"

# JMAP settings are not required in mock mode
# Protocol selection - "jmap" or "imap"
# In mock mode, this determines which mock client is used
# Currently only JMAP mock is fully implemented
protocol: "jmap"

# Credentials are not required in mock mode
jmap:
endpoint: ""
api_token: ""

imap:
host: ""
port: 993
username: ""
password: ""
use_tls: true
archive_folder: "Archive"

# IMPORTANT: Keep dry_run true in mock mode for safety
dry_run: true

# Default similarity threshold (0-100)
default_similarity: 75

# MOCK MODE - Set to true to use sample data instead of real Fastmail account
# When enabled, no real JMAP connection is made and sample emails are used
# Perfect for testing and development
mock_mode: true
# MOCK MODE - Set to true to use sample data instead of real email account
# When enabled, no real connection is made and realistic sample emails are used
# Perfect for testing, development, and demonstrations without any credentials
mock_mode: true

# Notes:
# - Mock mode provides 40+ realistic sample emails with similar groups
# - Archive operations are simulated (emails are marked as archived in memory)
# - No network connection is made in mock mode
# - Great for testing the similarity matching algorithm
# - IMAP mock mode is planned for future implementation
21 changes: 18 additions & 3 deletions config.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,25 @@ server:
port: 8080
host: "localhost"

# Protocol selection: "jmap" or "imap"
# Defaults to "jmap" if not specified (backward compatible)
protocol: "jmap"

# JMAP Configuration (for Fastmail and other JMAP providers)
jmap:
endpoint: "https://api.fastmail.com/jmap/session"
api_token: "" # Set your Fastmail API token (generate at Settings → Privacy & Security → Integrations)

# IMAP Configuration (for Gmail, Outlook, and other IMAP providers)
# Only required if protocol is set to "imap"
imap:
host: "imap.gmail.com"
port: 993
username: "" # Your email address
password: "" # Your password or app-specific password
use_tls: true
archive_folder: "Archive" # Folder name for archived emails (Gmail uses "[Gmail]/All Mail")

# IMPORTANT SAFETY FEATURE
# Set to false to enable actual archiving operations
# Keep as true for testing to prevent any modifications to your mailbox
Expand All @@ -17,7 +32,7 @@ dry_run: true
# Default similarity threshold (0-100)
default_similarity: 75

# MOCK MODE - Set to true to use sample data instead of real Fastmail account
# When enabled, no real JMAP connection is made and sample emails are used
# Perfect for testing and development
# MOCK MODE - Set to true to use sample data instead of real email account
# When enabled, no real connection is made and sample emails are used
# Perfect for testing and development without credentials
mock_mode: false
6 changes: 6 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ module mailboxzero
go 1.21

require (
github.com/emersion/go-imap v1.2.1
github.com/gorilla/mux v1.8.1
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
golang.org/x/text v0.14.0 // indirect
)
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjTA=
github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY=
github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 h1:hH4PQfOndHDlpzYfLAAfl63E8Le6F2+EL/cdhlkyRJY=
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
Loading