From e04dacdf654a7b32eb684cfcdd0d9ecf815e4901 Mon Sep 17 00:00:00 2001 From: John Ogle Date: Mon, 22 Dec 2025 22:59:09 -0800 Subject: [PATCH] Add email support with notmuch, mbsync, and msmtp Set up complete email workflow in Emacs using: - notmuch for email indexing and UI - mbsync for IMAP synchronization from proton.johnogle.info - msmtp for SMTP sending via port 25 with PLAIN auth - systemd timer for automatic sync every 5 minutes Configuration includes: - New email role at home/roles/email with all mail tools - Doom Emacs notmuch module enabled with saved searches - Secure credential retrieval via rbw from Bitwarden - Fixed systemd service PATH to access rbw-agent - TLS/STARTTLS for secure connections Email role enabled on nix-book (laptop-compact profile). --- home/home-laptop-compact.nix | 1 + home/roles/default.nix | 1 + home/roles/emacs/doom/config.el | 26 +++++++ home/roles/emacs/doom/init.el | 2 +- home/roles/email/default.nix | 128 ++++++++++++++++++++++++++++++++ 5 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 home/roles/email/default.nix diff --git a/home/home-laptop-compact.nix b/home/home-laptop-compact.nix index 460b3ba..04e126c 100644 --- a/home/home-laptop-compact.nix +++ b/home/home-laptop-compact.nix @@ -14,6 +14,7 @@ desktop.enable = true; development.enable = true; communication.enable = true; + email.enable = true; kdeconnect.enable = true; media.enable = true; sync.enable = true; diff --git a/home/roles/default.nix b/home/roles/default.nix index 925dfca..b99375c 100644 --- a/home/roles/default.nix +++ b/home/roles/default.nix @@ -8,6 +8,7 @@ ./communication ./desktop ./development + ./email ./gaming ./kdeconnect ./kubectl diff --git a/home/roles/emacs/doom/config.el b/home/roles/emacs/doom/config.el index 03d97e7..0423bfd 100644 --- a/home/roles/emacs/doom/config.el +++ b/home/roles/emacs/doom/config.el @@ -159,6 +159,32 @@ (dolist (module '("bbdb" "buffer" "elisp" "emacs" "gnus" "os" "search-and-replace" "url")) (gptel-tool-library-load-module module))) +;; Notmuch email configuration +(after! notmuch + (setq notmuch-search-oldest-first nil + notmuch-show-logo nil + notmuch-fcc-dirs "proton/Sent" + + ;; User identity + user-mail-address "john@ogle.fyi" + user-full-name "John Ogle" + + ;; Sending mail via msmtp + message-send-mail-function 'message-send-mail-with-sendmail + sendmail-program (executable-find "msmtp") + message-sendmail-envelope-from 'header + mail-envelope-from 'header + mail-specify-envelope-from t + + ;; Saved searches for quick access + notmuch-saved-searches + '((:name "inbox" :query "tag:inbox" :key "i") + (:name "unread" :query "tag:unread" :key "u") + (:name "flagged" :query "tag:flagged" :key "f") + (:name "sent" :query "tag:sent" :key "t") + (:name "drafts" :query "tag:draft" :key "d") + (:name "all" :query "*" :key "a")))) + ;; Whenever you reconfigure a package, make sure to wrap your config in an ;; `after!' block, otherwise Doom's defaults may override your settings. E.g. ;; diff --git a/home/roles/emacs/doom/init.el b/home/roles/emacs/doom/init.el index 4718462..268cea5 100644 --- a/home/roles/emacs/doom/init.el +++ b/home/roles/emacs/doom/init.el @@ -177,7 +177,7 @@ :email ;;(mu4e +org +gmail) - ;;notmuch + notmuch ;;(wanderlust +gmail) :app diff --git a/home/roles/email/default.nix b/home/roles/email/default.nix new file mode 100644 index 0000000..234aac1 --- /dev/null +++ b/home/roles/email/default.nix @@ -0,0 +1,128 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.home.roles.email; +in +{ + options.home.roles.email = { + enable = mkEnableOption "Enable email with notmuch, mbsync, and msmtp"; + }; + + config = mkIf cfg.enable { + home.packages = with pkgs; [ + isync # provides mbsync for IMAP sync + msmtp # for SMTP sending + notmuch # email indexing and search + openssl # for certificate management + ]; + + # Ensure Mail directory exists + home.file."Mail/.keep".text = ""; + + # mbsync configuration + home.file.".mbsyncrc".text = '' + # IMAP Account Configuration + IMAPAccount proton + Host proton.johnogle.info + Port 143 + User john@ogle.fyi + PassCmd "${pkgs.rbw}/bin/rbw get proton.johnogle.info" + TLSType STARTTLS + AuthMechs PLAIN + + # Remote Storage + IMAPStore proton-remote + Account proton + + # Local Storage + MaildirStore proton-local + Path ~/Mail/ + Inbox ~/Mail/INBOX + SubFolders Verbatim + + # Channel Configuration - Sync All + Channel proton + Far :proton-remote: + Near :proton-local: + Patterns * + Create Both + Expunge Both + SyncState * + ''; + + # Notmuch configuration + home.file.".notmuch-config".text = '' + [database] + path=${config.home.homeDirectory}/Mail + + [user] + name=John Ogle + primary_email=john@ogle.fyi + + [new] + tags=unread;inbox; + ignore= + + [search] + exclude_tags=deleted;spam; + + [maildir] + synchronize_flags=true + ''; + + # msmtp configuration + home.file.".msmtprc".text = '' + # Default settings + defaults + auth plain + tls on + tls_starttls on + tls_trust_file /etc/ssl/certs/ca-certificates.crt + logfile ${config.home.homeDirectory}/.msmtp.log + + # Proton mail account + account proton + host proton.johnogle.info + port 25 + from john@ogle.fyi + user john@ogle.fyi + passwordeval rbw get proton.johnogle.info + + # Set default account + account default : proton + ''; + + # Systemd service for mail sync + systemd.user.services.mbsync = { + Unit = { + Description = "Mailbox synchronization service"; + After = [ "network-online.target" ]; + Wants = [ "network-online.target" ]; + }; + Service = { + Type = "oneshot"; + ExecStart = "${pkgs.bash}/bin/bash -c '${pkgs.isync}/bin/mbsync -a && ${pkgs.notmuch}/bin/notmuch new'"; + Environment = "PATH=${pkgs.rbw}/bin:${pkgs.coreutils}/bin"; + StandardOutput = "journal"; + StandardError = "journal"; + }; + }; + + # Systemd timer for automatic sync + systemd.user.timers.mbsync = { + Unit = { + Description = "Mailbox synchronization timer"; + }; + Timer = { + OnBootSec = "2min"; + OnUnitActiveSec = "5min"; + Unit = "mbsync.service"; + }; + Install = { + WantedBy = [ "timers.target" ]; + }; + }; + }; +}