diff options
Diffstat (limited to 'home/mail')
| -rw-r--r-- | home/mail/default.nix | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/home/mail/default.nix b/home/mail/default.nix new file mode 100644 index 0000000..2b2b031 --- /dev/null +++ b/home/mail/default.nix @@ -0,0 +1,244 @@ +{ pkgs, config, ... }: + +let + # Common configuration for Gmail-based accounts + mkGmailAccount = + { + name, + address, + userName, + passwordCommand, + primary ? false, + }: + let + accountConfig = { + inherit + primary + address + userName + passwordCommand + ; + realName = "Petri Hienonen"; + + imap = { + host = "imap.gmail.com"; + port = 993; + tls.enable = true; + }; + + smtp = { + host = "smtp.gmail.com"; + port = 587; + tls.enable = true; + }; + + maildir = { + path = name; + }; + + mbsync = { + enable = true; + create = "both"; + expunge = "both"; + remove = "both"; + patterns = [ + "*" + "!Drafts" + "!Sent Mail" + ]; + extraConfig.channel = { + CopyArrivalDate = "yes"; + SyncState = "*"; + }; + }; + + notmuch.enable = true; + + himalaya = { + enable = true; + settings = { + inherit primary; + display-name = "Petri Hienonen"; + signature = "Regards,\nPetri Hienonen"; + signature-delim = "-- \n"; + + "backend.type" = "notmuch"; + "backend.db-path" = "${config.home.homeDirectory}/Mail/${name}"; + + "folder.aliases.inbox" = "INBOX"; + "folder.aliases.sent" = "Sent Mail"; + "folder.aliases.drafts" = "Drafts"; + "folder.aliases.trash" = "Trash"; + + "message.write.headers" = [ + "From" + "To" + "Cc" + "Bcc" + "Subject" + ]; + "message.send.save-copy" = true; + "message.delete.style" = "folder"; + + "template.new.signature-style" = "inlined"; + "template.reply.posting-style" = "top"; + "template.reply.signature-style" = "below-quote"; + "template.reply.quote-headline-fmt" = "On %d/%m/%Y %H:%M, {senders} wrote:\n"; + + "message.send.backend.type" = "smtp"; + "message.send.backend.host" = "smtp.gmail.com"; + "message.send.backend.port" = 465; + "message.send.backend.login" = userName; + "message.send.backend.auth.type" = "password"; + "message.send.backend.auth.cmd" = passwordCommand; + + "pgp.type" = "commands"; + "pgp.encrypt-cmd" = "${pkgs.gnupg}/bin/gpg --encrypt --armor --quiet -r '%r'"; + "pgp.decrypt-cmd" = "${pkgs.gnupg}/bin/gpg --decrypt --quiet"; + "pgp.sign-cmd" = "${pkgs.gnupg}/bin/gpg --sign --armor --quiet --default-key '%s'"; + "pgp.verify-cmd" = "${pkgs.gnupg}/bin/gpg --verify --quiet"; + }; + }; + + aerc = { + enable = true; + }; + + imapnotify = { + enable = true; + boxes = [ "INBOX" ]; + onNotify = emailNotifyScript name; + extraConfig.wait = 60; + }; + }; + in + accountConfig; + + # Simplified notification script that only extracts sender and subject + emailNotifyScript = + account: + pkgs.writeShellScript "email-notify-${account}" '' + set -euo pipefail + + # Sync this account specifically + ${pkgs.isync}/bin/mbsync "${account}" + + # Wait a moment for notmuch to index + sleep 2 + ${pkgs.notmuch}/bin/notmuch new + + LATEST_MSG=$(${pkgs.notmuch}/bin/notmuch search --output=messages --limit=1 "tag:unread and folder:${account}/INBOX" | head -1) + + if [ -n "$LATEST_MSG" ]; then + # Extract sender and subject using notmuch show + SENDER=$(${pkgs.notmuch}/bin/notmuch show --format=json "$LATEST_MSG" | ${pkgs.jq}/bin/jq -r '.[][0].headers.From // "Unknown sender"') + SUBJECT=$(${pkgs.notmuch}/bin/notmuch show --format=json "$LATEST_MSG" | ${pkgs.jq}/bin/jq -r '.[][0].headers.Subject // "No subject"') + + # Send notification + ${pkgs.libnotify}/bin/notify-send -i mail-unread -a "Email" \ + "New email in ${account}" \ + "From: $SENDER\nSubject: $SUBJECT" \ + -t 10000 # 10 second timeout + fi + ''; + +in +{ + accounts.email = { + maildirBasePath = "${config.home.homeDirectory}/Mail"; + + accounts = { + gmail = mkGmailAccount { + name = "gmail"; + primary = true; + address = "petri.hienonen@gmail.com"; + userName = "petri.hienonen@gmail.com"; + passwordCommand = "${pkgs.coreutils}/bin/cat ${config.age.secrets.gmail.path}"; + }; + + relesoft = mkGmailAccount { + name = "relesoft"; + primary = false; + address = "petri.hienonen@relesoft.io"; + userName = "petri.hienonen@relesoft.io"; + passwordCommand = "${pkgs.coreutils}/bin/cat ${config.age.secrets.relesoft.path}"; + }; + }; + }; + + # Global settings for programs (not account-specific) + programs.mbsync.enable = true; + + programs.notmuch = { + enable = true; + hooks = { + preNew = "${pkgs.isync}/bin/mbsync -a || true"; + }; + new = { + tags = [ + "new" + "unread" + ]; + ignore = [ + "/.*[.](json|lock|bak)$/" + ".uidvalidity" + ".mbsyncstate" + ".mbsyncstate.journal" + ".msoepln" + ".mbsyncstate.new" + ".mbsyncstate.lock" + ]; + }; + }; + + programs.himalaya = { + enable = true; + package = pkgs.himalaya.override { + withFeatures = [ + "notmuch" + "pgp-gpg" + ]; + }; + }; + + # aerc configuration + programs.aerc = { + enable = true; + # aerc will automatically pick up accounts from accounts.email + # Additional aerc-wide configuration can go here + extraConfig = { + general = { + unsafe-accounts-conf = true; + # Example aerc configuration + # ui.message-list-time-format = "2006-01-02 15:04" + # ui.timestamp-format = "2006-01-02 15:04" + }; + }; + }; + + systemd.user.services.mbsync = { + Unit = { + Description = "Sync mail with mbsync"; + After = [ "network-online.target" ]; + Wants = [ "network-online.target" ]; + }; + Service = { + Type = "oneshot"; + ExecStart = "${pkgs.isync}/bin/mbsync -a"; + }; + Install.WantedBy = [ "default.target" ]; + }; + + systemd.user.timers.mbsync = { + Unit = { + Description = "Timer for mbsync mail synchronization"; + Requires = "mbsync.service"; + }; + Timer = { + OnBootSec = "5m"; + OnUnitInactiveSec = "5m"; + Unit = "mbsync.service"; + }; + Install.WantedBy = [ "timers.target" ]; + }; +} |
