Email fetcher: one.com → Migadu migration Email Fetcher Migration: one.com → Migadu MC Task: #100395 Migration Date: 2026-05-12 14:30-15:00 UTC Verification: 12/12 atomic claims PASS (15:05 UTC) Status: Production cutover complete Overview On 2026-05-10 20:20 UTC, the CEO registered Migadu email hosting and switched MX records for alai.no and basicconsulting.no to Migadu (priority 10/20), retaining one.com as fallback (priority 100). The email-agent daemon (~/system/tools/email-agent.js) and mail-native.js IMAP client were still configured for one.com IMAP, making mail routed to Migadu invisible to John's email processing pipeline. On 2026-05-12, John executed the migration cutover: provisioned 4 new Migadu mailboxes via Admin API, rotated Bitwarden credentials, reconfigured himalaya CLI and mail-native.js to use imap.migadu.com:993 + smtp.migadu.com:465, and deployed a workaround for himalaya 1.1.0 PLAIN SASL incompatibility by forcing ImapFlow fallback (HIMALAYA_DISABLED=1 env var). Affected Components Config files: ~/.config/himalaya/config.toml — 5 accounts (john, info, alai, alem, dev) migrated from imap.one.com to imap.migadu.com; folder aliases changed from INBOX.Sent to flat Sent ~/system/tools/mail-native.js — VAULT_NAMES updated to Migadu — prefix; default imap_host/smtp_host changed to Migadu servers ~/Library/LaunchAgents/com.john.email-agent.plist — added HIMALAYA_DISABLED=1 environment variable Bitwarden items: 5 items created/updated with naming convention Migadu — Migadu — alem@alai.no Migadu — john@alai.no Migadu — john@basicconsulting.no Migadu — info@basicconsulting.no Migadu — dev@alai.no Daemons: com.john.email-agent — restarted after config changes; now connects to 6 mailboxes (5 Migadu + 1 Gmail) Backups: ~/.config/himalaya/config.toml.one-com-backup-20260512-163802 ~/Library/LaunchAgents/com.john.email-agent.plist.bak-20260512-164711 mail-native.js: revert via git diff against pre-migration commit Migadu Mailbox Provisioning Migadu mailboxes are created via Admin API using the API key from Bitwarden item migadu keyy . Create mailbox via API # Get Migadu API credentials API_KEY=$(bw get password 'migadu keyy' --session $(cat /tmp/bw-session)) DOMAIN="alai.no" # or basicconsulting.no LOCAL_PART="john" PASSWORD=$(openssl rand -base64 24) # Create mailbox curl -X POST "https://api.migadu.com/v1/domains/${DOMAIN}/mailboxes" \ -u "admin@alai.no:${API_KEY}" \ -H "Content-Type: application/json" \ -d '{ "local_part": "'"${LOCAL_PART}"'", "password": "'"${PASSWORD}"'", "may_send": true, "may_receive": true, "may_access_imap": true, "may_access_pop3": true, "may_access_managesieve": true }' # Verify creation curl "https://api.migadu.com/v1/domains/${DOMAIN}/mailboxes/${LOCAL_PART}" \ -u "admin@alai.no:${API_KEY}" Store credentials in Bitwarden # Create Bitwarden item with naming convention echo "{ \"organizationId\": null, \"folderId\": null, \"type\": 1, \"name\": \"Migadu — ${LOCAL_PART}@${DOMAIN}\", \"login\": { \"username\": \"${LOCAL_PART}@${DOMAIN}\", \"password\": \"${PASSWORD}\", \"uris\": [ { \"match\": null, \"uri\": \"imap.migadu.com\" }, { \"match\": null, \"uri\": \"smtp.migadu.com\" } ] } }" | bw encode | bw create item --session $(cat /tmp/bw-session) Evidence: See /Users/makinja/system/state/evidence/migadu-mailbox-create-20260512T083653Z.log for actual execution output of 4 mailboxes created on 2026-05-12. Bitwarden Credential Structure Naming convention: Migadu — This convention is hardcoded in ~/system/tools/mail-native.js VAULT_NAMES mapping: const VAULT_NAMES = { john: 'Migadu — john@basicconsulting.no', info: 'Migadu — info@basicconsulting.no', alai: 'Migadu — john@alai.no', alem: 'Migadu — alem@alai.no', dev: 'Migadu — dev@alai.no', gmail: 'Gmail — alembasic@gmail.com' }; List all Migadu credentials: bw list items --search 'Migadu —' --session $(cat /tmp/bw-session) | jq -r '.[] | "\(.name) (\(.id))"' End-to-End Verification Use Python imaplib to verify IMAP login and mailbox access: #!/usr/bin/env python3 import imaplib import json import subprocess def test_imap(email): # Fetch password from Bitwarden vault_name = f"Migadu — {email}" bw_session = open('/tmp/bw-session').read().strip() password = subprocess.check_output( ['bw', 'get', 'password', vault_name, '--session', bw_session], text=True ).strip() # Connect to Migadu IMAP imap = imaplib.IMAP4_SSL('imap.migadu.com', 993) imap.login(email, password) status, messages = imap.select('INBOX') if status == 'OK': msg_count = int(messages[0]) print(f"✓ {email}: INBOX OK, {msg_count} messages") else: print(f"✗ {email}: SELECT INBOX failed") imap.logout() if __name__ == '__main__': accounts = [ 'alem@alai.no', 'john@alai.no', 'john@basicconsulting.no', 'info@basicconsulting.no', 'dev@alai.no' ] for acc in accounts: test_imap(acc) Expected output: ✓ alem@alai.no: INBOX OK, 881 messages ✓ john@alai.no: INBOX OK, 0 messages ✓ john@basicconsulting.no: INBOX OK, 13 messages ✓ info@basicconsulting.no: INBOX OK, 0 messages ✓ dev@alai.no: INBOX OK, 0 messages Evidence: Verifier executed equivalent IMAP4_SSL login probes on 2026-05-12 15:05 UTC — claim C3 PASS (see /Users/makinja/system/state/evidence/mc-100395-verifier-verdict-20260512.md ). Rollback Procedure If Migadu migration must be reverted (e.g., service outage, credential issues), follow these steps: Stop email-agent daemon: launchctl unload ~/Library/LaunchAgents/com.john.email-agent.plist Restore himalaya config to one.com: cp ~/.config/himalaya/config.toml ~/.config/himalaya/config.toml.migadu-backup-$(date +%Y%m%d-%H%M%S) cp ~/.config/himalaya/config.toml.one-com-backup-20260512-163802 ~/.config/himalaya/config.toml Revert mail-native.js (verify before running): cd ~/system/tools git diff mail-native.js # Review changes git checkout HEAD -- mail-native.js # Revert to pre-migration state Remove HIMALAYA_DISABLED from LaunchAgent: cp ~/Library/LaunchAgents/com.john.email-agent.plist ~/Library/LaunchAgents/com.john.email-agent.plist.bak-$(date +%Y%m%d-%H%M%S) # Edit plist to remove HIMALAYA_DISABLED env var: plutil -replace EnvironmentVariables.HIMALAYA_DISABLED -string "" ~/Library/LaunchAgents/com.john.email-agent.plist # Or manually edit and remove the key/value pair Update Bitwarden vault names in code (if needed): If mail-native.js git revert doesn't restore old BW item names, manually edit VAULT_NAMES back to Email - pattern. Restart daemon: launchctl load ~/Library/LaunchAgents/com.john.email-agent.plist Verify connection to one.com: tail -f ~/system/logs/email-agent.log | grep -E "Connected|ERROR" Expect lines like: Connected to john (john@basicconsulting.no) within 60 seconds. Rollback time estimate: 5-10 minutes (assuming backups are intact). Known Issue: himalaya 1.1.0 PLAIN SASL vs Migadu Symptom: himalaya CLI 1.1.0 fails IMAP login to imap.migadu.com:993 with error: Error: cannot parse envelope at line 1 near column 1 Kind: MalformedMessage Root cause: himalaya 1.1.0 attempts PLAIN SASL authentication, which Migadu's IMAP server rejects or mishandles (verify before re-running). This is a known incompatibility between himalaya's IMAP library and Migadu's Dovecot configuration. Workaround: Force email-agent.js to skip himalaya and use ImapFlow (native Node.js IMAP client) by setting environment variable: EnvironmentVariables HIMALAYA_DISABLED 1 in ~/Library/LaunchAgents/com.john.email-agent.plist . Evidence: Email-agent.js log on 2026-05-12 14:48:12 shows: {"timestamp":"2026-05-12T14:48:12.896Z","service":"email-agent","level":"info","message":"[WARN] himalaya disabled for john, falling back to legacy unseen fetch"} All 6 mailboxes connected successfully via ImapFlow (claims C9/C10 PASS). Long-term fix: File upstream issue with himalaya maintainers or test downgrade to himalaya 1.0.x. Track in separate MC task. Migration Timeline Timestamp (UTC) Event 2026-05-10 20:20 CEO registered Migadu, MX records switched 2026-05-12 08:36 4 mailboxes provisioned via Migadu API (post, dev, info, john@basicconsulting) 2026-05-12 14:37 john@alai.no mailbox created 2026-05-12 14:48 email-agent cutover: himalaya disabled, ImapFlow connected to 5 Migadu + 1 Gmail 2026-05-12 14:51 First mail cycle after cutover: 3 new emails classified via Ollama 2026-05-12 15:05 Verifier subagent: 12/12 claims PASS Post-Migration State MX records: aspmx1/2.migadu.com (priority 10/20) PRIMARY, mx01.one.com (priority 100) FALLBACK Active mailboxes: 5 Migadu (alem, john×2, info, dev) + 1 Gmail (alembasic) Daemon status: com.john.email-agent running, last exit 0, connects every 3 minutes Mail processing: End-to-end verified — GitHub PR notification, GCP billing, undeliverable bounce all classified via Ollama (claim C11 PASS) one.com mailboxes: Still receiving via fallback MX prio 100 — backlog drain deferred to future MC task References MC Task: #100395 Evidence directory: /Users/makinja/system/state/evidence/ mc-100395-verifier-verdict-20260512.md — 12/12 atomic claims PASS mc-100395-migration-complete-20260512T145224Z.log — Builder summary migadu-mailbox-create-20260512T083653Z.log — API provisioning logs email-agent-migadu-cutover-20260512T145138Z.log — Daemon cutover logs Bitwarden API key: migadu keyy (search in BW vault) Migadu Admin API: https://api.migadu.com/v1/