Files
beantownbabeandClaude Sonnet 5 95abe3b167 Add a From-address dropdown to the mail-merge tool
Replaces the free-text From field with a select of real working addresses
(mblack@txproducts.de, now the default; mckinley@mckinleyblack.com kept for
internal test sends), deduplicating the 8 render_template("index.html", ...)
call sites into a single render_index() helper along the way. Also picks up
today's real outreach-log entry from testing the reconnect_message send to
Peter's actual address.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-17 15:16:47 +02:00
..

Conference Contact Mail Merge

Personalizes and drafts follow-up emails for people met at conferences, pulling fields from an Excel sheet. No CRM yet, so this is plain Excel + Python -- conference_contacts.xlsx can be uploaded to Nextcloud once it's filled in, for anyone else to see/update (there's no live desktop sync set up, so that's a manual upload-after-editing step, not automatic).

Files

  • conference_contacts.xlsx -- one row per contact. Columns: First Name, Last Name, Email, Company, Role, Conference, Date Met, Notes, Materials Sent, Date Sent. Add as many rows as you like. A "Draft File" column gets added/filled in automatically after each run (draft mode only, not --send) -- click the link in that cell to jump straight to that contact's .eml. Note: each run rewrites the whole sheet to fill this in, which resets any manual formatting (column widths, colors, etc.) you've added in Excel.
  • email_template.txt -- the email text. First line must start with SUBJECT:. Any {{Column Name}} in the subject or body gets replaced with that contact's value from the matching Excel column.
  • mail_merge.py -- fills the template per row. No signature is built or embedded -- whatever signature your mail app (or the mail server) adds is separate from this, and won't apply to the --send path (see below).

Usage

  1. Fill in conference_contacts.xlsx with real contacts (keep the column headers as they are, since the template matches on those names).

  2. Edit email_template.txt if you want to change the wording. Add new {{Column Name}} placeholders as long as a matching column exists.

  3. Run it from Terminal, in this folder:

    python3 mail_merge.py --attach ~/Documents/TXproducts_Materials/txservices.pdf ~/Documents/TXproducts_Materials/wavegate.pdf
    

    This writes one .eml file per contact into output_drafts/. Double-click a .eml to open it as a draft in Mail.app/Outlook/whatever your default mail app is -- read it over, make any last personal tweak, and hit send yourself. Nothing is sent automatically with this mode.

  4. Once you've actually sent one, mark it in the Excel sheet ("Materials Sent" = Yes, fill in "Date Sent") so a re-run skips it.

Useful flags

  • --attach file1.pdf file2.pdf -- attach one or more files (space-separated).
  • --from-address someone@example.com -- sets the "From" on the .eml draft, so Mail.app picks the right account if you have more than one configured. Defaults to mblack@txproducts.de.
  • --only email1@x.com email2@y.com -- only generate drafts for these specific addresses, skipping everyone else currently in the sheet. Leave this off to process every row that isn't marked "Materials Sent: Yes".

Optional: direct sending via SMTP

If you'd rather send straight from the script instead of via .eml drafts, set these environment variables and run with --send. Port matters: use 465 for implicit SSL, 587 for STARTTLS -- the script picks the right handshake automatically based on which port you give it.

export SMTP_HOST=...
export SMTP_PORT=587
export SMTP_USER=you@example.com
export SMTP_PASS=...
python3 mail_merge.py --send

It shows you a preview of each email and asks [y/N] before sending it -- nothing goes out without a per-email confirmation. --send uses SMTP_USER as the From address, ignoring --from-address.

Note on contacting these people

These are people you met and spoke with in person at a conference, which is a different situation from the boss's cold Phase 1 target list (LinkedIn-only, personal note required, see the Address Book README) -- an in-person introduction is a much stronger legitimate-interest basis for a follow-up email. Still worth keeping things genuinely personal per contact rather than sending an identical form letter to everyone.