{...}: { config.flake.modules.homeManager.mail = { lib, config, pkgs, ... }: let default_account_params = { realName = "Aner Zakobar"; mbsync = { enable = true; create = "maildir"; remove = "both"; expunge = "both"; }; msmtp.enable = true; }; default_gmail_params = default_account_params // { flavor = "gmail.com"; }; default_smtp = { tls = { enable = true; useStartTls = true; certificatesFile = "/etc/ssl/certs/ca-certificates.crt"; }; }; # mbsync's PassCmd shells out to `pass`, which needs the GPG smartcard to # decrypt. On a timer, a missing card would otherwise surface as a # pinentry "please insert card" prompt every run. `gpg --card-status` # only queries the card reader (no pinentry involved either way), so it's # safe to use as a silent presence check: skip the sync entirely when the # card isn't there, instead of letting mbsync hit that prompt. # # New mail is detected by counting files under every account's Maildir # "new" subdirectory before and after the sync -- that's where messages # the server hasn't marked seen land, across all three accounts at once, # with no need to touch mu's index. A rise in that count means mail # actually arrived, so only then does it post a desktop notification via # notify-send -- intentionally separate from mu4e's own "mbsync -a" (its # mu4e-get-mail-command), which doesn't go through this script at all. mbsyncSafe = pkgs.writeShellScript "mbsync-safe" '' if ! ${pkgs.gnupg}/bin/gpg --card-status >/dev/null 2>&1; then exit 0 fi before=$(find "$HOME/Maildir" -path '*/new/*' -type f 2>/dev/null | wc -l) ${pkgs.isync}/bin/mbsync -a after=$(find "$HOME/Maildir" -path '*/new/*' -type f 2>/dev/null | wc -l) new=$((after - before)) if [ "$new" -gt 0 ]; then label="new message" [ "$new" -ne 1 ] && label="new messages" ${pkgs.libnotify}/bin/notify-send "Mail" "$new $label" fi ''; in { options.azos.mail.enable = lib.mkOption { default = true; type = lib.types.bool; }; config = lib.mkIf config.azos.mail.enable { programs = { mu.enable = true; mbsync.enable = true; msmtp.enable = true; }; home.activation.muInit = lib.hm.dag.entryAfter ["writeBoundary"] '' if [ ! -d "$HOME/.cache/mu" ]; then $DRY_RUN_CMD ${pkgs.mu}/bin/mu init \ --maildir="$HOME/Maildir" \ --my-address=aner@zakobar.com \ --my-address=anerisgreat@gmail.com \ --my-address=anerz@post.bgu.ac.il fi ''; accounts.email.accounts = { gmail = default_gmail_params // { address = "anerisgreat@gmail.com"; userName = "anerisgreat"; passwordCommand = "pass mbsync/anerisgreat@gmail.com | head -1"; }; bgu = default_gmail_params // { address = "anerz@post.bgu.ac.il"; userName = "anerz@post.bgu.ac.il"; passwordCommand = "pass mbsync/anerz@post.bgu.ac.il | head -1"; }; zakobar = default_account_params // { address = "aner@zakobar.com"; primary = true; userName = "aner@zakobar.com"; imap = {host = "mail.privateemail.com";}; smtp = default_smtp // { port = 587; host = "mail.privateemail.com"; }; passwordCommand = "pass privateemail.com | head -1"; }; }; systemd.user.services.mbsync-timer = { Unit.Description = "Sync mail via mbsync (skips silently if smartcard is absent)"; Service = { Type = "oneshot"; ExecStart = "${mbsyncSafe}"; }; }; systemd.user.timers.mbsync-timer = { Unit.Description = "Periodic mbsync mail sync"; Timer = { OnStartupSec = "2m"; OnUnitActiveSec = "5m"; }; Install.WantedBy = ["timers.target"]; }; }; }; }