aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/email/.gitignore1
-rw-r--r--modules/email/aerc-binds.conf140
-rw-r--r--modules/email/aerc.conf23
-rw-r--r--modules/email/aerc.home.nix61
-rw-r--r--modules/email/aerc.theme.nix51
-rw-r--r--modules/email/mailbox-sync.module.nix70
-rw-r--r--modules/email/query-map.conf9
7 files changed, 355 insertions, 0 deletions
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 @@
+<C-p> = :prev-tab<Enter>
+<C-n> = :next-tab<Enter>
+<C-t> = :term<Enter>
+? = :help keys<Enter>
+<C-c> = :prompt 'Quit?' quit<Enter>
+<C-q> = :prompt 'Quit?' quit<Enter>
+<C-z> = :suspend<Enter>
+
+
+
+
+[messages]
+q = :prompt 'Quit?' quit<Enter>
+
+a = :read<Enter>
+A = :unread<Enter>
+i = :tag +important<Enter>
+I = :tag -important<Enter>
+
+<Enter> = :view<Enter>
+
+j = :next<Enter>
+k = :prev<Enter>
+<C-d> = :next 50%<Enter>
+<C-f> = :next 100%<Enter>
+<C-u> = :prev 50%<Enter>
+<C-b> = :prev 100%<Enter>
+g = :select 0<Enter>
+G = :select -1<Enter>
+
+J = :next-folder<Enter>
+K = :prev-folder<Enter>
+
+v = :mark -t<Enter>
+<Space> = :mark -t<Enter>:next<Enter>
+V = :mark -v<Enter>
+
+T = :toggle-threads<Enter>
+za = :fold -t<Enter>
+
+C = :compose<Enter>
+
+rr = :reply -a<Enter>
+Rr = :reply<Enter>
+
+! = :term<space>
+| = :pipe<space>
+
+/ = :search<space>
+\ = :filter<space>
+n = :next-result<Enter>
+N = :prev-result<Enter>
+<Esc> = :clear<Enter>
+
+s = :split<Enter>
+S = :vsplit<Enter>
+
+[messages:folder=Drafts]
+<Enter> = :recall<Enter>
+
+
+
+
+[view]
+/ = :toggle-key-passthrough<Enter>/
+q = :close<Enter>
+o = :open<Enter>
+S = :save<space>
+| = :pipe<space>
+D = :delete<Enter>
+
+<C-l> = :open-link <space>
+
+f = :forward<Enter>
+rr = :reply -a<Enter>
+Rr = :reply<Enter>
+
+H = :toggle-headers<Enter>
+<C-k> = :prev-part<Enter>
+<C-j> = :next-part<Enter>
+J = :next<Enter>
+K = :prev<Enter>
+
+
+
+
+[view::passthrough]
+$noinherit = true
+$ex = <C-x>
+<Esc> = :toggle-key-passthrough<Enter>
+
+
+
+
+[compose]
+$noinherit = true
+$ex = <C-x>
+$complete = <C-o>
+<C-k> = :prev-field<Enter>
+<C-j> = :next-field<Enter>
+<tab> = :next-field<Enter>
+<backtab> = :prev-field<Enter>
+<C-p> = :prev-tab<Enter>
+<C-n> = :next-tab<Enter>
+
+
+
+
+[compose::editor]
+$noinherit = true
+$ex = <C-x>
+<C-k> = :prev-field<Enter>
+<C-j> = :next-field<Enter>
+<C-p> = :prev-tab<Enter>
+<C-n> = :next-tab<Enter>
+
+
+
+
+[compose::review]
+# Inline comments are used as descriptions on the review screen
+y = :send<Enter> # Send
+n = :abort<Enter> # Abort (discard message, no confirmation)
+p = :preview<Enter> # Preview message
+e = :edit<Enter> # Edit (body and headers)
+a = :attach<space> # Add attachment
+d = :detach<space> # Remove attachment
+P = :postpone<Enter> # Postpone
+
+
+
+
+
+[terminal]
+$noinherit = true
+$ex = <C-x>
+
+<C-p> = :prev-tab<Enter>
+<C-n> = :next-tab<Enter>
+
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 <email>`
+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