diff --git a/users/simon/modules/mail/accounts.nix b/users/simon/modules/mail/accounts.nix new file mode 100644 index 0000000..02a25c1 --- /dev/null +++ b/users/simon/modules/mail/accounts.nix @@ -0,0 +1,74 @@ +{ config, ... }: +let + signaturePersonal = '' + -- + Simon Bruder + Wallmersbach 42 + 97215 Uffenheim + + 🔑 (GPG): 47E7 559E 037A 3565 2DBB F8AA 8D3C 82F9 F309 F8EC + 📧 (e-mail): simon@sbruder.de + 📱 (mobile): +49 152 56561414 + ''; +in +{ + accounts.email = { + accounts = { + personal = rec { + primary = true; + + realName = "Simon Bruder"; + address = "simon@sbruder.de"; + aliases = [ ]; # FIXME!? + + userName = address; + passwordCommand = "pass sbruder.de/mail"; + + imap = { + host = "vueko.sbruder.de"; + tls.useStartTls = true; + }; + smtp = { + host = "vueko.sbruder.de"; + tls.useStartTls = true; + }; + + gpg = { + key = config.programs.gpg.settings.default-key; + signByDefault = true; + encryptByDefault = true; + }; + + signature.text = signaturePersonal; + + aerc.enable = true; + }; + riseup = rec { + realName = "Simon Bruder"; + address = "sbruder@riseup.net"; + + userName = address; + passwordCommand = "pass web/riseup.net | head -n 1"; + + imap = { + host = "mail.riseup.net"; + tls.useStartTls = true; + }; + smtp = { + host = "mail.riseup.net"; + tls.useStartTls = true; + }; + + gpg = { + key = config.programs.gpg.settings.default-key; + signByDefault = true; + encryptByDefault = true; + }; + + signature.text = signaturePersonal; + + aerc.enable = true; + }; + }; + }; +} diff --git a/users/simon/modules/mail/aerc/default.nix b/users/simon/modules/mail/aerc/default.nix index d5222ab..529cc1d 100644 --- a/users/simon/modules/mail/aerc/default.nix +++ b/users/simon/modules/mail/aerc/default.nix @@ -1,278 +1,273 @@ -{ lib, pkgs, ... }: +{ config, lib, pkgs, ... }: let package = pkgs.aerc; - - accountDefaults = { - smtp-starttls = "yes"; - copy-to = "Sent"; - signature-file = pkgs.writeText "signature" '' - -- - Simon Bruder - Wallmersbach 42 - 97215 Uffenheim - - 🔑 (GPG): 47E7 559E 037A 3565 2DBB F8AA 8D3C 82F9 F309 F8EC - 📧 (E-Mail): simon@sbruder.de - 📱 (mobile): +49 152 56561414 - ''; - pgp-auto-sign = true; - pgp-key-id = "47E7559E037A35652DBBF8AA8D3C82F9F309F8EC"; - pgp-opportunistic-encrypt = true; - }; in { - home.packages = [ - package - ]; - - xdg.configFile = { - "aerc/accounts.conf".text = lib.generators.toINI { } { - Personal = accountDefaults // { - source = "`imap://simon%40sbruder.de@vueko.sbruder.de`"; - source-cred-cmd = "`pass sbruder.de/mail`"; - outgoing = "`smtp+plain://simon%40sbruder.de@vueko.sbruder.de`"; - outgoing-cred-cmd = "`pass sbruder.de/mail`"; - from = "Simon Bruder "; - }; - - Riseup = accountDefaults // { - source = "`imap://sbruder@mail.riseup.net`"; - source-cred-cmd = "`pass web/riseup.net | head -n 1`"; - outgoing = "`smtp+plain://sbruder@mail.riseup.net`"; - outgoing-cred-cmd = "`pass web/riseup.net | head -n 1`"; - from = "Simon Bruder "; - }; + options = { + accounts.email.accounts = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule { + options.aerc.enable = lib.mkEnableOption "aerc"; + }); }; + }; + config = { + home.packages = [ + package + ]; - "aerc/aerc.conf".text = lib.generators.toINI { } { - general = { - pgp-provider = "gpg"; # internal does not work - - # Allow world-readable accounts.conf (passwords are not stored in it, so it is ok) - unsafe-accounts-conf = true; - }; - - ui = { - index-format = "%-17.17D %-20.20n %Z %s"; - - # See https://godoc.org/time#Time.Format - timestamp-format = "2006-01-02 15:04 MST"; - this-day-time-format = "15:04"; - this-week-time-format = "Monday 15:04"; - this-year-time-format = "02 January"; - - pinned-tab-marker = "車"; - - border-char-vertical = "│"; - border-char-horizontal = "─"; - - fuzzy-complete = true; - - threading-enabled = true; - - new-message-bell = false; - }; - - statusline = { - display-mode = "icon"; - }; - - viewer = { - header-layout = lib.concatStringsSep "," [ - "From|To" - "Cc|Bcc" - "Subject" - "Date" - "Reply-To" - "X-Mailer" - "User-Agent" - ]; - }; - - compose = { - editor = "nvim"; - - header-layout = lib.concatStringsSep "," [ - "To|From" - "Subject" - ]; - - address-book-cmd = "khard email --parsable --remove-first-line %s"; - }; - - filters = { - "subject,~^\\[PATCH" = "awk -f ${package}/share/aerc/filters/hldiff"; - "text/plain" = "${./colorize}"; # taken from upstream and patched - "text/html" = "html"; # internal filter - "text/calendar" = "${pkgs.python3.withPackages (ps: with ps; [ vobject ])}/bin/python ${package}/share/aerc/filters/show-ics-details.py"; # hacky fix for broken nix support - }; - - triggers = { - new-email = "exec notify-send -i mail-unread-symbolic 'New e-mail from %n' '%s'"; - }; - - templates = { }; - }; - - "aerc/binds.conf".text = lib.generators.toINIWithGlobalSection { } { - globalSection = { - # Binds are of the form = - # To use '=' in a key sequence, substitute it with "Eq": "" - # If you wish to bind #, you can wrap the key sequence in quotes: "#" = quit - "" = ":prev-tab"; - "" = ":next-tab"; - "" = ":term"; - }; - - sections = { - messages = { - "q" = ":quit"; - - "j" = ":next"; - "" = ":next"; - "" = ":next 50%"; - "" = ":next 100%"; - "" = ":next 100%"; - - "k" = ":prev"; - "" = ":prev"; - "" = ":prev 50%"; - "" = ":prev 100%"; - "" = ":prev 100%"; - "g" = ":select 0"; - "G" = ":select -1"; - - "J" = ":next-folder"; - "K" = ":prev-folder"; - "H" = ":collapse-folder"; - "L" = ":expand-folder"; - - "v" = ":mark -t"; - "V" = ":mark -v"; - - "T" = ":toggle-threads"; - - "" = ":view"; - "d" = ":prompt 'Really delete this message?' 'delete-message'"; - "D" = ":delete"; - "A" = ":archive flat"; - - "C" = ":compose"; - - "rr" = ":reply -a"; - "rq" = ":reply -aq"; - "Rr" = ":reply"; - "Rq" = ":reply -q"; - - "c" = ":cf"; - "$" = ":term"; - "!" = ":term"; - "|" = ":pipe"; - - "/" = ":search"; - "\\" = ":filter"; - "n" = ":next-result"; - "N" = ":prev-result"; - "" = ":clear"; - }; - - view = { - "/" = ":toggle-key-passthrough/"; - "q" = ":close"; - "O" = ":open"; - "S" = ":save"; - "|" = ":pipe"; - "D" = ":delete"; - "A" = ":archive flat"; - - "f" = ":forward"; - "rr" = ":reply -a"; - "rq" = ":reply -aq"; - "Rr" = ":reply"; - "Rq" = ":reply -q"; - - "H" = ":toggle-headers"; - "" = ":prev-part"; - "" = ":next-part"; - "J" = ":next"; - "K" = ":prev"; - }; - - "view::passthrough" = { - "$noinherit" = "true"; - "$ex" = ""; - "" = ":toggle-key-passthrough"; - }; - - # Keybindings used when the embedded terminal is not selected in the compose view" - compose = { - "$ex" = ""; - "" = ":prev-field"; - "" = ":next-field"; - "" = ":next-field"; - "" = ":prev-field"; - }; - - # Keybindings used when the embedded terminal is selected in the compose view - "compose::editor" = { - "$noinherit" = "true"; - "$ex" = ""; - "" = ":prev-field"; - "" = ":next-field"; - "" = ":prev-tab"; - "" = ":next-tab"; - }; - - # Keybindings used when reviewing a message to be sent - "compose::review" = { - "y" = ":send"; - "n" = ":abort"; - "p" = ":postpone"; - "q" = ":choose -o d discard abort -o p postpone postpone"; - "e" = ":edit"; - "a" = ":attach"; - "d" = ":detach"; - }; - - terminal = { - "$noinherit" = "true"; - "$ex" = ""; - - "" = ":prev-tab"; - "" = ":next-tab"; - }; - }; - }; - - "aerc/stylesets/default".text = lib.concatStrings - (lib.mapAttrsToList - (k: v: "${k} = ${if lib.isBool v then (if v then "true" else "false") else toString v}\n") + xdg.configFile = { + "aerc/accounts.conf".text = lib.generators.toINI { } (lib.mapAttrs + # incomplete support for all configuration options! + (name: config: with config; let + quoteMailAddress = lib.replaceChars [ "@" ] [ "%40" ]; + in { - "*.selected.reverse" = true; + source = "`imap://${quoteMailAddress address}@${imap.host}`"; + source-cred-cmd = "`${lib.concatStringsSep " " passwordCommand}`"; + outgoing = "`smtp+plain://${quoteMailAddress address}@${smtp.host}`"; + outgoing-cred-cmd = "`${lib.concatStringsSep " " passwordCommand}`"; + from = "${realName} <${address}>"; + smtp-starttls = if smtp.tls.useStartTls then "yes" else "no"; + copy-to = "Sent"; + signature-file = pkgs.writeText "signature-${name}" signature.text; + pgp-key-id = gpg.key; + pgp-auto-sign = gpg.signByDefault; + pgp-opportunistic-encrypt = gpg.encryptByDefault; + }) + (lib.filterAttrs + (_: config: config.aerc.enable) + config.accounts.email.accounts)); - "title.reverse" = true; - "header.bold" = true; + "aerc/aerc.conf".text = lib.generators.toINI { } { + general = { + pgp-provider = "gpg"; # internal does not work - "*error.bold" = true; - "error.fg" = 1; - "warning.fg" = 3; - "success.fg" = 2; + # Allow world-readable accounts.conf (passwords are not stored in it, so it is ok) + unsafe-accounts-conf = true; + }; - "statusline_default.bg" = 0; - "statusline_error.fg" = 1; - "statusline_error.reverse" = true; - "statusline_success.fg" = 2; - "statusline_success.reverse" = true; + ui = { + index-format = "%-17.17D %-20.20n %Z %s"; - "msglist_unread.bold" = true; - "msglist_deleted.fg" = 10; + # See https://godoc.org/time#Time.Format + timestamp-format = "2006-01-02 15:04 MST"; + this-day-time-format = "15:04"; + this-week-time-format = "Monday 15:04"; + this-year-time-format = "02 January"; - "tab.bg" = 11; - "tab.selected.reverse" = false; - "tab.selected.bg" = 12; - "tab.fg" = 0; + pinned-tab-marker = "車"; - "completion_default.bg" = 0; - }); + border-char-vertical = "│"; + border-char-horizontal = "─"; + + fuzzy-complete = true; + + threading-enabled = true; + + new-message-bell = false; + }; + + statusline = { + display-mode = "icon"; + }; + + viewer = { + header-layout = lib.concatStringsSep "," [ + "From|To" + "Cc|Bcc" + "Subject" + "Date" + "Reply-To" + "X-Mailer" + "User-Agent" + ]; + }; + + compose = { + editor = "nvim"; + + header-layout = lib.concatStringsSep "," [ + "To|From" + "Subject" + ]; + + address-book-cmd = "khard email --parsable --remove-first-line %s"; + }; + + filters = { + "subject,~^\\[PATCH" = "awk -f ${package}/share/aerc/filters/hldiff"; + "text/plain" = "${./colorize}"; # taken from upstream and patched + "text/html" = "html"; # internal filter + "text/calendar" = "${pkgs.python3.withPackages (ps: with ps; [ vobject ])}/bin/python ${package}/share/aerc/filters/show-ics-details.py"; # hacky fix for broken nix support + }; + + triggers = { + new-email = "exec notify-send -i mail-unread-symbolic 'New e-mail from %n' '%s'"; + }; + + templates = { }; + }; + + "aerc/binds.conf".text = lib.generators.toINIWithGlobalSection { } { + globalSection = { + # Binds are of the form = + # To use '=' in a key sequence, substitute it with "Eq": "" + # If you wish to bind #, you can wrap the key sequence in quotes: "#" = quit + "" = ":prev-tab"; + "" = ":next-tab"; + "" = ":term"; + }; + + sections = { + messages = { + "q" = ":quit"; + + "j" = ":next"; + "" = ":next"; + "" = ":next 50%"; + "" = ":next 100%"; + "" = ":next 100%"; + + "k" = ":prev"; + "" = ":prev"; + "" = ":prev 50%"; + "" = ":prev 100%"; + "" = ":prev 100%"; + "g" = ":select 0"; + "G" = ":select -1"; + + "J" = ":next-folder"; + "K" = ":prev-folder"; + "H" = ":collapse-folder"; + "L" = ":expand-folder"; + + "v" = ":mark -t"; + "V" = ":mark -v"; + + "T" = ":toggle-threads"; + + "" = ":view"; + "d" = ":prompt 'Really delete this message?' 'delete-message'"; + "D" = ":delete"; + "A" = ":archive flat"; + + "C" = ":compose"; + + "rr" = ":reply -a"; + "rq" = ":reply -aq"; + "Rr" = ":reply"; + "Rq" = ":reply -q"; + + "c" = ":cf"; + "$" = ":term"; + "!" = ":term"; + "|" = ":pipe"; + + "/" = ":search"; + "\\" = ":filter"; + "n" = ":next-result"; + "N" = ":prev-result"; + "" = ":clear"; + }; + + view = { + "/" = ":toggle-key-passthrough/"; + "q" = ":close"; + "O" = ":open"; + "S" = ":save"; + "|" = ":pipe"; + "D" = ":delete"; + "A" = ":archive flat"; + + "f" = ":forward"; + "rr" = ":reply -a"; + "rq" = ":reply -aq"; + "Rr" = ":reply"; + "Rq" = ":reply -q"; + + "H" = ":toggle-headers"; + "" = ":prev-part"; + "" = ":next-part"; + "J" = ":next"; + "K" = ":prev"; + }; + + "view::passthrough" = { + "$noinherit" = "true"; + "$ex" = ""; + "" = ":toggle-key-passthrough"; + }; + + # Keybindings used when the embedded terminal is not selected in the compose view" + compose = { + "$ex" = ""; + "" = ":prev-field"; + "" = ":next-field"; + "" = ":next-field"; + "" = ":prev-field"; + }; + + # Keybindings used when the embedded terminal is selected in the compose view + "compose::editor" = { + "$noinherit" = "true"; + "$ex" = ""; + "" = ":prev-field"; + "" = ":next-field"; + "" = ":prev-tab"; + "" = ":next-tab"; + }; + + # Keybindings used when reviewing a message to be sent + "compose::review" = { + "y" = ":send"; + "n" = ":abort"; + "p" = ":postpone"; + "q" = ":choose -o d discard abort -o p postpone postpone"; + "e" = ":edit"; + "a" = ":attach"; + "d" = ":detach"; + }; + + terminal = { + "$noinherit" = "true"; + "$ex" = ""; + + "" = ":prev-tab"; + "" = ":next-tab"; + }; + }; + }; + + "aerc/stylesets/default".text = lib.concatStrings + (lib.mapAttrsToList + (k: v: "${k} = ${if lib.isBool v then (if v then "true" else "false") else toString v}\n") + { + "*.selected.reverse" = true; + + "title.reverse" = true; + "header.bold" = true; + + "*error.bold" = true; + "error.fg" = 1; + "warning.fg" = 3; + "success.fg" = 2; + + "statusline_default.bg" = 0; + "statusline_error.fg" = 1; + "statusline_error.reverse" = true; + "statusline_success.fg" = 2; + "statusline_success.reverse" = true; + + "msglist_unread.bold" = true; + "msglist_deleted.fg" = 10; + + "tab.bg" = 11; + "tab.selected.reverse" = false; + "tab.selected.bg" = 12; + "tab.fg" = 0; + + "completion_default.bg" = 0; + }); + }; }; } diff --git a/users/simon/modules/mail/default.nix b/users/simon/modules/mail/default.nix index 6a61e69..f5ca1ee 100644 --- a/users/simon/modules/mail/default.nix +++ b/users/simon/modules/mail/default.nix @@ -1,5 +1,6 @@ { imports = [ + ./accounts.nix ./aerc ]; }