From cad8146f1bfe6224ad476f33e3087b2e2074c717 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sat, 31 Jan 2026 16:23:00 -0600 Subject: docs: add new workflows and AMD GPU workaround - Add email workflow (msmtp direct sending) - Add assemble-email workflow (document gathering for manual send) - Add retrospective workflow - Add AMD GPU suspend workaround notes --- docs/workflows/email.org | 198 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 docs/workflows/email.org (limited to 'docs/workflows/email.org') diff --git a/docs/workflows/email.org b/docs/workflows/email.org new file mode 100644 index 0000000..cfd7adf --- /dev/null +++ b/docs/workflows/email.org @@ -0,0 +1,198 @@ +#+TITLE: Email Workflow +#+AUTHOR: Craig Jennings & Claude +#+DATE: 2026-01-26 + +* Overview + +This workflow sends emails with optional attachments via msmtp using the cmail account (c@cjennings.net via Proton Bridge). + +* When to Use This Workflow + +When Craig says: +- "email workflow" or "send an email" +- "email [person] about [topic]" +- "send [file] to [person]" + +* Required Information + +Before sending, gather and confirm: + +1. **To:** (required) - recipient email address(es) +2. **CC:** (optional) - carbon copy recipients +3. **BCC:** (optional) - blind carbon copy recipients +4. **Subject:** (required) - email subject line +5. **Body:** (required) - email body text +6. **Attachments:** (optional) - file path(s) to attach + +* The Workflow + +** Step 1: Gather Missing Information + +If any required fields are missing, prompt Craig: + +#+begin_example +To send this email, I need: +- To: [who should receive this?] +- Subject: [what's the subject line?] +- Body: [what should the email say?] +- Attachments: [any files to attach?] +- CC/BCC: [anyone to copy?] +#+end_example + +** Step 2: Validate Email Addresses + +Look up all recipient names/emails in the contacts file: + +#+begin_src bash +grep -i "[name or email]" ~/sync/org/contacts.org +#+end_src + +**Note:** If contacts.org is empty, check for sync-conflict files: +#+begin_src bash +ls ~/sync/org/contacts*.org +#+end_src + +For each recipient: +1. Search contacts by name or email +2. Confirm the email address matches +3. If name not found, ask Craig to confirm the email is correct +4. If multiple emails for a contact, ask which one to use + +** Step 3: Confirm Before Sending + +Display the complete email for review: + +#+begin_example +Ready to send: + +From: c@cjennings.net +To: [validated email(s)] +CC: [if any] +BCC: [if any] +Subject: [subject] + +[body text] + +Attachments: [list files if any] + +Send this email? [Y/n] +#+end_example + +** 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 + +**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 +#+end_src + +** Step 5: Verify Delivery + +Check the msmtp log for confirmation: + +#+begin_src bash +tail -3 ~/.msmtp.cmail.log +#+end_src + +Look for: ~smtpstatus=250~ and ~exitcode=EX_OK~ + +** Step 6: Sync to Sent Folder (Optional) + +If Craig wants the email in his Sent folder: + +#+begin_src bash +mbsync cmail +#+end_src + +* msmtp Configuration + +The cmail account should be configured in ~/.msmtprc: + +#+begin_example +account cmail +tls_certcheck off +auth on +host 127.0.0.1 +port 1025 +protocol smtp +from c@cjennings.net +user c@cjennings.net +passwordeval "cat ~/.config/.cmailpass" +tls on +tls_starttls on +logfile ~/.msmtp.cmail.log +#+end_example + +**Note:** ~tls_certcheck off~ is used because Proton Bridge uses self-signed certificates on localhost. + +* Attachment Handling + +** Supported Types + +Common MIME subtypes: +- PDF: ~_subtype='pdf'~ +- Images: ~_subtype='png'~, ~_subtype='jpeg'~ +- Text: ~_subtype='plain'~ +- Generic: ~_subtype='octet-stream'~ + +** Multiple Attachments + +Add multiple attachment blocks before ~print(msg.as_string())~ + +* Troubleshooting + +** Password File Missing +Ensure ~/.config/.cmailpass exists with the Proton Bridge SMTP password. + +** TLS Certificate Errors +Use ~tls_certcheck off~ in msmtprc for Proton Bridge (localhost only). + +** Proton Bridge Not Running +Start Proton Bridge before sending. Check if port 1025 is listening: +#+begin_src bash +ss -tlnp | grep 1025 +#+end_src + +* Example Usage + +Craig: "email workflow - send the November 3rd SOV to Christine" + +Claude: +1. Searches contacts for "Christine" -> finds cciarmello@gmail.com +2. Asks for subject and body if not provided +3. Locates the SOV file in assets/ +4. Shows confirmation +5. Sends via msmtp +6. Verifies delivery in log -- cgit v1.2.3