From ee32d0d0813f9870d89fb7d821633fd8b4a9987a Mon Sep 17 00:00:00 2001 From: Arpit Chakladar Date: Thu, 9 Jul 2026 20:34:00 +0530 Subject: feat: added email configuration with mbsync + notmuch added a private module which will be gitignored and serves to include options that are not meant to be shared --- modules/scripts/aerc-mail-setup.sh | 332 ------------------------------------- modules/scripts/aerc-sync-mail.sh | 14 -- modules/scripts/default.nix | 41 ++--- modules/scripts/meli-sync.sh | 5 + 4 files changed, 18 insertions(+), 374 deletions(-) delete mode 100644 modules/scripts/aerc-mail-setup.sh delete mode 100644 modules/scripts/aerc-sync-mail.sh create mode 100644 modules/scripts/meli-sync.sh (limited to 'modules/scripts') diff --git a/modules/scripts/aerc-mail-setup.sh b/modules/scripts/aerc-mail-setup.sh deleted file mode 100644 index cca982e..0000000 --- a/modules/scripts/aerc-mail-setup.sh +++ /dev/null @@ -1,332 +0,0 @@ -set -euo pipefail - -config_home="${XDG_CONFIG_HOME:-$HOME/.config}" -data_home="${XDG_DATA_HOME:-$HOME/.local/share}" -state_home="${XDG_STATE_HOME:-$HOME/.local/state}" -password_store_dir="${PASSWORD_STORE_DIR:-$HOME/.password-store}" - -mail_root="${data_home}/mail" -isync_config="${config_home}/isyncrc" -aerc_accounts="${config_home}/aerc/accounts.conf" -notmuch_config="${config_home}/notmuch/default/config" -query_map="${config_home}/aerc/notmuch-query-map" - -usage() { - cat <<'USAGE' -Usage: - aerc-mail-setup add Add or update a Gmail, Yahoo, or Outlook account - aerc-mail-setup remove Remove generated aerc/isync blocks for an account - aerc-mail-setup list List generated accounts - aerc-mail-setup sync Run mbsync and notmuch indexing - -Secrets are stored through pass(1). Generated private config is written under -~/.config/isyncrc, ~/.config/aerc/accounts.conf, and ~/.config/notmuch/default/config. -Removing an account only removes generated config blocks; it does not delete mail or passwords. -USAGE -} - -prompt() { - local label="$1" - local default="${2:-}" - local value - - if [[ -n "$default" ]]; then - printf '%s [%s]: ' "$label" "$default" >&2 - read -r value - printf '%s\n' "${value:-$default}" - else - printf '%s: ' "$label" >&2 - read -r value - printf '%s\n' "$value" - fi -} - -sanitize_account() { - printf '%s' "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9_.-]/-/g' -} - -url_encode_user() { - printf '%s' "$1" | sed 's/%/%25/g; s/@/%40/g; s/+/%2B/g' -} - -ensure_query_map() { - mkdir -p "$(dirname "$query_map")" - if [[ ! -e "$query_map" ]]; then - cat >"$query_map" <<'EOF' -Inbox=tag:inbox and not tag:deleted -Unread=tag:unread and not tag:deleted -Flagged=tag:flagged and not tag:deleted -Sent=folder:sent or folder:Sent or folder:"[Gmail]/Sent Mail" -Archive=not tag:inbox and not tag:deleted -All=* -EOF - fi -} - -write_notmuch_config() { - local name="$1" - local email="$2" - - mkdir -p "$(dirname "$notmuch_config")" "$mail_root" "$state_home/isync" - if [[ ! -e "$notmuch_config" ]]; then - cat >"$notmuch_config" <"$tmp" - fi - - { - sed '/^[[:space:]]*$/N;/^\n$/D' "$tmp" 2>/dev/null || true - printf '\n# BEGIN %s\n' "$block_name" - cat - printf '# END %s\n' "$block_name" - } >"$file" - rm -f "$tmp" - chmod 600 "$file" -} - -remove_block() { - local file="$1" - local block_name="$2" - local tmp - - [[ -e "$file" ]] || return - tmp="$(mktemp)" - awk -v start="# BEGIN ${block_name}" -v end="# END ${block_name}" ' - $0 == start { skip = 1; next } - $0 == end { skip = 0; next } - !skip { print } - ' "$file" >"$tmp" - cat "$tmp" >"$file" - rm -f "$tmp" - chmod 600 "$file" -} - -pass_insert_if_requested() { - local pass_entry="$1" - - if pass show "$pass_entry" >/dev/null 2>&1; then - return - fi - - printf 'No pass entry found at %s.\n' "$pass_entry" - if [[ ! -f "${password_store_dir}/.gpg-id" ]]; then - cat >&2 < - -After that, rerun: - aerc-mail-setup add -EOF - exit 1 - fi - - printf 'Store the password there now? [y/N]: ' - read -r answer - case "$answer" in - y|Y|yes|YES) - pass insert "$pass_entry" - ;; - *) - printf 'Create it later with: pass insert %s\n' "$pass_entry" - ;; - esac -} - -provider_defaults() { - local provider="$1" - case "$provider" in - gmail) - imap_host="imap.gmail.com" - imap_port="993" - imap_tls="IMAPS" - imap_auth="LOGIN" - smtp_host="smtp.gmail.com" - smtp_port="587" - smtp_scheme="smtp+login" - ;; - yahoo) - imap_host="imap.mail.yahoo.com" - imap_port="993" - imap_tls="IMAPS" - imap_auth="LOGIN" - smtp_host="smtp.mail.yahoo.com" - smtp_port="587" - smtp_scheme="smtp+login" - ;; - outlook) - imap_host="outlook.office365.com" - imap_port="993" - imap_tls="IMAPS" - imap_auth="LOGIN" - smtp_host="smtp.office365.com" - smtp_port="587" - smtp_scheme="smtp+login" - ;; - *) - printf 'Unsupported provider: %s\n' "$provider" >&2 - exit 1 - ;; - esac -} - -add_account() { - local provider account email name user pass_entry sync_patterns - local imap_host imap_port imap_tls imap_auth smtp_host smtp_port smtp_scheme - local encoded_user - - provider="$(prompt "Provider (gmail/yahoo/outlook)")" - provider="$(printf '%s' "$provider" | tr '[:upper:]' '[:lower:]')" - provider_defaults "$provider" - sync_patterns="*" - - email="$(prompt "Email address")" - account="$(prompt "Account id" "$(sanitize_account "$email")")" - account="$(sanitize_account "$account")" - name="$(prompt "Display name")" - - printf 'Use an app password stored in pass; OAuth is not configured here.\n' - user="$(prompt "IMAP/SMTP username" "$email")" - - imap_host="$(prompt "IMAP host" "$imap_host")" - imap_port="$(prompt "IMAP port" "$imap_port")" - imap_tls="$(prompt "mbsync IMAP TLS mode (IMAPS/STARTTLS/None)" "$imap_tls")" - imap_auth="$(prompt "mbsync IMAP auth mechanism" "$imap_auth")" - smtp_host="$(prompt "SMTP host" "$smtp_host")" - smtp_port="$(prompt "SMTP port" "$smtp_port")" - smtp_scheme="$(prompt "aerc SMTP scheme" "$smtp_scheme")" - - pass_entry="$(prompt "pass entry for this account password" "mail/${account}")" - pass_insert_if_requested "$pass_entry" - - mkdir -p "${mail_root}/${account}/INBOX/cur" "${mail_root}/${account}/INBOX/new" "${mail_root}/${account}/INBOX/tmp" - ensure_query_map - write_notmuch_config "$name" "$email" - - replace_block "$isync_config" "aerc-mail:${account}" < -outgoing = ${smtp_scheme}://${encoded_user}@${smtp_host}:${smtp_port} -outgoing-cred-cmd = pass show ${pass_entry} -check-mail = 5m -check-mail-cmd = aerc-sync-mail ${account} -check-mail-timeout = 5m -default = Inbox -copy-to = Sent -archive = Archive -postpone = Drafts -EOF - - printf 'Configured %s. Run this once for the initial download:\n' "$account" - printf ' aerc-sync-mail %s\n' "$account" -} - -list_accounts() { - if [[ ! -e "$aerc_accounts" ]]; then - printf 'No generated accounts found.\n' - return - fi - sed -n 's/^# BEGIN aerc-mail:\(.*\)$/\1/p' "$aerc_accounts" -} - -remove_account() { - local account - - account="$(prompt "Account id to remove")" - account="$(sanitize_account "$account")" - - remove_block "$isync_config" "aerc-mail:${account}" - remove_block "$aerc_accounts" "aerc-mail:${account}" - printf 'Removed generated config blocks for %s.\n' "$account" -} - -case "${1:-}" in - add) - add_account - ;; - remove) - remove_account - ;; - list) - list_accounts - ;; - sync) - shift - aerc-sync-mail "$@" - ;; - -h|--help|help|"") - usage - ;; - *) - usage >&2 - exit 1 - ;; -esac diff --git a/modules/scripts/aerc-sync-mail.sh b/modules/scripts/aerc-sync-mail.sh deleted file mode 100644 index 7e45cdf..0000000 --- a/modules/scripts/aerc-sync-mail.sh +++ /dev/null @@ -1,14 +0,0 @@ -set -euo pipefail - -target="${1:--a}" -mail_root="${XDG_DATA_HOME:-$HOME/.local/share}/mail" -mkdir -p "$mail_root" - -if [[ "$target" == "all" ]]; then - target="-a" -else - mkdir -p "${mail_root}/${target}/INBOX/cur" "${mail_root}/${target}/INBOX/new" "${mail_root}/${target}/INBOX/tmp" -fi - -mbsync "$target" -notmuch new diff --git a/modules/scripts/default.nix b/modules/scripts/default.nix index 8ee8f11..5e6b88b 100644 --- a/modules/scripts/default.nix +++ b/modules/scripts/default.nix @@ -37,34 +37,6 @@ let # Script definitions: { path, env?, deps?, conditions? } # condition: attrset of { option (string path), value (expected value) } scriptDefs = { - aerc-mail-setup = { - path = ./aerc-mail-setup.sh; - deps = [ - pkgs.gnupg - pkgs.isync - pkgs.notmuch - config.programs.gopass.package - ]; - conditions = [ - { - option = "programs.aerc.enable"; - value = true; - } - ]; - }; - aerc-sync-mail = { - path = ./aerc-sync-mail.sh; - deps = [ - pkgs.isync - pkgs.notmuch - ]; - conditions = [ - { - option = "programs.aerc.enable"; - value = true; - } - ]; - }; aria2-run = { path = ./aria2-run.sh; deps = [ @@ -218,6 +190,19 @@ let } ]; }; + meli-sync = { + path = ./meli-sync.sh; + deps = [ + pkgs.mbsync + pkgs.notmuch + ]; + conditions = [ + { + option = "programs.meli.enable"; + value = true; + } + ]; + }; }; # Check whether all conditions for a script are satisfied diff --git a/modules/scripts/meli-sync.sh b/modules/scripts/meli-sync.sh new file mode 100644 index 0000000..2024562 --- /dev/null +++ b/modules/scripts/meli-sync.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env sh + +# Sync all accounts and immediately tag with notmuch +mbsync -a +notmuch new 2>/dev/null \ No newline at end of file -- cgit v1.2.3