Files
nixos-configs/home/roles/email/default.nix
John Ogle 7898def044 Fix notmuch inbox tag to match IMAP INBOX folder
Previously, the notmuch config applied the "inbox" tag to all new
messages regardless of which IMAP folder they were in. This caused
tag:inbox to return all 22k+ messages instead of just those in INBOX.

Changes:
- Use temporary "new" tag instead of "inbox" for newly indexed messages
- Add post-new hook that applies tags based on maildir folder location
- inbox tag now only applies to messages in INBOX folder
- Also adds sent, draft, spam, deleted, and archive tags based on folder
2026-01-04 12:23:39 -08:00

161 lines
4.3 KiB
Nix

{ 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;new;
ignore=
[search]
exclude_tags=deleted;spam;
[maildir]
synchronize_flags=true
'';
# Notmuch post-new hook for folder-based tagging
home.file."Mail/.notmuch/hooks/post-new" = {
executable = true;
text = ''
#!${pkgs.bash}/bin/bash
# Tag messages based on their maildir folder location
# This runs after 'notmuch new' indexes new messages
# Process only messages with the 'new' tag (just indexed)
# Add inbox tag only for messages in INBOX folder
${pkgs.notmuch}/bin/notmuch tag +inbox -- tag:new AND folder:INBOX
# Add sent tag for messages in Sent folder
${pkgs.notmuch}/bin/notmuch tag +sent -inbox -- tag:new AND folder:Sent
# Add draft tag for messages in Drafts folder
${pkgs.notmuch}/bin/notmuch tag +draft -inbox -- tag:new AND folder:Drafts
# Add spam tag for messages in Spam folder
${pkgs.notmuch}/bin/notmuch tag +spam -inbox -unread -- tag:new AND folder:Spam
# Add deleted tag for messages in Trash folder
${pkgs.notmuch}/bin/notmuch tag +deleted -inbox -unread -- tag:new AND folder:Trash
# Add archive tag for messages in Archive folder
${pkgs.notmuch}/bin/notmuch tag +archive -inbox -- tag:new AND folder:Archive
# Remove the temporary 'new' tag from all messages
${pkgs.notmuch}/bin/notmuch tag -new -- tag:new
'';
};
# 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" ];
};
};
};
}