mail/aerc: Use home-manager module (mostly)

This does not use the home-manager provided account module, because it
does not support notmuch, LOGIN authentication and special characters in
user names.
nazuna
Simon Bruder 2022-12-10 16:03:16 +01:00
parent 71308a9284
commit 47c5bd5338
Signed by: simon
GPG Key ID: 8D3C82F9F309F8EC
2 changed files with 194 additions and 193 deletions

View File

@ -44,7 +44,7 @@ in
signature.text = signaturePersonal; signature.text = signaturePersonal;
aerc.enable = true; aerc-sbruder.enable = true;
mbsync = { mbsync = {
enable = true; enable = true;
#flatten = "."; #flatten = ".";
@ -79,7 +79,7 @@ in
signature.text = signaturePersonal; signature.text = signaturePersonal;
aerc.enable = true; aerc-sbruder.enable = true;
}; };
tu-dresden = rec { tu-dresden = rec {
realName = "Simon Bruder"; realName = "Simon Bruder";
@ -106,7 +106,7 @@ in
signature.text = signaturePersonal; signature.text = signaturePersonal;
aerc.enable = true; aerc-sbruder.enable = true;
}; };
}; };
}; };

View File

@ -1,73 +1,70 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
let
package = pkgs.aerc;
in
{ {
options = { options = {
accounts.email.accounts = lib.mkOption { accounts.email.accounts = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule { type = lib.types.attrsOf (lib.types.submodule {
options.aerc.enable = lib.mkEnableOption "aerc"; options.aerc-sbruder.enable = lib.mkEnableOption "aerc (custom implementation)";
}); });
}; };
}; };
config = { config = {
home.packages = [ programs.aerc = {
package enable = true;
];
xdg.configFile = { # incomplete support for all configuration options!
"aerc/accounts.conf".text = lib.generators.toINI { } (lib.mapAttrs extraAccounts =
# incomplete support for all configuration options! (lib.mapAttrs
(name: accountConfig: with accountConfig; let (name: accountConfig: with accountConfig; let
quoteMailAddress = lib.replaceChars [ "@" "\\" ] [ "%40" "%5C" ]; quoteMailAddress = lib.replaceChars [ "@" "\\" ] [ "%40" "%5C" ];
# home-manager has no way to set if an account requires AUTH LOGIN # home-manager has no way to set if an account requires AUTH LOGIN
# this emulats this by setting a list of known providers that do require it # this emulats this by setting a list of known providers that do require it
requiresLogin = lib.elem requiresLogin = lib.elem
(lib.elemAt (lib.strings.splitString "@" address) 1) (lib.elemAt (lib.strings.splitString "@" address) 1)
[ "mailbox.tu-dresden.de" ]; [ "mailbox.tu-dresden.de" ];
in in
{ {
source = source =
if notmuch.enable if notmuch.enable
then "notmuch://${config.accounts.email.maildirBasePath}" then "notmuch://${config.accounts.email.maildirBasePath}"
else "`imap://${quoteMailAddress userName}@${imap.host}`"; else "`imap://${quoteMailAddress userName}@${imap.host}`";
source-cred-cmd = "`${lib.concatStringsSep " " passwordCommand}`"; source-cred-cmd = "`${lib.concatStringsSep " " passwordCommand}`";
# TODO: remove when copy-to is implemented in aerc for notmuch # TODO: remove when copy-to is implemented in aerc for notmuch
outgoing = outgoing =
if notmuch.enable if notmuch.enable
then "${./msmtp-wrapper} ${name}" then "${./msmtp-wrapper} ${name}"
else "`smtp${lib.optionalString requiresLogin "+login"}://${quoteMailAddress userName}@${smtp.host}`"; else "`smtp${lib.optionalString requiresLogin "+login"}://${quoteMailAddress userName}@${smtp.host}`";
outgoing-cred-cmd = "`${lib.concatStringsSep " " passwordCommand}`"; outgoing-cred-cmd = "`${lib.concatStringsSep " " passwordCommand}`";
from = "${realName} <${address}>"; from = "${realName} <${address}>";
smtp-starttls = if smtp.tls.useStartTls then "yes" else "no"; smtp-starttls = if smtp.tls.useStartTls then "yes" else "no";
copy-to = "Sent"; copy-to = "Sent";
signature-file = pkgs.writeText "signature-${name}" signature.text; signature-file = toString (pkgs.writeText "signature-${name}" signature.text);
pgp-key-id = gpg.key; pgp-key-id = gpg.key;
pgp-auto-sign = gpg.signByDefault; pgp-auto-sign = gpg.signByDefault;
pgp-opportunistic-encrypt = gpg.encryptByDefault; pgp-opportunistic-encrypt = gpg.encryptByDefault;
} // (lib.optionalAttrs notmuch.enable { } // (lib.optionalAttrs notmuch.enable {
query-map = pkgs.writeText "aerc-query-map" '' query-map = toString (pkgs.writeText "aerc-query-map" ''
Archive=not tag:inbox and not tag:sent Archive=not tag:inbox and not tag:sent
Git=tag:git Git=tag:git
INBOX=tag:inbox INBOX=tag:inbox
Newsletter=tag:newsletter Newsletter=tag:newsletter
Sent=tag:sent Sent=tag:sent
Spam=tag:spam Spam=tag:spam
Trash=tag:deleted Trash=tag:deleted
eBay Kleinanzeigen=tag:kleinanzeigen eBay Kleinanzeigen=tag:kleinanzeigen
eBay=tag:ebay eBay=tag:ebay
''; '');
exclude-tags = lib.concatStringsSep "," [ exclude-tags = lib.concatStringsSep "," [
"archived" "archived"
"deleted" "deleted"
"spam" "spam"
]; ];
})) }))
(lib.filterAttrs (lib.filterAttrs
(_: config: config.aerc.enable) (_: config: config.aerc-sbruder.enable)
config.accounts.email.accounts)); config.accounts.email.accounts));
"aerc/aerc.conf".text = lib.generators.toINI { } { extraConfig = {
general = { general = {
pgp-provider = "gpg"; # internal does not work pgp-provider = "gpg"; # internal does not work
@ -124,10 +121,10 @@ in
}; };
filters = { filters = {
"subject,~^\\[PATCH" = "awk -f ${package}/share/aerc/filters/hldiff"; "subject,~^\\[PATCH" = "awk -f ${pkgs.aerc}/share/aerc/filters/hldiff";
"text/plain" = "${./colorize}"; # taken from upstream and patched "text/plain" = "${./colorize}"; # taken from upstream and patched
"text/html" = "html"; # internal filter "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 "text/calendar" = "${pkgs.python3.withPackages (ps: with ps; [ vobject ])}/bin/python ${pkgs.aerc}/share/aerc/filters/show-ics-details.py"; # hacky fix for broken nix support
}; };
triggers = { triggers = {
@ -137,8 +134,8 @@ in
templates = { }; templates = { };
}; };
"aerc/binds.conf".text = lib.generators.toINIWithGlobalSection { } { extraBinds = {
globalSection = { global = {
# Binds are of the form <key sequence> = <command to run> # Binds are of the form <key sequence> = <command to run>
# To use '=' in a key sequence, substitute it with "Eq": "<Ctrl+Eq>" # To use '=' in a key sequence, substitute it with "Eq": "<Ctrl+Eq>"
# If you wish to bind #, you can wrap the key sequence in quotes: "#" = quit # If you wish to bind #, you can wrap the key sequence in quotes: "#" = quit
@ -147,163 +144,167 @@ in
"<C-t>" = ":term<Enter>"; "<C-t>" = ":term<Enter>";
}; };
sections = { messages = {
messages = { "q" = ":quit<Enter>";
"q" = ":quit<Enter>";
"<C-r>" = ":exec notmuch new<Enter>"; "<C-r>" = ":exec notmuch new<Enter>";
"j" = ":next<Enter>"; "j" = ":next<Enter>";
"<Down>" = ":next<Enter>"; "<Down>" = ":next<Enter>";
"<C-d>" = ":next 50%<Enter>"; "<C-d>" = ":next 50%<Enter>";
"<C-f>" = ":next 100%<Enter>"; "<C-f>" = ":next 100%<Enter>";
"<PgDn>" = ":next 100%<Enter>"; "<PgDn>" = ":next 100%<Enter>";
"k" = ":prev<Enter>"; "k" = ":prev<Enter>";
"<Up>" = ":prev<Enter>"; "<Up>" = ":prev<Enter>";
"<C-u>" = ":prev 50%<Enter>"; "<C-u>" = ":prev 50%<Enter>";
"<C-b>" = ":prev 100%<Enter>"; "<C-b>" = ":prev 100%<Enter>";
"<PgUp>" = ":prev 100%<Enter>"; "<PgUp>" = ":prev 100%<Enter>";
"g" = ":select 0<Enter>"; "g" = ":select 0<Enter>";
"G" = ":select -1<Enter>"; "G" = ":select -1<Enter>";
"J" = ":next-folder<Enter>"; "J" = ":next-folder<Enter>";
"K" = ":prev-folder<Enter>"; "K" = ":prev-folder<Enter>";
"H" = ":collapse-folder<Enter>"; "H" = ":collapse-folder<Enter>";
"L" = ":expand-folder<Enter>"; "L" = ":expand-folder<Enter>";
"v" = ":mark -t<Enter>"; "v" = ":mark -t<Enter>";
"V" = ":mark -v<Enter>"; "V" = ":mark -v<Enter>";
"T" = ":toggle-threads<Enter>"; "T" = ":toggle-threads<Enter>";
"<Enter>" = ":view<Enter>"; "<Enter>" = ":view<Enter>";
#"d" = ":prompt 'Really delete this message?' ':modify-labels +deleted'<Enter>"; # does not work #"d" = ":prompt 'Really delete this message?' ':modify-labels +deleted'<Enter>"; # does not work
"D" = ":modify-labels +deleted -inbox<Enter>"; "D" = ":modify-labels +deleted -inbox<Enter>";
"A" = ":modify-labels -inbox<Enter>"; "A" = ":modify-labels -inbox<Enter>";
"ms" = ":modify-labels +spam -inbox<Enter>"; "ms" = ":modify-labels +spam -inbox<Enter>";
"mS" = ":modify-labels -spam +inbox<Enter>"; "mS" = ":modify-labels -spam +inbox<Enter>";
"mn" = ":modify-labels +newsletter<Enter>"; "mn" = ":modify-labels +newsletter<Enter>";
"mN" = ":modify-labels -newsletter<Enter>"; "mN" = ":modify-labels -newsletter<Enter>";
"C" = ":compose<Enter>"; "C" = ":compose<Enter>";
"rr" = ":reply -a<Enter>"; "rr" = ":reply -a<Enter>";
"rq" = ":reply -aq<Enter>"; "rq" = ":reply -aq<Enter>";
"Rr" = ":reply<Enter>"; "Rr" = ":reply<Enter>";
"Rq" = ":reply -q<Enter>"; "Rq" = ":reply -q<Enter>";
"c" = ":cf<space>"; "c" = ":cf<space>";
"$" = ":term<space>"; "$" = ":term<space>";
"!" = ":term<space>"; "!" = ":term<space>";
"|" = ":pipe<space>"; "|" = ":pipe<space>";
"/" = ":search<space>"; "/" = ":search<space>";
"\\" = ":filter<space>"; "\\" = ":filter<space>";
"n" = ":next-result<Enter>"; "n" = ":next-result<Enter>";
"N" = ":prev-result<Enter>"; "N" = ":prev-result<Enter>";
"<Esc>" = ":clear<Enter>"; "<Esc>" = ":clear<Enter>";
}; };
view = { view = {
"/" = ":toggle-key-passthrough<Enter>/"; "/" = ":toggle-key-passthrough<Enter>/";
"q" = ":close<Enter>"; "q" = ":close<Enter>";
"O" = ":open<Enter>"; "O" = ":open<Enter>";
"S" = ":save<space>"; "S" = ":save<space>";
"|" = ":pipe<space>"; "|" = ":pipe<space>";
"D" = ":modify-labels +deleted -inbox<Enter>"; "D" = ":modify-labels +deleted -inbox<Enter>";
"A" = ":modify-labels -inbox<Enter>"; "A" = ":modify-labels -inbox<Enter>";
"f" = ":forward<Enter>"; "f" = ":forward<Enter>";
"rr" = ":reply -a<Enter>"; "rr" = ":reply -a<Enter>";
"rq" = ":reply -aq<Enter>"; "rq" = ":reply -aq<Enter>";
"Rr" = ":reply<Enter>"; "Rr" = ":reply<Enter>";
"Rq" = ":reply -q<Enter>"; "Rq" = ":reply -q<Enter>";
"H" = ":toggle-headers<Enter>"; "H" = ":toggle-headers<Enter>";
"<C-k>" = ":prev-part<Enter>"; "<C-k>" = ":prev-part<Enter>";
"<C-j>" = ":next-part<Enter>"; "<C-j>" = ":next-part<Enter>";
"J" = ":next<Enter>"; "J" = ":next<Enter>";
"K" = ":prev<Enter>"; "K" = ":prev<Enter>";
}; };
"view::passthrough" = { "view::passthrough" = {
"$noinherit" = "true"; "$noinherit" = "true";
"$ex" = "<C-x>"; "$ex" = "<C-x>";
"<Esc>" = ":toggle-key-passthrough<Enter>"; "<Esc>" = ":toggle-key-passthrough<Enter>";
}; };
# Keybindings used when the embedded terminal is not selected in the compose view" # Keybindings used when the embedded terminal is not selected in the compose view"
compose = { compose = {
"$ex" = "<C-x>"; "$ex" = "<C-x>";
"<C-k>" = ":prev-field<Enter>"; "<C-k>" = ":prev-field<Enter>";
"<C-j>" = ":next-field<Enter>"; "<C-j>" = ":next-field<Enter>";
"<tab>" = ":next-field<Enter>"; "<tab>" = ":next-field<Enter>";
"<backtab>" = ":prev-field<Enter>"; "<backtab>" = ":prev-field<Enter>";
}; };
# Keybindings used when the embedded terminal is selected in the compose view # Keybindings used when the embedded terminal is selected in the compose view
"compose::editor" = { "compose::editor" = {
"$noinherit" = "true"; "$noinherit" = "true";
"$ex" = "<C-x>"; "$ex" = "<C-x>";
"<C-k>" = ":prev-field<Enter>"; "<C-k>" = ":prev-field<Enter>";
"<C-j>" = ":next-field<Enter>"; "<C-j>" = ":next-field<Enter>";
"<C-p>" = ":prev-tab<Enter>"; "<C-p>" = ":prev-tab<Enter>";
"<C-n>" = ":next-tab<Enter>"; "<C-n>" = ":next-tab<Enter>";
}; };
# Keybindings used when reviewing a message to be sent # Keybindings used when reviewing a message to be sent
"compose::review" = { "compose::review" = {
"y" = ":send<Enter>"; "y" = ":send<Enter>";
"n" = ":abort<Enter>"; "n" = ":abort<Enter>";
"p" = ":postpone<Enter>"; "p" = ":postpone<Enter>";
"q" = ":choose -o d discard abort -o p postpone postpone<Enter>"; "q" = ":choose -o d discard abort -o p postpone postpone<Enter>";
"e" = ":edit<Enter>"; "e" = ":edit<Enter>";
"a" = ":attach<space>"; "a" = ":attach<space>";
"d" = ":detach<space>"; "d" = ":detach<space>";
}; };
terminal = { terminal = {
"$noinherit" = "true"; "$noinherit" = "true";
"$ex" = "<C-x>"; "$ex" = "<C-x>";
"<C-p>" = ":prev-tab<Enter>"; "<C-p>" = ":prev-tab<Enter>";
"<C-n>" = ":next-tab<Enter>"; "<C-n>" = ":next-tab<Enter>";
};
}; };
}; };
"aerc/stylesets/default".text = lib.concatStrings stylesets = {
(lib.mapAttrsToList default = {
(k: v: "${k} = ${if lib.isBool v then (if v then "true" else "false") else toString v}\n") "*.selected.reverse" = true;
{
"*.selected.reverse" = true;
"title.reverse" = true; "title.reverse" = true;
"header.bold" = true; "header.bold" = true;
"*error.bold" = true; "*error.bold" = true;
"error.fg" = 1; "error.fg" = 1;
"warning.fg" = 3; "warning.fg" = 3;
"success.fg" = 2; "success.fg" = 2;
"statusline_default.bg" = 0; "statusline_default.bg" = 0;
"statusline_error.fg" = 1; "statusline_error.fg" = 1;
"statusline_error.reverse" = true; "statusline_error.reverse" = true;
"statusline_success.fg" = 2; "statusline_success.fg" = 2;
"statusline_success.reverse" = true; "statusline_success.reverse" = true;
"msglist_unread.bold" = true; "msglist_unread.bold" = true;
"msglist_deleted.fg" = 10; "msglist_deleted.fg" = 10;
"tab.bg" = 11; "tab.bg" = 11;
"tab.selected.reverse" = false; "tab.selected.reverse" = false;
"tab.selected.bg" = 12; "tab.selected.bg" = 12;
"tab.fg" = 0; "tab.fg" = 0;
"completion_default.bg" = 0; "completion_default.bg" = 0;
}); };
};
}; };
#quoteMailAddress = lib.replaceChars [ "@" "\\" ] [ "%40" "%5C" ];
## home-manager has no way to set if an account requires AUTH LOGIN
## this emulats this by setting a list of known providers that do require it
#requiresLogin = lib.elem
# (lib.elemAt (lib.strings.splitString "@" address) 1)
# [ "mailbox.tu-dresden.de" ];
}; };
} }