aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-30 22:13:37 -0500
committerCraig Jennings <c@cjennings.net>2026-05-30 22:13:37 -0500
commitddcde66a768758844a5be705de6a89e68697fa1a (patch)
treec360f2ca7aef69d6e976e3b12470746b4a0a925f
parente446dab251fb0889c516c491e0d73a6ec9f0b873 (diff)
downloadrulesets-ddcde66a768758844a5be705de6a89e68697fa1a.tar.gz
rulesets-ddcde66a768758844a5be705de6a89e68697fa1a.zip
docs(protocols): surface cmail-action send as the default email path
An org-drill session asked to send a follow-up email first claimed it couldn't, then hand-built MIME through msmtp, because nothing told it cmail send exists. I added a "Sending Email" subsection to protocols.org (read every session): cmail (c@cjennings.net) is the default for personal mail, dmail for work, and cmail-action send is the tool, with one-liner examples for body-file, attachments, Cc/Bcc, and threaded replies. I also rewrote send-email.org Step 4, replacing the inline-Python heredoc that taught the hard way with the cmail-action send call.
-rw-r--r--.ai/protocols.org26
-rw-r--r--.ai/workflows/send-email.org50
-rw-r--r--claude-templates/.ai/protocols.org26
-rw-r--r--claude-templates/.ai/workflows/send-email.org50
4 files changed, 82 insertions, 70 deletions
diff --git a/.ai/protocols.org b/.ai/protocols.org
index d5290aa..1499fbb 100644
--- a/.ai/protocols.org
+++ b/.ai/protocols.org
@@ -261,6 +261,32 @@ for it on a specific document* — never sign for him on your own initiative. Th
=edit-pdf= workflow (project-level, where present) has the reportlab snippet for
stamping it.
+** Sending Email
+
+Craig has three mail accounts. *Default to cmail for personal / non-work email* — reach for it unless the message is work-related.
+
+| Account | Address | Use for |
+|---------+---------+---------|
+| =cmail= | =c@cjennings.net= (Proton Bridge) | *Default.* Personal / non-work mail. |
+| =dmail= | =craig.jennings@deepsat.com= (Gmail) | Work mail. |
+| =gmail= | =craigmartinjennings@gmail.com= | Third account, rarely the right one. |
+
+*The tool is =cmail-action send=* (symlinked into =~/.local/bin=, on PATH from any project). Don't hand-roll MIME or pipe raw messages through =msmtp= — the script builds the message, threading, and attachments for you.
+
+#+begin_src bash
+# simple
+cmail-action send --to addr@example.com --subject "Subject" --body "One-liner body."
+# body from a file (preferred for anything multi-line)
+cmail-action send --to addr@example.com --subject "Subject" --body-file /tmp/draft.txt
+# with attachments (repeatable --attach, MIME type auto-detected)
+cmail-action send --to addr@example.com --subject "Subj" --body-file /tmp/draft.txt --attach a.pdf --attach b.png
+# a threaded reply
+cmail-action send --to addr@example.com --subject "Re: ..." --body-file /tmp/draft.txt \
+ --cc someone@example.com --in-reply-to "<msgid>" --references "<msgid>"
+#+end_src
+
+=cmail-action= handles the receive/triage side too (=list-unread=, =read=, =mark-read=, =star=, =trash=). For the full guided flow (validate the recipient against =contacts.org=, confirm before sending, verify delivery), run the =send-email= workflow; for a known recipient, the one-liner above is enough.
+
** Task List Location
Craig's global task list is available at: =/home/cjennings/sync/org/roam/inbox.org=
diff --git a/.ai/workflows/send-email.org b/.ai/workflows/send-email.org
index cfd7adf..065f925 100644
--- a/.ai/workflows/send-email.org
+++ b/.ai/workflows/send-email.org
@@ -4,7 +4,7 @@
* Overview
-This workflow sends emails with optional attachments via msmtp using the cmail account (c@cjennings.net via Proton Bridge).
+This workflow sends emails with optional attachments via =cmail-action send= (the cmail account, c@cjennings.net via Proton Bridge).
* When to Use This Workflow
@@ -80,44 +80,24 @@ Send this email? [Y/n]
** Step 4: Send the Email
-Use Python to construct MIME message and pipe to msmtp:
-
-#+begin_src python
-python3 << 'EOF' | msmtp -a cmail [recipient]
-import sys
-from email.mime.multipart import MIMEMultipart
-from email.mime.text import MIMEText
-from email.mime.application import MIMEApplication
-from email.utils import formatdate
-import os
-
-msg = MIMEMultipart()
-msg['From'] = 'c@cjennings.net'
-msg['To'] = '[to_address]'
-# msg['Cc'] = '[cc_address]' # if applicable
-# msg['Bcc'] = '[bcc_address]' # if applicable
-msg['Subject'] = '[subject]'
-msg['Date'] = formatdate(localtime=True)
-
-body = """[body text]"""
-msg.attach(MIMEText(body, 'plain'))
-
-# For each attachment:
-# pdf_path = '/path/to/file.pdf'
-# with open(pdf_path, 'rb') as f:
-# attachment = MIMEApplication(f.read(), _subtype='pdf')
-# attachment.add_header('Content-Disposition', 'attachment', filename='filename.pdf')
-# msg.attach(attachment)
-
-print(msg.as_string())
-EOF
-#+end_src
+Send with =cmail-action send=. It builds the MIME message, threading, and attachments, and connects to Proton Bridge's local SMTP as c@cjennings.net. Don't hand-roll a heredoc or pipe through =msmtp=.
-**Important:** When there are CC or BCC recipients, pass ALL recipients to msmtp:
#+begin_src bash
-python3 << 'EOF' | msmtp -a cmail to@example.com cc@example.com bcc@example.com
+# simple
+cmail-action send --to addr@example.com --subject "Subject" --body "One-liner body."
+# multi-line body from a file (preferred for anything beyond one line)
+cmail-action send --to addr@example.com --subject "Subject" --body-file /tmp/draft.txt
+# attachments (repeatable --attach, MIME type auto-detected)
+cmail-action send --to addr@example.com --subject "Subj" --body-file /tmp/draft.txt \
+ --attach report.pdf --attach chart.png
+# Cc / Bcc (repeatable) and a threaded reply
+cmail-action send --to addr@example.com --subject "Re: ..." --body-file /tmp/draft.txt \
+ --cc colleague@example.com --bcc archive@example.com \
+ --in-reply-to "<original-msgid>" --references "<root-msgid> <original-msgid>"
#+end_src
+=--cc= / =--bcc= are repeatable; recipients are derived from the To/Cc/Bcc headers automatically, and Bcc is stripped from the sent message. For a reply that threads on the recipient's end, pass =--in-reply-to= (and =--references=) with the original message's Message-ID.
+
** Step 5: Verify Delivery
Check the msmtp log for confirmation:
diff --git a/claude-templates/.ai/protocols.org b/claude-templates/.ai/protocols.org
index d5290aa..1499fbb 100644
--- a/claude-templates/.ai/protocols.org
+++ b/claude-templates/.ai/protocols.org
@@ -261,6 +261,32 @@ for it on a specific document* — never sign for him on your own initiative. Th
=edit-pdf= workflow (project-level, where present) has the reportlab snippet for
stamping it.
+** Sending Email
+
+Craig has three mail accounts. *Default to cmail for personal / non-work email* — reach for it unless the message is work-related.
+
+| Account | Address | Use for |
+|---------+---------+---------|
+| =cmail= | =c@cjennings.net= (Proton Bridge) | *Default.* Personal / non-work mail. |
+| =dmail= | =craig.jennings@deepsat.com= (Gmail) | Work mail. |
+| =gmail= | =craigmartinjennings@gmail.com= | Third account, rarely the right one. |
+
+*The tool is =cmail-action send=* (symlinked into =~/.local/bin=, on PATH from any project). Don't hand-roll MIME or pipe raw messages through =msmtp= — the script builds the message, threading, and attachments for you.
+
+#+begin_src bash
+# simple
+cmail-action send --to addr@example.com --subject "Subject" --body "One-liner body."
+# body from a file (preferred for anything multi-line)
+cmail-action send --to addr@example.com --subject "Subject" --body-file /tmp/draft.txt
+# with attachments (repeatable --attach, MIME type auto-detected)
+cmail-action send --to addr@example.com --subject "Subj" --body-file /tmp/draft.txt --attach a.pdf --attach b.png
+# a threaded reply
+cmail-action send --to addr@example.com --subject "Re: ..." --body-file /tmp/draft.txt \
+ --cc someone@example.com --in-reply-to "<msgid>" --references "<msgid>"
+#+end_src
+
+=cmail-action= handles the receive/triage side too (=list-unread=, =read=, =mark-read=, =star=, =trash=). For the full guided flow (validate the recipient against =contacts.org=, confirm before sending, verify delivery), run the =send-email= workflow; for a known recipient, the one-liner above is enough.
+
** Task List Location
Craig's global task list is available at: =/home/cjennings/sync/org/roam/inbox.org=
diff --git a/claude-templates/.ai/workflows/send-email.org b/claude-templates/.ai/workflows/send-email.org
index cfd7adf..065f925 100644
--- a/claude-templates/.ai/workflows/send-email.org
+++ b/claude-templates/.ai/workflows/send-email.org
@@ -4,7 +4,7 @@
* Overview
-This workflow sends emails with optional attachments via msmtp using the cmail account (c@cjennings.net via Proton Bridge).
+This workflow sends emails with optional attachments via =cmail-action send= (the cmail account, c@cjennings.net via Proton Bridge).
* When to Use This Workflow
@@ -80,44 +80,24 @@ Send this email? [Y/n]
** Step 4: Send the Email
-Use Python to construct MIME message and pipe to msmtp:
-
-#+begin_src python
-python3 << 'EOF' | msmtp -a cmail [recipient]
-import sys
-from email.mime.multipart import MIMEMultipart
-from email.mime.text import MIMEText
-from email.mime.application import MIMEApplication
-from email.utils import formatdate
-import os
-
-msg = MIMEMultipart()
-msg['From'] = 'c@cjennings.net'
-msg['To'] = '[to_address]'
-# msg['Cc'] = '[cc_address]' # if applicable
-# msg['Bcc'] = '[bcc_address]' # if applicable
-msg['Subject'] = '[subject]'
-msg['Date'] = formatdate(localtime=True)
-
-body = """[body text]"""
-msg.attach(MIMEText(body, 'plain'))
-
-# For each attachment:
-# pdf_path = '/path/to/file.pdf'
-# with open(pdf_path, 'rb') as f:
-# attachment = MIMEApplication(f.read(), _subtype='pdf')
-# attachment.add_header('Content-Disposition', 'attachment', filename='filename.pdf')
-# msg.attach(attachment)
-
-print(msg.as_string())
-EOF
-#+end_src
+Send with =cmail-action send=. It builds the MIME message, threading, and attachments, and connects to Proton Bridge's local SMTP as c@cjennings.net. Don't hand-roll a heredoc or pipe through =msmtp=.
-**Important:** When there are CC or BCC recipients, pass ALL recipients to msmtp:
#+begin_src bash
-python3 << 'EOF' | msmtp -a cmail to@example.com cc@example.com bcc@example.com
+# simple
+cmail-action send --to addr@example.com --subject "Subject" --body "One-liner body."
+# multi-line body from a file (preferred for anything beyond one line)
+cmail-action send --to addr@example.com --subject "Subject" --body-file /tmp/draft.txt
+# attachments (repeatable --attach, MIME type auto-detected)
+cmail-action send --to addr@example.com --subject "Subj" --body-file /tmp/draft.txt \
+ --attach report.pdf --attach chart.png
+# Cc / Bcc (repeatable) and a threaded reply
+cmail-action send --to addr@example.com --subject "Re: ..." --body-file /tmp/draft.txt \
+ --cc colleague@example.com --bcc archive@example.com \
+ --in-reply-to "<original-msgid>" --references "<root-msgid> <original-msgid>"
#+end_src
+=--cc= / =--bcc= are repeatable; recipients are derived from the To/Cc/Bcc headers automatically, and Bcc is stripped from the sent message. For a reply that threads on the recipient's end, pass =--in-reply-to= (and =--references=) with the original message's Message-ID.
+
** Step 5: Verify Delivery
Check the msmtp log for confirmation: