IMAP Downloader
A simple Python script to download all emails from an IMAP server into individual EML files, preserving the folder structure.
Features
- Downloads emails as standard
.emlfiles - Preserves IMAP folder hierarchy locally
- Extracts attachments into zip files alongside each email
- Supports SSL and STARTTLS connections
- Incremental updates using UID tracking (only download new emails)
- Multi-account support (separate folders per email address)
- Configurable download limit for testing/debugging
Requirements
- Python 3.6+
- No external dependencies (uses only standard library)
Installation
# Clone or download the script
git clone <repo-url>
cd imapdown
# Create virtual environment (optional but recommended)
python3 -m venv .venv
source .venv/bin/activate
Usage
Basic Usage
By default, the script only downloads new emails since the last run (incremental mode). On first run, it downloads everything.
# Download emails using SSL (most common)
./imapdown.py --server imap.example.com --email me@example.com --user me@example.com --password "secret" --ssl
# Using STARTTLS
./imapdown.py --server imap.example.com --email me@example.com --user me@example.com --password "secret" --starttls
# Custom port
./imapdown.py --server imap.example.com --email me@example.com --user me@example.com --password "secret" --ssl --port 12993
# Custom storage directory
./imapdown.py --server imap.example.com --email me@example.com --user me@example.com --password "secret" --ssl --store /path/to/backup
Full Download
To force a complete download of all emails (ignoring previous state):
./imapdown.py --server imap.example.com --email me@example.com --user me@example.com --password "secret" --ssl --full
Note: As a safety measure, --full will refuse to run if the download folder already contains emails. This prevents accidental duplicates. To re-download everything, first delete the folder:
rm -rf download/me@example.com/
./imapdown.py --server imap.example.com --email me@example.com --user me@example.com --password "secret" --ssl --full
Debugging/Testing
Limit the number of emails downloaded:
./imapdown.py --server imap.example.com --email me@example.com --user me@example.com --password "secret" --ssl --limit 10
Command Line Arguments
| Argument | Required | Description |
|---|---|---|
--server |
Yes | IMAP server hostname |
--email |
Yes | Email address (used for folder organization) |
--user |
Yes | Username for authentication |
--password |
Yes | Password for authentication |
--ssl |
No | Use implicit SSL/TLS (default port 993) |
--starttls |
No | Use STARTTLS (default port 143) |
--port |
No | Custom port (overrides defaults) |
--limit |
No | Maximum number of emails to download |
--full |
No | Download all emails (default: only new since last run) |
--store |
No | Directory to store downloaded emails (default: ./download) |
Note: --ssl and --starttls are mutually exclusive.
Output Structure
The default output structure (when --store is not specified):
./download/
├── user@example.com/
│ ├── .imapdown_state.json # Tracks last downloaded UID per folder
│ ├── INBOX/
│ │ ├── 123_20240115_Meeting_notes.eml
│ │ ├── 124_20240116_Report.eml
│ │ └── 124_20240116_Report.zip # Attachments (if any)
│ ├── Sent/
│ │ └── 456_20240114_RE_Question.eml
│ └── Archive/
│ └── 789_20240101_Old_email.eml
└── another@example.com/
└── ...
File Naming
Email files are named: {UID}_{date}_{subject}.eml
- UID: Unique identifier from the IMAP server
- date: Message date in
YYYYMMDD_HHMMSSformat - subject: Sanitized email subject (truncated to 50 characters)
Attachments
When an email contains attachments, they are extracted and saved in a zip file with the same base name as the .eml file but with a .zip extension.
State Tracking
The script maintains a .imapdown_state.json file in each email account's folder. This file tracks the highest downloaded UID for each IMAP folder, enabling efficient incremental updates with --update.
Example state file:
{
"INBOX": 19334,
"INBOX.Archive": 1770,
"Sent": 892
}
License
MIT