diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-30 22:13:37 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-30 22:13:37 -0500 |
| commit | ddcde66a768758844a5be705de6a89e68697fa1a (patch) | |
| tree | c360f2ca7aef69d6e976e3b12470746b4a0a925f | |
| parent | e446dab251fb0889c516c491e0d73a6ec9f0b873 (diff) | |
| download | rulesets-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.org | 26 | ||||
| -rw-r--r-- | .ai/workflows/send-email.org | 50 | ||||
| -rw-r--r-- | claude-templates/.ai/protocols.org | 26 | ||||
| -rw-r--r-- | claude-templates/.ai/workflows/send-email.org | 50 |
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: |
