Compare commits

...

2 Commits

Author SHA1 Message Date
aner f079a39cbc Make elfeed-protocol Nextcloud password fetch retriable
A failed pass/gpg fetch (e.g. YubiKey not plugged in yet) used to pass
process output straight to string-trim, which signals instead of
returning nil on empty output, aborting the sentinel before
elfeed-feeds or elfeed-protocol-enable ran. That left elfeed-feeds nil
for the rest of the session with no visible error beyond a *Messages*
line, and every later elfeed-update silently had nothing to fetch.

Wrap the fetch in azos/elfeed-protocol-init-feeds so a failed attempt
can be retried interactively instead of requiring a full reload of the
elfeed-protocol feature.
2026-10-08 13:14:14 +03:00
aner edd18bafdd Remove unused lieer, add silent periodic mbsync timer; bump azos-core
lieer was declared (programs/services.lieer.enable) but had zero real
footprint — mu4e actually fetches via mbsync (mu4e-get-mail-command is
literally "mbsync -a") and sends via msmtp; lieer never had an auth/sync
state file anywhere. Drop it to stop the config suggesting a sync path
that isn't actually in use.

Add a systemd user timer that runs mbsync every 5 minutes. mbsync's
PassCmd shells out to `pass`, which needs the GPG smartcard; on a blind
timer a missing card would otherwise surface as a pinentry "please
insert card" prompt every run. The wrapper script gates the sync behind
`gpg --card-status`, which only queries the reader without invoking
pinentry either way, so a missing card is now a silent no-op instead of
a nag.

Bump azos-core for EDNC popup notifications.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-08 13:14:08 +03:00
3 changed files with 64 additions and 17 deletions
+37 -14
View File
@@ -207,12 +207,9 @@ deprecation warning, and =elfeed-feeds= ends up with the bare URL
and no =:password=, so requests silently authenticate with an empty
password and nothing ever lands in the db.
This =:config= block runs synchronously the first time =elfeed= is
loaded (i.e. the first =M-x elfeed= of the session), with no user
keypress behind it the way =azos/caldav-sync= has. Fetching the
password with =shell-command-to-string= there used to deadlock
Emacs whenever the GPG PIN cache had expired: that call blocks
Emacs's single thread on the =pass|gpg= subprocess, but
Fetching the password with =shell-command-to-string= used to
deadlock Emacs whenever the GPG PIN cache had expired: that call
blocks Emacs's single thread on the =pass|gpg= subprocess, but
=pinentry-emacs= (see the GPG Pinentry section above) needs Emacs's
command loop running to answer its loopback prompt — so Emacs waits
on gpg-agent while gpg-agent waits on Emacs. Fetching the password
@@ -222,11 +219,27 @@ with =make-process= instead keeps the command loop alive, so
fires. Same stderr-redirect reasoning as before, to keep a stray
gpg/pass warning off the captured password.
The fetch is wrapped in a named, interactive function rather than
inlined in =:config= so a failed attempt (e.g. =pass= produced no
output because the YubiKey wasn't plugged in yet) can be retried
with =M-x azos/elfeed-protocol-init-feeds= — re-running =:config=
itself would require reloading the =elfeed-protocol= feature
entirely. An earlier version passed =(process-get proc 'output)=
straight to =string-trim=, which signals (not just returns nil) when
no output was ever read, aborting the sentinel before =elfeed-feeds=
or =elfeed-protocol-enable= ran — so a failed first attempt left
=elfeed-feeds= permanently =nil= for the rest of the session with no
visible error beyond a =*Messages*= line, and every subsequent
=elfeed-update= silently had nothing to fetch.
#+begin_src emacs-lisp
(use-package elfeed-protocol
:after elfeed
:config
(setq elfeed-protocol-enabled-protocols '(owncloud))
(defun azos/elfeed-protocol-init-feeds ()
"Fetch the Nextcloud password and (re)enable elfeed-protocol sync.
Unlike the one-shot `use-package' :config form this is called from,
safe to call again (e.g. via \\[azos/elfeed-protocol-init-feeds]) if
a previous attempt failed, such as the YubiKey not being plugged in
yet — it re-spawns the `pass' process and re-prompts for the PIN."
(interactive)
(make-process
:name "elfeed-protocol-pass"
:command '("sh" "-c" "pass zakobar.com 2>/dev/null | head -1")
@@ -234,10 +247,20 @@ gpg/pass warning off the captured password.
:filter (lambda (proc chunk)
(process-put proc 'output (concat (or (process-get proc 'output) "") chunk)))
:sentinel (lambda (proc _event)
(setq elfeed-feeds
`(("owncloud+https://aner@nextcloud.zakobar.com"
:password ,(string-trim (process-get proc 'output)))))
(elfeed-protocol-enable))))
(let ((password (string-trim (or (process-get proc 'output) ""))))
(if (string-empty-p password)
(message "elfeed-protocol: `pass zakobar.com' produced no output; retry with M-x azos/elfeed-protocol-init-feeds")
(setq elfeed-feeds
`(("owncloud+https://aner@nextcloud.zakobar.com"
:password ,password)))
(elfeed-protocol-enable)
(elfeed-update))))))
(use-package elfeed-protocol
:after elfeed
:config
(setq elfeed-protocol-enabled-protocols '(owncloud))
(azos/elfeed-protocol-init-feeds))
#+end_src
** Elfeed Full Article Fetch
+26 -2
View File
@@ -25,6 +25,17 @@
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.
mbsyncSafe = pkgs.writeShellScript "mbsync-safe" ''
if ${pkgs.gnupg}/bin/gpg --card-status >/dev/null 2>&1; then
exec ${pkgs.isync}/bin/mbsync -a
fi
'';
in {
options.azos.mail.enable = lib.mkOption {
default = true;
@@ -35,7 +46,6 @@
mu.enable = true;
mbsync.enable = true;
msmtp.enable = true;
lieer.enable = true;
};
home.activation.muInit = lib.hm.dag.entryAfter ["writeBoundary"] ''
if [ ! -d "$HOME/.cache/mu" ]; then
@@ -46,7 +56,6 @@
--my-address=anerz@post.bgu.ac.il
fi
'';
services.lieer.enable = true;
accounts.email.accounts = {
gmail =
default_gmail_params
@@ -78,6 +87,21 @@
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"];
};
};
};
}