From ce0a366e8ba58fb967d4270e9c0e7d3ba759c759 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Sat, 24 May 2025 17:40:28 +0530 Subject: Add setup for notmuch+lieer+aerc for email --- modules/email/.gitignore | 1 + modules/email/aerc-binds.conf | 140 ++++++++++++++++++++++++++++++++++ modules/email/aerc.conf | 23 ++++++ modules/email/aerc.home.nix | 61 +++++++++++++++ modules/email/aerc.theme.nix | 51 +++++++++++++ modules/email/mailbox-sync.module.nix | 70 +++++++++++++++++ modules/email/query-map.conf | 9 +++ 7 files changed, 355 insertions(+) create mode 100644 modules/email/.gitignore create mode 100644 modules/email/aerc-binds.conf create mode 100644 modules/email/aerc.conf create mode 100644 modules/email/aerc.home.nix create mode 100644 modules/email/aerc.theme.nix create mode 100644 modules/email/mailbox-sync.module.nix create mode 100644 modules/email/query-map.conf (limited to 'modules') diff --git a/modules/email/.gitignore b/modules/email/.gitignore new file mode 100644 index 0000000..a211cae --- /dev/null +++ b/modules/email/.gitignore @@ -0,0 +1 @@ +private.nix diff --git a/modules/email/aerc-binds.conf b/modules/email/aerc-binds.conf new file mode 100644 index 0000000..15d3a49 --- /dev/null +++ b/modules/email/aerc-binds.conf @@ -0,0 +1,140 @@ + = :prev-tab + = :next-tab + = :term +? = :help keys + = :prompt 'Quit?' quit + = :prompt 'Quit?' quit + = :suspend + + + + +[messages] +q = :prompt 'Quit?' quit + +a = :read +A = :unread +i = :tag +important +I = :tag -important + + = :view + +j = :next +k = :prev + = :next 50% + = :next 100% + = :prev 50% + = :prev 100% +g = :select 0 +G = :select -1 + +J = :next-folder +K = :prev-folder + +v = :mark -t + = :mark -t:next +V = :mark -v + +T = :toggle-threads +za = :fold -t + +C = :compose + +rr = :reply -a +Rr = :reply + +! = :term +| = :pipe + +/ = :search +\ = :filter +n = :next-result +N = :prev-result + = :clear + +s = :split +S = :vsplit + +[messages:folder=Drafts] + = :recall + + + + +[view] +/ = :toggle-key-passthrough/ +q = :close +o = :open +S = :save +| = :pipe +D = :delete + + = :open-link + +f = :forward +rr = :reply -a +Rr = :reply + +H = :toggle-headers + = :prev-part + = :next-part +J = :next +K = :prev + + + + +[view::passthrough] +$noinherit = true +$ex = + = :toggle-key-passthrough + + + + +[compose] +$noinherit = true +$ex = +$complete = + = :prev-field + = :next-field + = :next-field + = :prev-field + = :prev-tab + = :next-tab + + + + +[compose::editor] +$noinherit = true +$ex = + = :prev-field + = :next-field + = :prev-tab + = :next-tab + + + + +[compose::review] +# Inline comments are used as descriptions on the review screen +y = :send # Send +n = :abort # Abort (discard message, no confirmation) +p = :preview # Preview message +e = :edit # Edit (body and headers) +a = :attach # Add attachment +d = :detach # Remove attachment +P = :postpone # Postpone + + + + + +[terminal] +$noinherit = true +$ex = + + = :prev-tab + = :next-tab + diff --git a/modules/email/aerc.conf b/modules/email/aerc.conf new file mode 100644 index 0000000..86982ae --- /dev/null +++ b/modules/email/aerc.conf @@ -0,0 +1,23 @@ +[general] +enable-osc8 = true +unsafe-accounts-conf = true + +[ui] +auto-mark-read = true + +[viewer] +parse-http-links = true + +[compose] +editor = nvim +file-picker-cmd = lf -selection-path=%f + +[filters] +text/plain=bat -f --paging=never --file-name="$AERC_SUBJECT ($AERC_FROM)" --style=header,grid +text/html=! w3m -I UTF-8 -T text/html +text/*=bat -fP --file-name="$AERC_FILENAME" --style=plain + +[openers] +image/*=sxiv {} +application/pdf=zathura {} + diff --git a/modules/email/aerc.home.nix b/modules/email/aerc.home.nix new file mode 100644 index 0000000..7dcd99e --- /dev/null +++ b/modules/email/aerc.home.nix @@ -0,0 +1,61 @@ +{ config, ... }: +# Create private.nix with work.email, work.name +# Setup with `notmuch setup` +# Authenticate with `take ~/mail/account.gmail/ && gmi init ` +let + private = import ./private.nix; + theme = import ./aerc.theme.nix; + maildir = "${config.home.homeDirectory}/mail"; + work-maildir = "${maildir}/account.gmail"; +in { + imports = [ ./mailbox-sync.module.nix ]; + + services.mailbox-sync = { + enable = true; + name = "work"; + maildir = work-maildir; + sync.frequency = "*:0/5"; + notify.enable = true; + }; + + programs.notmuch = { + enable = true; + new = { + tags = ["new"]; + ignore = ["/.*[.](json|lock|bak)$/"]; + }; + extraConfig = { + database = { + path = maildir; + }; + user = { + name = private.work.name; + primary_email = private.work.email; + }; + search = { + exclude_tags = "ignored"; + }; + }; + }; + + programs.aerc = { + enable = true; + + extraAccounts.Work = { + from = "${private.work.name} <${private.work.email}>"; + source = "notmuch://${maildir}"; + outgoing = "gmi send -t -C ${work-maildir}"; + query-map = "${./query-map.conf}"; + folders-sort = "Inbox,Unread,Important,_sent,_spam"; + default = "INBOX"; + copy-to = "Sent"; + postpone = "[Gmail]/Drafts"; + cache-headers = true; + }; + + extraConfig = builtins.readFile ./aerc.conf; + extraBinds = builtins.readFile ./aerc-binds.conf; + + stylesets.default = theme; + }; +} diff --git a/modules/email/aerc.theme.nix b/modules/email/aerc.theme.nix new file mode 100644 index 0000000..f2f525d --- /dev/null +++ b/modules/email/aerc.theme.nix @@ -0,0 +1,51 @@ +let + accent = "#4f3aA3"; +in { + "title.bg" = accent; + "title.fg" = "black"; + "title.bold" = true; + "header.bold" = true; + "header.fg" = accent; + "tab.bold" = true; + "tab.selected.fg" = "white"; + "tab.selected.bg" = accent; + "tab.selected.bold" = true; + "dirlist*.selected.bg" = accent; + "dirlist*.selected.fg" = "white"; + "dirlist*.selected.bold" = false; + "*error.bold" = true; + "*error.fg" = "red"; + "*warning.fg" = "yellow"; + "*success.fg" = "green"; + "statusline_default.bg" = "#303030"; + "statusline_error.fg" = "red"; + "msglist_unread.fg" = "#ffffff"; + "msglist_unread.bold" = true; + "msglist_deleted.fg" = "#666666"; + "msglist_*.selected.bg" = accent; + "msglist_marked.fg" = "black"; + "msglist_marked.selected.fg" = "black"; + "msglist_marked.bg" = "#BD93F9"; + "msglist_marked.selected.bg" = "#9956f5"; + "completion_pill.reverse" = false; + "selector_focused.bold" = false; + "selector_focused.bg" = accent; + "selector_focused.fg" = "white"; + "selector_chooser.bold" = false; + "selector_chooser.bg" = accent; + "selector_chooser.fg" = "white"; + "default.selected.bold" = false; + "default.selected.fg" = "white"; + "default.selected.bg" = accent; + "completion_default.selected.bg" = accent; + "completion_default.selected.fg" = "white"; + "part_filename.bold" = true; + "part_mimetype.fg" = accent; + "part_filename.selected.bg" = accent; + "part_filename.selected.fg" = "white"; + "part_mimetype.selected.bg" = accent; + "part_mimetype.selected.fg" = "white"; + "part_mimetype.selected.bold" = true; + "part_switcher.selected.bg" = accent; + "part_switcher.selected.fg" = "white"; +} diff --git a/modules/email/mailbox-sync.module.nix b/modules/email/mailbox-sync.module.nix new file mode 100644 index 0000000..ad5f94e --- /dev/null +++ b/modules/email/mailbox-sync.module.nix @@ -0,0 +1,70 @@ +{ config, pkgs, lib, ... }: +with lib; +let + cfg = config.services.mailbox-sync; + + notmuch = "${pkgs.notmuch}/bin/notmuch"; + gmi = "${pkgs.lieer}/bin/gmi"; + notify-send = "${pkgs.libnotify}/bin/notify-send"; + jq = "${pkgs.jq}/bin/jq"; + + notify-script = '' + emails=$(${notmuch} search --format=json '${cfg.notify.filter}' \ + | ${jq} -r '.[0:5] | map("* " + .subject + " (tag: " + (.tags | join(" ")) + ")") | join("\n\n")'); + + # Notify + ${notify-send} --app-name=notmuch "New mail baybey ($new_mail_count)" "$emails"; + ''; + + sync-script = '' + #!${pkgs.bash}/bin/bash + set -eu -o pipefail; + + ${gmi} sync; + + new_mail_count=$(${notmuch} count '${cfg.notify.filter}'); + if [ $new_mail_count = 0 ]; then + echo "No new mail"; + else + ${if cfg.notify.enable then notify-script else ""} + fi + + ${notmuch} tag -new -- tag:new; + ''; + + service-unit = { + Unit.ConditionPathExists = "${cfg.maildir}/.gmailieer.json"; + Service = { + Type = "oneshot"; + ExecStart = "${pkgs.writeScript "mailbox-sync-script" sync-script}"; + WorkingDirectory = cfg.maildir; + Environment = "NOTMUCH_CONFIG=${config.xdg.configHome}/notmuch/default/config"; + }; + }; + + timer-unit = { + Timer = { + OnCalendar = cfg.sync.frequency; + RandomizedDelaySec = 30; + }; + Install.WantedBy = [ "timers.target" ]; + }; +in { + options.services.mailbox-sync = { + enable = mkEnableOption "mailbox sync"; + name = mkOption { type = types.str; default = "default"; }; + maildir = mkOption { type = types.str; }; + sync.frequency = mkOption { type = types.str; default = "*:0/5"; }; + notify.enable = mkEnableOption "notify on new mail"; + notify.filter = mkOption { + type = types.str; + default = "tag:inbox and tag:unread and tag:new"; + }; + }; + + config = mkIf cfg.enable { + programs.lieer.enable = true; + systemd.user.services."mailbox-sync-${cfg.name}" = service-unit; + systemd.user.timers."mailbox-sync-${cfg.name}" = timer-unit; + }; +} diff --git a/modules/email/query-map.conf b/modules/email/query-map.conf new file mode 100644 index 0000000..fe14b08 --- /dev/null +++ b/modules/email/query-map.conf @@ -0,0 +1,9 @@ +Inbox=tag:inbox and not tag:archived and not tag:sent and not tag:deleted and not tag:spam + +Unread=tag:inbox and tag:unread and not tag:spam + +Important=tag:important and not tag:archived and not tag:deleted and not tag:spam + +_sent=tag:sent and not tag:archived not tag:deleted + +_spam=tag:spam -- cgit v1.3.1