diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..7c5e21f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "submodules/much"] + path = submodules/much + url = git@github.com:kmein/much diff --git a/configs/mail.nix b/configs/mail.nix index a34df2e..9b92a77 100644 --- a/configs/mail.nix +++ b/configs/mail.nix @@ -1,15 +1,12 @@ { config, pkgs, lib, ... }: let generateTaggingScript = filters: - let template = index: { tags, query, message ? "tagging ${query} -> ${lib.concatStringsSep " " tags}", ... }: - let - command = '' - ${pkgs.notmuch}/bin/notmuch tag ${lib.concatStringsSep " " tags} -- "${query}" - ''; - in '' + let + template = { tags, query, message ? "tagging ${query} -> ${lib.concatStringsSep " " tags}", ... }: '' echo '${message}' - ${command} - ''; in lib.concatStringsSep "\n" (lib.imap0 template filters); + ${pkgs.notmuch}/bin/notmuch tag ${lib.concatStringsSep " " tags} -- "${query}" + ''; + in lib.concatStringsSep "\n" (map template filters); taggingConfig = [ { @@ -34,35 +31,50 @@ let expunge = "both"; }; msmtp.enable = true; - neomutt.enable = true; notmuch.enable = true; }; - addArchiveCommand = folder: - lib.recursiveUpdate { - neomutt.extraConfig = '' - # named-mailboxes " └Archive" "=${folder}" - macro pager,index \' "+${folder}" "Archive" - ''; - }; + + much-pkg = pkgs.haskellPackages.callCabal2nix "much" {}; + much = pkgs.haskell.lib.dontHaddock much-pkg; in { environment.systemPackages = [ pkgs.neomutt - pkgs.haskellPackages.much - (pkgs.writers.writeDashBin "fetch-mail" '' + + (pkgs.writers.writeDashBin "mua" '' + if [ $# -eq 0 ]; then + ${much}/bin/much-kmein + else + ${much}/bin/much-kmein -q "$@" + fi + '') + + (pkgs.writers.writeDashBin "mail-fetch" '' ${pkgs.isync}/bin/mbsync --all ${pkgs.notmuch}/bin/notmuch new '') - (pkgs.writers.writeDashBin "notmuch-rm-deleted" '' + + (pkgs.writers.writeDashBin "mail-rm-deleted" '' ${pkgs.notmuch}/bin/notmuch search --output files --format=text0 tag:deleted | ${pkgs.findutils}/bin/xargs -r0 rm ${pkgs.notmuch}/bin/notmuch new '') ]; - home-manager.users.me = let maildir = "${config.users.users.me.home}/mail"; - in { - accounts.email.maildirBasePath = maildir; + home-manager.users.me = { + programs.msmtp.enable = true; + + programs.mbsync.enable = true; + + programs.notmuch = { + enable = true; + new.tags = [ "unread" "inbox" ]; + search.excludeTags = [ "deleted" "spam" ]; + hooks.postNew = generateTaggingScript taggingConfig; + }; + + accounts.email.maildirBasePath = "${config.users.users.me.home}/mail"; + accounts.email.accounts = { - fysi = addArchiveCommand "Archive" (enableDefaults { + fysi = enableDefaults { primary = false; smtp = { host = "smtp.fastmail.com"; @@ -78,8 +90,8 @@ in { address = "kieran@fysi.tech"; realName = config.niveum.user.name; passwordCommand = pass "mail/kieran@fysi.tech"; - }); - cock = addArchiveCommand "Archive" (enableDefaults { + }; + cock = enableDefaults { primary = false; smtp = { host = "mail.cock.li"; @@ -98,62 +110,54 @@ in { address = "2210@cock.li"; realName = "2210"; passwordCommand = pass "mail/2210@cock.li"; - }); - kieran-gmail = addArchiveCommand "[Gmail]/Alle Nachrichten" - (enableDefaults { - primary = false; - flavor = "gmail.com"; - address = "kieran.meinhardt@gmail.com"; - realName = config.niveum.user.name; - userName = "kieran.meinhardt"; - passwordCommand = pass "mail/kieran.meinhardt@gmail.com"; - folders = { - drafts = "[Gmail]/Entw&APw-rfe"; - sent = "[Gmail]/Gesendet"; - trash = "[Gmail]/Papierkorb"; + }; + kieran-gmail = enableDefaults { + primary = false; + flavor = "gmail.com"; + address = "kieran.meinhardt@gmail.com"; + realName = config.niveum.user.name; + userName = "kieran.meinhardt"; + passwordCommand = pass "mail/kieran.meinhardt@gmail.com"; + folders = { + drafts = "[Gmail]/Entw&APw-rfe"; + sent = "[Gmail]/Gesendet"; + trash = "[Gmail]/Papierkorb"; + }; + }; + amroplay = enableDefaults { + primary = false; + flavor = "gmail.com"; + address = "amroplay@gmail.com"; + realName = config.niveum.user.name; + userName = "amroplay"; + passwordCommand = pass "mail/amroplay@gmail.com"; + folders = { + drafts = "[Gmail]/Drafts"; + sent = "[Gmail]/Sent Mail"; + trash = "[Gmail]/Bin"; + }; + }; + posteo = enableDefaults { + primary = true; + smtp = { + host = "posteo.de"; + port = 587; + tls = { + enable = true; + useStartTls = true; }; - }); - amroplay = addArchiveCommand "[Gmail]/All Mail" - (enableDefaults { - primary = false; - flavor = "gmail.com"; - address = "amroplay@gmail.com"; - realName = config.niveum.user.name; - userName = "amroplay"; - passwordCommand = pass "mail/amroplay@gmail.com"; - folders = { - drafts = "[Gmail]/Drafts"; - sent = "[Gmail]/Sent Mail"; - trash = "[Gmail]/Bin"; - }; - }); - posteo = addArchiveCommand "Archive" - (enableDefaults { - primary = true; - smtp = { - host = "posteo.de"; - port = 587; - tls = { - enable = true; - useStartTls = true; - }; - }; - imap = { - host = "posteo.de"; - port = 993; - tls.enable = true; - }; - address = "kieran.meinhardt@posteo.net"; - realName = config.niveum.user.name; - userName = "kieran.meinhardt@posteo.net"; - passwordCommand = pass "shared/posteo/password"; - folders = { - drafts = "Drafts"; - sent = "Sent"; - trash = "Trash"; - }; - }); - hu-berlin = addArchiveCommand "Archives" (enableDefaults { + }; + imap = { + host = "posteo.de"; + port = 993; + tls.enable = true; + }; + address = "kieran.meinhardt@posteo.net"; + realName = config.niveum.user.name; + userName = "kieran.meinhardt@posteo.net"; + passwordCommand = pass "shared/posteo/password"; + }; + hu-berlin = enableDefaults { primary = false; address = "meinhark@hu-berlin.de"; realName = config.niveum.user.name; @@ -172,385 +176,7 @@ in { port = 993; tls.enable = true; }; - }); - }; - - programs.neomutt = { - enable = true; - sidebar.enable = true; - sort = "reverse-date"; # or reverse-threads - vimKeys = true; - checkStatsInterval = 60; - settings = { - attribution = ''"%n (%a), %d:"''; - date_format = ''"%Y-%m-%d %H:%M"''; - # envelope_from = "yes"; # THIS BREAKS SENDING VIA MSMTP (the default setting already contains msmtpq --read-envelope) - fast_reply = "yes"; # skip to compose when forwarding - fcc_attach = "no"; # save attachments with the body - forward_format = ''"→ %s"''; # format of subject when forwarding - forward_quote = "yes"; # include message in forwards - include = "yes"; # include message in replies - # index_format = "\"%2C %Z %?X?A& ? %D %-15.15F %s (%-4.4c)\""; - index_format = '' - "${ - pkgs.writeDash "mutt-index" '' - # http://www.mutt.org/doc/manual/#formatstrings - recipent="$(echo $1 | sed 's/[^,]*<\([^>]*\)[^,]*/ \1/g')" - # output to mutt - # V - echo "%4C %Z %?GI?%GI& ? %[%y-%m-%d] %-20.20a %?M?(%3M)& ? %s %> $recipent %?g?%g?%" - # args to mutt-index dash script - # V - '' - } %r |"''; - mail_check = - "60"; # to avoid lags using IMAP with some email providers (yahoo for example) - mail_check_stats = "yes"; - mark_old = "no"; # unread mail stay unread until read - markers = "no"; # disables the `+` displayed at line wraps - mime_forward = "yes"; # forward attachments with mail - # nm_default_uri = "notmuch://${maildir}"; - # nm_record = "yes"; - # nm_record_tags = "-inbox archive"; - virtual_spoolfile = "yes"; # enable virtual folders - reverse_name = "yes"; # reply as whomever it was to - rfc2047_parameters = "yes"; # decode RFC2047-encoded attachments - sleep_time = "0"; # pause 0 seconds for informational messages - use_from = "yes"; - wait_key = "no"; # mutt won't ask "press key to continue" - mailcap_path = toString (pkgs.writeText "mailcap" '' - text/plain; $EDITOR %s ; - text/html; ${pkgs.lynx}/bin/lynx -assume_charset=%{charset} -display_charset=utf-8 -dump %s; nametemplate=%s.html; copiousoutput; - image/*; ${pkgs.sxiv}/bin/sxiv %s ; - video/*; ${pkgs.utillinux}/bin/setsid ${pkgs.mpv}/bin/mpv --quiet %s &; copiousoutput ; - application/*; ${pkgs.xdg_utils}/bin/xdg-open %s ; - ''); }; - macros = [ - { - action = ".."; - map = "browser"; - key = "h"; - } # go to parent directory - { - action = "T~UN."; - map = "index"; - key = "\\Cr"; - } # mark all messages read - { - action = "mbsync -a"; - map = "index"; - key = "O"; - } # run mbsync to sync all mail - { - action = "all\\n"; - map = "index"; - key = "A"; - } # show all messages (undo limit) - # { action = "=Archiveecho 'Saved to Archive'"; map = "index"; key = ",a"; } - { - action = '' - unset wait_keyread -p 'Enter a search term to find with notmuch: ' x; echo \$x >~/.cache/mutt_terms~i \"\`notmuch search --output=messages $(cat ~/.cache/mutt_terms) | head -n 600 | perl -le '@a=<>;s/^id:// for@a;$,="|";print@a' | perl -le '@a=<>; chomp@a; s/\+/\\+/ for@a;print@a' \`\"''; - map = "index"; - key = "\\Cf"; - } - ]; - binds = [ - { - action = "complete-query"; - key = ""; - map = "editor"; - } - { - action = "display-message"; - key = "l"; - map = "index"; - } - { - action = "exit"; - key = "h"; - map = "attach"; - } - { - action = "exit"; - key = "h"; - map = "pager"; - } - { - action = "group-reply"; - key = "R"; - map = "index"; - } - { - action = "group-reply"; - key = "R"; - map = "pager"; - } - { - action = "limit"; - key = "L"; - map = "index"; - } - { - action = "next-entry"; - key = "j"; - map = "index"; - } - { - action = "next-line"; - key = "\\005"; - map = "pager"; - } # mouse wheel - { - action = "next-undeleted"; - key = "\\005"; - map = "index"; - } # mouse wheel - { - action = "noop"; - key = ""; - map = "editor"; - } - { - action = "noop"; - key = "\\Cf"; - map = "index"; - } - { - action = "noop"; - key = "h"; - map = "index"; - } - { - action = "noop"; - key = "i"; - map = "index"; - } - { - action = "noop"; - key = "i"; - map = "pager"; - } - { - action = "previous-entry"; - key = "k"; - map = "index"; - } - { - action = "previous-line"; - key = "\\031"; - map = "pager"; - } # mouse wheel - { - action = "previous-undeleted"; - key = "\\031"; - map = "index"; - } # mouse wheel - { - action = "select-entry"; - key = "l"; - map = "browser"; - } - { - action = "sidebar-next"; - key = "\\Cj"; - map = "index"; - } - { - action = "sidebar-next"; - key = "\\Cj"; - map = "pager"; - } - { - action = "sidebar-next-new"; - key = "\\Cn"; - map = "index"; - } - { - action = "sidebar-next-new"; - key = "\\Cn"; - map = "pager"; - } - { - action = "sidebar-open"; - key = "\\Co"; - map = "index"; - } - { - action = "sidebar-open"; - key = "\\Co"; - map = "pager"; - } - { - action = "sidebar-prev"; - key = "\\Ck"; - map = "index"; - } - { - action = "sidebar-prev"; - key = "\\Ck"; - map = "pager"; - } - { - action = "sidebar-prev-new"; - key = "\\Cp"; - map = "index"; - } - { - action = "sidebar-prev-new"; - key = "\\Cp"; - map = "pager"; - } - { - action = "sidebar-toggle-visible"; - key = "B"; - map = "index"; - } - { - action = "sidebar-toggle-visible"; - key = "B"; - map = "pager"; - } - { - action = "sync-mailbox"; - key = "S"; - map = "index"; - } - { - action = "sync-mailbox"; - key = "S"; - map = "pager"; - } - { - action = "tag-entry"; - key = ""; - map = "index"; - } - { - action = "undelete-message"; - key = "U"; - map = "index"; - } - { - action = "view-attachments"; - key = "l"; - map = "pager"; - } - { - action = "view-mailcap"; - key = ""; - map = "attach"; - } - { - action = "view-mailcap"; - key = "l"; - map = "attach"; - } - { - action = "view-raw-message"; - key = "H"; - map = "index"; - } - { - action = "view-raw-message"; - key = "H"; - map = "pager"; - } - ]; - extraConfig = '' - auto_view text/html # automatically show html - alternative_order text/plain text/enriched text/html - - # virtual-mailboxes "INBOX" "notmuch://?query=tag:inbox" - # virtual-mailboxes "Unread" "notmuch://?query=tag:unread" - # virtual-mailboxes "TODO" "notmuch://?query=tag:TODO" - # virtual-mailboxes "Starred" "notmuch://?query=tag:*" - # virtual-mailboxes "Archive" "notmuch://?query=tag:archive" - # virtual-mailboxes "Sent" "notmuch://?query=tag:sent" - # virtual-mailboxes "Junk" "notmuch://?query=tag:junk" - # virtual-mailboxes "All" "notmuch://?query=*" - - # Default index colors: - # color index yellow default '.*' - color index_author red default '.*' - color index_number blue default - color index_subject cyan default '.*' - - # New mail is boldened: - color index brightyellow black "~N" - color index_author brightred black "~N" - color index_subject brightcyan black "~N" - - # Tagged mail is highlighted: - color index brightyellow blue "~T" - color index_author brightred blue "~T" - color index_subject brightcyan blue "~T" - - # Other colors and aesthetic settings: - mono bold bold - mono underline underline - mono indicator reverse - mono error bold - color normal default default - color indicator brightblack white - color sidebar_highlight red default - color sidebar_divider brightblack black - color sidebar_flagged red black - color sidebar_new green black - color normal brightyellow default - color error red default - color tilde black default - color message cyan default - color markers red white - color attachment white default - color search brightmagenta default - color status brightyellow black - color hdrdefault brightgreen default - color quoted green default - color quoted1 blue default - color quoted2 cyan default - color quoted3 yellow default - color quoted4 red default - color quoted5 brightred default - color signature brightgreen default - color bold black default - color underline black default - color normal default default - - # Regex highlighting: - color header blue default ".*" - color header brightmagenta default "^(From)" - color header brightcyan default "^(Subject)" - color header brightwhite default "^(CC|BCC)" - color body brightred default "[\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+" # Email addresses - color body brightblue default "(https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+" # URL - color body green default "\`[^\`]*\`" # Green text between ` and ` - color body brightblue default "^# \.*" # Headings as bold blue - color body brightcyan default "^## \.*" # Subheadings as bold cyan - color body brightgreen default "^### \.*" # Subsubheadings as bold green - color body yellow default "^(\t| )*(-|\\*) \.*" # List items as yellow - color body brightcyan default "[;:][-o][)/(|]" # emoticons - color body brightcyan default "[;:][)(|]" # emoticons - color body brightcyan default "[ ][*][^*]*[*][ ]?" # more emoticon? - color body brightcyan default "[ ]?[*][^*]*[*][ ]" # more emoticon? - color body red default "(BAD signature)" - color body cyan default "(Good signature)" - color body brightblack default "^gpg: Good signature .*" - color body brightyellow default "^gpg: " - color body brightyellow red "^gpg: BAD signature from.*" - mono body bold "^gpg: Good signature" - mono body bold "^gpg: BAD signature from.*" - color body red default "([a-z][a-z0-9+-]*://(((([a-z0-9_.!~*'();:&=+$,-]|%[0-9a-f][0-9a-f])*@)?((([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?|[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)(:[0-9]+)?)|([a-z0-9_.!~*'()$,;:@&=+-]|%[0-9a-f][0-9a-f])+)(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*(/([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*(;([a-z0-9_.!~*'():@&=+$,-]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?(#([a-z0-9_.!~*'();/?:@&=+$,-]|%[0-9a-f][0-9a-f])*)?|(www|ftp)\\.(([a-z0-9]([a-z0-9-]*[a-z0-9])?)\\.)*([a-z]([a-z0-9-]*[a-z0-9])?)\\.?(:[0-9]+)?(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*(/([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*(;([-a-z0-9_.!~*'():@&=+$,]|%[0-9a-f][0-9a-f])*)*)*)?(\\?([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?(#([-a-z0-9_.!~*'();/?:@&=+$,]|%[0-9a-f][0-9a-f])*)?)[^].,:;!)? \t\r\n<>\"]" - ''; - }; - - programs.msmtp.enable = true; - programs.mbsync.enable = true; - programs.notmuch = { - enable = true; - new.tags = [ "unread" "inbox" ]; - search.excludeTags = [ "deleted" "spam" ]; - hooks.postNew = generateTaggingScript taggingConfig; }; }; } diff --git a/submodules/much b/submodules/much new file mode 160000 index 0000000..8e92e6e --- /dev/null +++ b/submodules/much @@ -0,0 +1 @@ +Subproject commit 8e92e6e11d2b3b0bfb5ac9d68f347219493e6380