# gmailarchiver

Archive all Gmail messages from a given calendar year to an **mbox** or **Maildir** file, then permanently delete (or trash) them from your account.

---

## Features

- Downloads every message in a year via the Gmail API (all labels, including Spam/Trash)
- Saves to standard **mbox** or **Maildir** format — importable into Thunderbird, Apple Mail, Dovecot, etc.
- **Permanently deletes** after archiving (or `--trash` to use recoverable Trash)
- Idempotent-safe: archive written to disk *before* deletion is issued
- Batch deletes (up to 1 000 IDs/call) to stay within Gmail API quotas
- Exponential back-off on transient 429/5xx errors
- Progress bars via `rich`
- `--dry-run` to count messages without downloading

---

## Setup

### 1. Google Cloud credentials

1. Go to [Google Cloud Console](https://console.cloud.google.com/apis/credentials).
2. Create a project → enable the **Gmail API**.
3. Create an **OAuth 2.0 Client ID** → type **Desktop app**.
4. Download `credentials.json` and place it at:

```
~/.gmailarchiver/credentials.json
```

Or pass `--credentials <path>` at runtime.

### 2. Install

```bash
pipx install gmailarchiver     # recommended
# or
pip install gmailarchiver
```

### 3. First run (OAuth consent)

The first invocation opens a browser tab for Google OAuth consent. After approval the token is cached at `~/.gmailarchiver/token.json`.

---

## Usage

```
gmailarchiver <year> [options]
```

### Options

| Flag | Default | Description |
|---|---|---|
| `--output / -o PATH` | `./<year>.mbox` | Archive destination |
| `--format / -f {mbox,maildir}` | `mbox` | Archive format |
| `--no-delete` | off | Archive only; keep messages in Gmail |
| `--trash` | off | Move to Trash (30-day recovery) instead of permanent delete |
| `--dry-run` | off | Count messages, do nothing else |
| `--credentials PATH` | `~/.gmailarchiver/credentials.json` | OAuth credentials |
| `--token PATH` | `~/.gmailarchiver/token.json` | Cached OAuth token |
| `--label LABEL_ID` | all mail | Restrict to label (`INBOX`, `SENT`, custom ID); repeatable |

### Examples

```bash
# Archive 2022 to mbox, permanently delete from Gmail
gmailarchiver 2022 --output ~/mail/2022.mbox

# Archive 2021 to Maildir, move to Trash instead of hard-delete
gmailarchiver 2021 --output ~/mail/2021/ --format maildir --trash

# Dry run: count 2023 messages without touching anything
gmailarchiver 2023 --dry-run

# Archive only INBOX and SENT from 2020, keep in Gmail
gmailarchiver 2020 --output ~/mail/2020.mbox --no-delete \
  --label INBOX --label SENT

# Use a specific credentials file
gmailarchiver 2022 --credentials ~/secrets/gmail_oauth.json
```

---

## Archive formats

| Format | Best for |
|---|---|
| `mbox` | Single file, easy to move/compress, Apple Mail, Thunderbird |
| `maildir` | Dovecot / Postfix import, per-message files, fast random access |

Both formats are RFC-standard and widely supported.

---

## Safety notes

- Messages are written to disk **before** any delete call is issued.
- `--trash` is the safer option if you want a 30-day grace period.
- Permanent deletion via `batchDelete` is **irreversible**.
- If the run is interrupted mid-way, re-run the same command — already-archived messages will be re-downloaded (mbox gets duplicates), but nothing is lost. Use `--no-delete` on a re-run if you only want to fill gaps, then delete manually.

---

## Gmail API quota

The default Gmail API quota is 1 billion quota units/day. Each `messages.get` call costs 5 units; `messages.batchDelete` costs 50 units per call. Archiving 50 000 messages ≈ 253 000 units — well within limits. If you hit quota, the tool backs off and retries automatically.

---

## Development

```bash
git clone https://github.com/youruser/gmailarchiver
cd gmailarchiver
pip install -e ".[dev]"
pytest
```

---

## License

Apache 2.0
