[mail] Fix how notmuch and mbsync work

This commit is contained in:
2026-08-05 00:05:24 -04:00
parent a956955300
commit b4935c82d7
12 changed files with 160 additions and 136 deletions

View File

@ -7,9 +7,10 @@ if [ $(pidof $AFEW_SERVICE) ] || [ $(pidof $MBSYNC_SERVICE) ] || [ $(pidof $NOTM
echo "Checkmail is already running."
else
echo "Checking for new mail"
afew -m -n
mbsync -a
mkdir -p ~/Mail/colin@unbl.ink/Junk/{cur,new,tmp}
mbsync unblink
notmuch new
afew -t -n
afew -m -n
fi
exit 0

View File

@ -1,19 +1,91 @@
#!/usr/bin/env python3
import http.client
import json
import subprocess
import sys
import time
new_mail_list = json.loads(
subprocess.check_output(
["notmuch", "show", "--format=json", "tag:inbox"],
).decode('utf-8')
)
NTFY_HOST = "ntfy.unbl.ink"
NTFY_PATH = "/207-comms"
MAILBOX_URL = "https://box.unbl.ink/mail/?_task=mail&_mbox=INBOX"
MAX_BODY = 3000
SEND_DELAY = 1.5
if new_mail_list:
output = "Mail's here!\n\n"
for message in new_mail_list:
msg = message[0][0]
dt = msg['headers']['Date']
subj = msg['headers']['Subject']
output += f"{dt}\n{subj}\n\n"
def extract_text(body_parts):
plain = []
html = []
subprocess.run(["dunstify", output])
def walk(parts):
for part in parts:
content_type = part.get('content-type', '')
content = part.get('content')
if isinstance(content, list):
walk(content)
elif content:
if 'text/plain' in content_type:
plain.append(content)
elif 'text/html' in content_type:
html.append(content)
walk(body_parts)
return '\n'.join(plain) if plain else '\n'.join(html)
def send_ntfy(headers, payload):
data = payload.encode('utf-8')
for attempt in range(3):
conn = http.client.HTTPSConnection(NTFY_HOST, timeout=15)
try:
conn.putrequest("POST", NTFY_PATH, skip_host=True)
conn.putheader(b"Host", NTFY_HOST.encode('utf-8'))
for name, value in headers.items():
conn.putheader(name.encode('utf-8'), value.encode('utf-8'))
conn.putheader("Content-Type", b"text/plain; charset=utf-8")
conn.putheader("Content-Length", str(len(data)))
conn.endheaders(data)
resp = conn.getresponse()
resp.read()
if resp.status == 429:
retry = resp.getheader('Retry-After', '5') or '5'
time.sleep(float(retry))
continue
if resp.status < 200 or resp.status >= 300:
print(f"ntfy failed: {resp.status}", file=sys.stderr)
return
except OSError as e:
print(f"ntfy error: {e}", file=sys.stderr)
time.sleep(attempt + 1)
finally:
conn.close()
def main():
new_mail = json.loads(
subprocess.check_output(
["notmuch", "show", "--format=json", "tag:new"],
).decode('utf-8')
)
for thread in new_mail:
for message_pair in thread:
headers = message_pair[0]['headers']
subject = headers.get('Subject', '')
sender = headers.get('From', '')
date = headers.get('Date', '')
body = extract_text(message_pair[0].get('body', []))[:MAX_BODY]
payload = f"{sender}\n\n{body}\n\n{date}"
send_ntfy(
{
"Title": subject,
"Tags": "envelope",
"Click": MAILBOX_URL,
},
payload,
)
time.sleep(SEND_DELAY)
if __name__ == "__main__":
main()

View File

@ -170,6 +170,9 @@ UTILS_LINUX=(gnuplot graphviz shfmt shellcheck pandoc)
DESKTOP_LINUX=(kitty alacritty dino syncthing)
# Mail stack (notmuch search, isync sync, afew tagging, msmtp send)
MAIL_LINUX=(notmuch isync afew msmtp)
FEDORA_EXTRAS=(
gnome-extensions-app
gnome-tweaks
@ -210,6 +213,9 @@ MAC_BREW_PKGS=(
syncthing
pinentry-mac
emacs
notmuch
isync
msmtp
)
MAC_CASKS=(
@ -246,6 +252,7 @@ fedora)
dnf_install_best_effort "${DEV_TOOLS_LINUX[@]}"
dnf_install_best_effort "${UTILS_LINUX[@]}"
dnf_install_best_effort "${DESKTOP_LINUX[@]}"
dnf_install_best_effort "${MAIL_LINUX[@]}"
dnf_install_best_effort "${FEDORA_EXTRAS[@]}"
ensure_flathub
@ -268,6 +275,7 @@ arch)
pacman_install_best_effort "${DEV_TOOLS_LINUX[@]}"
pacman_install_best_effort "${UTILS_LINUX[@]}"
pacman_install_best_effort "${DESKTOP_LINUX[@]}"
pacman_install_best_effort "${MAIL_LINUX[@]}"
pacman_install_best_effort "${ARCH_EXTRAS[@]}"
aur_install_if_possible google-chrome slack-desktop || true
@ -288,6 +296,11 @@ macos)
brew_install "${MAC_BREW_PKGS[@]}"
brew_cask "${MAC_CASKS[@]}" || true
if ! have afew && have pipx; then
log "Installing afew via pipx..."
pipx install afew || true
fi
if [[ -f "$(brew --prefix)/opt/fzf/install" ]]; then
log "Tip: run fzf install helper if you want keybindings/completion:"
echo " $(brew --prefix)/opt/fzf/install"
@ -319,6 +332,7 @@ freebsd)
# Optional stuff from your history where it makes sense
pkg_install_best_effort "${FREEBSD_MISC[@]}"
pkg_install_best_effort "notmuch isync msmtp"
log "Final system upgrade..."
sudo pkg upgrade -y