#!/usr/bin/env bash # cmail-setup-finish.sh — finish Proton Mail Bridge + cmail-action setup after # Bridge first-run. Idempotent; safe to re-run after a Bridge cert rotation or # a claude-templates re-clone. # # Pre-reqs (the script aborts if any are missing): # - protonmail-bridge installed (archsetup handles it) # - You have run 'protonmail-bridge --cli', logged in, and quit at least once # (the script looks for state at ~/.config/protonmail/bridge-v3/) # - claude-templates cloned at ~/projects/claude-templates # - dotfiles stowed (~/.config/.cmailpass.gpg present) # # What it does: # 1. Decrypts ~/.config/.cmailpass.gpg → ~/.config/.cmailpass (mode 0600) # 2. Copies Bridge's self-signed cert → ~/.config/protonbridge.pem # 3. Symlinks ~/projects/claude-templates/.ai/scripts/cmail-action.py # → ~/.local/bin/cmail-action # 4. Removes the leftover ~/.config/autostart/Proton Mail Bridge.desktop # stub (it double-launches Bridge alongside the systemd user service # and throws an "orphan instance" dialog every login) # 5. Installs a wait-for-dns drop-in so Bridge doesn't spam # name-resolution errors during the early-boot DNS race # 6. Enables + starts the protonmail-bridge user service # 7. Verifies Bridge is listening on 127.0.0.1:1143 / :1025 set -euo pipefail err() { printf 'error: %s\n' "$*" >&2; exit 1; } info() { printf '==> %s\n' "$*"; } ok() { printf ' %s\n' "$*"; } # 1. Pre-reqs command -v protonmail-bridge >/dev/null 2>&1 \ || err "protonmail-bridge not found in PATH — install via archsetup first" bridge_state="$HOME/.config/protonmail/bridge-v3" [ -d "$bridge_state" ] \ || err "Bridge has no state at $bridge_state — run 'protonmail-bridge --cli' and log in first" cmail_action_src="$HOME/projects/claude-templates/.ai/scripts/cmail-action.py" [ -f "$cmail_action_src" ] \ || err "cmail-action.py not found at $cmail_action_src — clone claude-templates first" cmailpass_enc="$HOME/.config/.cmailpass.gpg" [ -f "$cmailpass_enc" ] \ || err "$cmailpass_enc not found — ensure dotfiles are stowed" # 2. Decrypt cmailpass info "decrypting $cmailpass_enc" cmailpass_plain="$HOME/.config/.cmailpass" gpg --quiet --yes --decrypt --output "$cmailpass_plain" "$cmailpass_enc" chmod 600 "$cmailpass_plain" ok "wrote $cmailpass_plain (mode 0600)" # 3. Bridge cert info "exporting Bridge cert" cert_src="$(find "$bridge_state" -name 'cert.pem' -print -quit 2>/dev/null)" [ -n "$cert_src" ] || err "no cert.pem found under $bridge_state — Bridge state is incomplete" cert_dst="$HOME/.config/protonbridge.pem" cp "$cert_src" "$cert_dst" ok "copied $cert_src → $cert_dst" # 4. Symlink cmail-action info "symlinking cmail-action" mkdir -p "$HOME/.local/bin" ln -sf "$cmail_action_src" "$HOME/.local/bin/cmail-action" ok "linked $HOME/.local/bin/cmail-action → $cmail_action_src" # 5. Remove leftover XDG autostart stub # The systemd --user service is the canonical launcher. The autostart .desktop # starts a second Bridge instance that can't get the lock and pops up an # "orphan instance" dialog every login. info "removing orphan autostart launcher (if present)" autostart_stub="$HOME/.config/autostart/Proton Mail Bridge.desktop" if [ -f "$autostart_stub" ]; then rm "$autostart_stub" ok "removed $autostart_stub" else ok "no autostart stub present" fi # 6. Install wait-for-dns drop-in # User-instance systemd doesn't carry network-online.target / nss-lookup.target, # so the packaged unit's After=network.target doesn't imply DNS readiness. # Bridge starts before the resolver is up and its first API calls all fail # until DNS comes online a few seconds later. The drop-in waits (bounded 30s) # for resolution before ExecStart. The leading '-' on ExecStartPre makes it # non-fatal, so an offline boot still starts the unit. info "installing wait-for-dns drop-in" dropin_dir="$HOME/.config/systemd/user/protonmail-bridge.service.d" dropin_file="$dropin_dir/wait-for-dns.conf" mkdir -p "$dropin_dir" cat > "$dropin_file" <<'EOF' [Service] ExecStartPre=-/bin/sh -c 'for i in $(seq 1 30); do getent hosts mail-api.proton.me >/dev/null 2>&1 && exit 0; sleep 1; done' EOF ok "wrote $dropin_file" systemctl --user daemon-reload ok "reloaded systemd user units" # 7. Enable + start systemd user service info "enabling protonmail-bridge user service" was_active=0 systemctl --user is-active --quiet protonmail-bridge.service && was_active=1 systemctl --user enable --now protonmail-bridge if [ "$was_active" = "1" ]; then systemctl --user restart protonmail-bridge ok "service active (restarted to pick up drop-in)" else ok "service active" fi # 8. Verify info "verifying Bridge is listening" if ss -ltn 2>/dev/null | grep -qE '127\.0\.0\.1:(1143|1025)'; then ok "127.0.0.1:1143 + :1025 LISTEN" else err "Bridge isn't listening on the expected ports — check 'systemctl --user status protonmail-bridge'" fi echo echo "cmail setup complete." echo "Next: 'mbsync cmail && mu index' for the first sync."