Local Store
This guide outlines a robust workflow for mirroring emails from a remote IMAP server to a local store archive, and archiving old emails to local storage.
IMAP stands for Internet Message Access Protocol, a standard protocol that lets you access and manage your emails on a remote server from multiple devices, keeping everything synchronized (reading, deleting, organizing) across your phone, computer, and webmail.
The core principle is to maintain a local mirror of your remote mailbox using mbsync, perform the archival (moving files) on the local mirror, and then use mbsync again to propagate the local changes (the "deletions" from the mirrored folder) back to the remote server.
Prerequisites
isyncInstalled: You must haveisync(which provides thembsynccommand) installed on your system.
- mbsync/isync
- notmuch
brew install isyncCreate config file
- Configured
isyncrc: A working~/.config/isyncrcfile must be set up for the target email account. The configuration must includeExpunge Bothto ensure that deletions on the local mirror are synced to the remote server.
Create either file is acceptable:
~/.mbsyncrc(older style but acceptable)~/.config/isyncrcI use this config file
Example isyncrc Channel configuration:
Channel twine
Far :twine-remote:
Near :twine-local:
Patterns *
Sync All
Expunge Both # <-- This is critical for the workflow
Create Near
Remove Near
SyncState *Making the directories
Create a folder as the local store for each email account.
~/.maildir/twine
~/.maildir/soundfreaq
~/.maildir/biaget下面我们以 twine 为例进行配置。
Directory Structure
~/.maildir/
├── twine/ # Active IMAP sync folder (mbsync manages this)
│ ├── INBOX/
│ ├── Sent/
│ ├── Drafts/
│ └── Trash/
├── 2025/ # Local archive for 2025 emails (YOU manage this)
│ ├── cur/
│ ├── new/
│ └── tmp/
└── 2026/ # Local archive for 2026+ emails (YOU manage this)
├── cur/
├── new/
└── tmp/Key Point: Only twine/ is synced with the remote IMAP server. Archives (2025/, 2026/) are local-only.
Why Archive?
| Problem | Solution |
|---|---|
| IMAP storage quota filling up | Move old emails to local archives |
| Slow mailbox performance | Keep only recent emails synced |
| Need to retain old emails for reference | Local archives remain accessible in NeoMutt |
| mbsync syncs everything | Archives are excluded from sync |
The Archiving Process
Step 1: Perform a Full Initial Sync
Before making any changes, ensure your local mail mirror is perfectly up-to-date with the remote server. This is a critical safety step.
Run mbsync for your account (replace twine with your channel name if different):
mbsync twineWait for this command to complete successfully. Your local ~/.maildir/twine/ directory now mirrors the remote server.
Step 2: Create the Local Archive Folder
Create a new directory on your local machine to store the archived emails. It's important to create it in the Maildir format, which requires cur, new, and tmp subdirectories.
# Create an archive folder for emails from 2025
mkdir -p ~/.maildir/2025/{cur,new,tmp}Step 3: Move Emails Locally
Understanding Maildir Timestamps
Maildir filenames start with a Unix timestamp (seconds since 1970-01-01):
1769655740.80796_1.AX-Mac-mini,U=429:2,S
│
└─┬─┘
│
Timestamp = 1769655740 → Thu Jan 29, 2026 11:02:20 CSTConvert timestamps to dates:
# Single timestamp
date -r 1769655740
# Preview all emails with dates in INBOX
for f in ~/.maildir/twine/INBOX/cur/*; do
ts=$(basename "$f" | cut -d. -f1)
echo "$ts → $(date -r "$ts" '+%Y-%m-%d')"
done | head -20Common cutoff timestamps:
| Archive Date | Cutoff Timestamp | Description |
|---|---|---|
| End of 2025 | 1735689600 | Emails before Jan 1, 2026 |
| End of Jan 2026 | 1769938460 | Emails before Feb 1, 2026 |
| End of Feb 2026 | 1772530800 | Emails before Mar 1, 2026 |
Calculate your own:
date -j -f "%Y-%m-%d %H:%M:%S" "2026-02-01 00:00:00" +%sMethod A: Manual Method using Yazi (File Manager)
If you prefer visual file browsing:
- Open Yazi (or Finder) and navigate to
~/.maildir/twine/INBOX/cur/ - Sort by name (filenames are timestamped, so oldest first)
- Select emails from January 2026 and earlier
- Move (not copy) selected files to
~/.maildir/2026/cur/ - Repeat for
twine/INBOX/new/→2026/new/if any unread old emails exist
⚠️ Warning: Always move, never copy. Copying will cause duplicates and mbsync may re-upload them to the server.
Method B: Terminal Commands
Preview what will be moved:
# Emails before Feb 1, 2026 (timestamp 1769938460)
CUTOFF=1769938460
echo "=== Emails to be archived ==="
count=0
for f in ~/.maildir/twine/INBOX/cur/*; do
ts=$(basename "$f" | cut -d. -f1)
if [ "$ts" -lt "$CUTOFF" ]; then
echo " $(date -r "$ts" '+%Y-%m-%d') : $(basename "$f" | head -c 50)..."
count=$((count + 1))
fi
done
echo "Total: $count emails"Execute the move:
CUTOFF=1769938460 # Adjust based on your needs
# Move from cur/
for f in ~/.maildir/twine/INBOX/cur/*; do
ts=$(basename "$f" | cut -d. -f1)
if [ "$ts" -lt "$CUTOFF" ]; then
mv "$f" ~/.maildir/2026/cur/
fi
done
# Move from new/ (if any unread old emails)
for f in ~/.maildir/twine/INBOX/new/*; do
[ -f "$f" ] || continue
ts=$(basename "$f" | cut -d. -f1)
if [ "$ts" -lt "$CUTOFF" ]; then
mv "$f" ~/.maildir/2026/new/
fi
done
echo "Archive complete!"Verify the move:
# Count remaining in twine
echo "twine/INBOX/cur: $(ls -1 ~/.maildir/twine/INBOX/cur | wc -l)"
echo "twine/INBOX/new: $(ls -1 ~/.maildir/twine/INBOX/new | wc -l)"
# Count archived
echo "2026/cur: $(ls -1 ~/.maildir/2026/cur | wc -l)"
echo "2026/new: $(ls -1 ~/.maildir/2026/new | wc -l)"Method C: Automation Script
Create a reusable archive script:
#!/bin/bash
# ~/.local/bin/maildir-archive
# Usage: maildir-archive 2026-02-01
set -e
if [ -z "$1" ]; then
echo "Usage: $0 <cutoff-date>"
echo "Example: $0 2026-02-01"
exit 1
fi
CUTOFF_DATE="$1"
CUTOFF_TS=$(date -j -f "%Y-%m-%d" "$CUTOFF_DATE" +%s)
ARCHIVE_DIR="$HOME/.maildir/2026"
echo "Archiving emails before $CUTOFF_DATE (timestamp < $CUTOFF_TS)"
# Create archive structure if needed
mkdir -p "$ARCHIVE_DIR"/{cur,new,tmp}
# Archive from INBOX
for folder in INBOX Sent Drafts; do
src="$HOME/.maildir/twine/$folder"
[ -d "$src/cur" ] || continue
echo "Processing $folder/cur..."
count=0
for f in "$src/cur"/*; do
[ -f "$f" ] || continue
ts=$(basename "$f" | cut -d. -f1)
if [ "$ts" -lt "$CUTOFF_TS" ]; then
mv "$f" "$ARCHIVE_DIR/cur/"
count=$((count + 1))
fi
done
echo " Moved $count emails"
done
echo "Done! Run 'mbsync twine' to sync changes to server."Make it executable:
chmod +x ~/.local/bin/maildir-archiveUsage:
# Archive all emails before February 2026
maildir-archive 2026-02-01
# Archive all emails before March 2026
maildir-archive 2026-03-01Step 4: Propagate Deletions to the Remote Server
This is the final and irreversible step. Run mbsync again.
mbsync twinembsync will detect that hundreds of files are missing from your local Near mirror (~/.maildir/twine/INBOX). Because of the Expunge Both setting, it will interpret this as a command to delete those same emails from the Far remote server.
Once the command finishes, the old emails are now gone from the server and reside safely in your local archive.
Access the Archives in NeoMutt
Account Config with Local Archives
Update your maildir-twine config to add archives to the sidebar with visual labels:
# Active folders (polled for new mail)
mailboxes -label "📥 INBOX" -notify -poll "+INBOX"
# Standard folders (no poll, shown in sidebar)
mailboxes -label "📤 Sent" -nonotify "+Sent" \
-label "📝 Drafts" -nonotify "+Drafts" \
-label "🗑️ Trash" -nonotify "+Trash"
# Archive folders (local only, no sync)
mailboxes -label "📁 2025" -nonotify "~/.maildir/2025" \
-label "📁 2026" -nonotify "~/.maildir/2026"Sidebar now shows:
│ 📥 INBOX │ 15
│ 📤 Sent │ 0
│ 📝 Drafts │ 3
│ 🗑️ Trash │ 0
│ 📁 2025 │ 450
│ 📁 2026 │ 120Quick Navigation Macros
Add these to your config for instant archive access:
# Press '25' for 2025 archive, '26' for 2026 archive
bind index,pager 2 noop
macro index,pager 25 "<change-folder>~/.maildir/2025<enter>" "Go to 2025 archive"
macro index,pager 26 "<change-folder>~/.maildir/2026<enter>" "Go to 2026 archive"Using the Archives in NeoMutt
| Action | Key | Description |
|---|---|---|
| Toggle sidebar | \ (backslash) | Show/hide folder list |
| Navigate folders | Ctrl+Up/Down | Move through sidebar |
| Open folder | Enter | View selected folder's emails |
| Quick archive | 25 / 26 | Jump to 2025/2026 directly |
| Change folder | C | Browse all folders |
| Return to INBOX | q (until back) | Navigate back to main inbox |
Maintenance & Best Practices
Yearly Archive Rotation
At the start of each year, create a new archive:
# January 2027: Create 2027 archive
mkdir -p ~/.maildir/2027/{cur,new,tmp}
# Add to maildir-twine config:
mailboxes -label "📁 2027" -nonotify "~/.maildir/2027"Backup Your Archives
Archives are local-only, so backup is critical:
# Time Machine (macOS) - automatic if ~/.maildir is included
# Or manual backup to external drive
rsync -av ~/.maildir/2025/ /Volumes/Backup/maildir-archives/2025/
rsync -av ~/.maildir/2026/ /Volumes/Backup/maildir-archives/2026/Troubleshooting
| Issue | Solution |
|---|---|
| Archives don't appear in sidebar | Check paths are absolute (~/.maildir/2025 not +2025) |
| mbsync tries to sync archives | Ensure only twine/ is in mbsync config |
| Emails reappear after mbsync | You copied instead of moved; delete originals |
| NeoMutt shows "unable to open mailbox" | Verify folder structure: mkdir -p folder/{cur,new,tmp} |
Disk Space Monitoring
# Check archive sizes
du -sh ~/.maildir/2025 ~/.maildir/2026 ~/.maildir/twine
# Find largest emails in archive
find ~/.maildir/2026/cur -type f -exec du -h {} + | sort -rh | head -20