{ 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" ]; }; }