Commit 96fe19dd4da3

Vincent Demeester <vincent@sbr.pm>
2026-01-14 20:18:44
feat(mail): Add goimapnotify for instant mail delivery via IMAP IDLE
- Sync mail immediately when new messages arrive on server - Automatically create services for all mbsync-enabled accounts - Trigger mu indexing and notify Emacs after mail sync - Remove mu4e periodic polling (now handled by push notifications) - Enable on both athena (iCloud) and kyushu (Gmail/RedHat) Signed-off-by: Vincent Demeester <vincent@sbr.pm>
1 parent 8e0ef35
Changed files (4)
dots
.config
emacs
home
common
systems
dots/.config/emacs/init.el
@@ -2128,8 +2128,9 @@ Add this function to the `after-save-hook'."
   (mu4e-change-filenames-when-moving t)
   (mu4e-attachment-dir "~/desktop/downloads")
   :config
-  (setq mu4e-get-mail-command (concat (executable-find "mbsync") " --all"))
-  (setq mu4e-update-interval 1800) ; 30m
+  ;; No need for get-mail-command - goimapnotify handles syncing via IMAP IDLE
+  ;; Disable automatic polling - mail arrives instantly via goimapnotify
+  (setq mu4e-update-interval nil)
 
   ;; Configure msmtp for sending mail
   (setq sendmail-program "msmtp"
home/common/services/goimapnotify.nix
@@ -0,0 +1,81 @@
+{
+  pkgs,
+  config,
+  hostname,
+  ...
+}:
+let
+  # Helper function to create goimapnotify config for an account
+  mkAccountConfig =
+    accountName: accountConfig:
+    let
+      # Determine if this is a Gmail account
+      isGmail = accountConfig.flavor or "" == "gmail.com";
+    in
+    ''
+      host: ${accountConfig.imap.host}
+      port: ${toString (accountConfig.imap.port or 993)}
+      tls: true
+      tlsOptions:
+        rejectUnauthorized: true
+      username: ${accountConfig.userName}
+      passwordCmd: ${accountConfig.passwordCommand}
+
+      # Monitor INBOX for new mail
+      boxes:
+        - INBOX
+
+      # Sync mail when new messages arrive
+      onNewMail: |
+        ${pkgs.isync}/bin/mbsync ${accountName}
+        ${pkgs.mu}/bin/mu index --quiet
+
+      # Notify Emacs after indexing (if running)
+      onNewMailPost: |
+        ${pkgs.emacs}/bin/emacsclient --eval '(mu4e-update-index)' 2>/dev/null || true
+    '';
+
+  # Get enabled email accounts that have mbsync enabled
+  enabledAccounts = builtins.filter (
+    name: (config.accounts.email.accounts.${name}.mbsync.enable or false)
+  ) (builtins.attrNames config.accounts.email.accounts);
+in
+{
+  # Install goimapnotify package
+  home.packages = [ pkgs.goimapnotify ];
+
+  # Create configuration files for each account
+  xdg.configFile = builtins.listToAttrs (
+    map (accountName: {
+      name = "goimapnotify/${accountName}.yaml";
+      value = {
+        text = mkAccountConfig accountName config.accounts.email.accounts.${accountName};
+      };
+    }) enabledAccounts
+  );
+
+  # Create systemd services for each account
+  systemd.user.services = builtins.listToAttrs (
+    map (accountName: {
+      name = "goimapnotify-${accountName}";
+      value = {
+        Unit = {
+          Description = "goimapnotify for ${accountName} IMAP IDLE";
+          After = [ "network-online.target" ];
+          Wants = [ "network-online.target" ];
+        };
+
+        Service = {
+          Type = "simple";
+          ExecStart = "${pkgs.goimapnotify}/bin/goimapnotify -conf %h/.config/goimapnotify/${accountName}.yaml";
+          Restart = "on-failure";
+          RestartSec = "30s";
+        };
+
+        Install = {
+          WantedBy = [ "default.target" ];
+        };
+      };
+    }) enabledAccounts
+  );
+}
systems/athena/home.nix
@@ -2,6 +2,7 @@
 {
   imports = [
     ../../home/common/desktop/passage.nix
+    ../../home/common/services/goimapnotify.nix
     ../../home/common/services/imapfilter.nix
   ];
 
systems/kyushu/home.nix
@@ -11,6 +11,7 @@ in
     ../../home/common/dev/containers.nix
     ../../home/common/dev/tektoncd.nix
     ../../home/common/services/color-scheme-timer.nix
+    ../../home/common/services/goimapnotify.nix
     ../../home/common/services/redhat.nix
   ];
   nixpkgs.config.allowUnfree = true;