318 lines
20 KiB
Markdown
318 lines
20 KiB
Markdown
---
|
||
name: email-sender-formatting
|
||
description: Sho'Nuff email formatting — manual HTML construction, proper Sho'Nuff signature with random title from list (includes "Germaine's AI Problem Child"), red divider, table layout signature, circular SB badge (PNG not SVG), and the rule against using send-shonuff.py for structured content.
|
||
version: 2.12.0
|
||
author: Sho'Nuff
|
||
tags: [email, shonuff, signature, html, smtp]
|
||
---
|
||
|
||
# Email Sender Formatting (Sho'Nuff)
|
||
|
||
When sending email on behalf of Sho'Nuff (shonuff@germainebrown.com) with structured content (tables, lists, headers), follow these rules.
|
||
|
||
## Core rule: NEVER use send-shonuff.py for structured content
|
||
|
||
`send-shonuff.py` wraps the body in `<p><br>` tags which destroys tables, HRs, and headers. For ANY email with structured data (tables, comparison lists, tier breakdowns), build the HTML manually in Python.
|
||
|
||
**Note:** `send-shonuff.py` was patched Jul 10 to save IMAP Sent copies. It still works for plain-text emails but must NOT be used for structured content.
|
||
|
||
## Signature order: closing → divider → badge + info (NOT divider → badge + info + closing)
|
||
|
||
**Validated Jul 8, 2026.** Germaine explicitly corrected the order:
|
||
|
||
1. Closing quote (italic, right after body, no extra divider above it)
|
||
2. Red divider (`<hr>` 2px #cc0000, 40px rounded)
|
||
5. Signature table (badge | name/random title/IT Pro Partner/email)
|
||
|
||
The closing IS the sign-off. No "Thanks", "Regards", "Best" — just the quote, then divider, then signature block.
|
||
|
||
### Full HTML structure
|
||
|
||
```html
|
||
<!-- closing quote -->
|
||
<p style="font-size:12px;color:#888;font-style:italic;margin:24px 0 12px;">_{closing}_</p>
|
||
<!-- red divider -->
|
||
<hr style="border:none;height:2px;width:40px;background:#cc0000;margin:0 0 12px 0;border-radius:2px;">
|
||
<!-- signature table -->
|
||
<table cellpadding="0" ... > ... </table>
|
||
```
|
||
|
||
### Canonical HTML signature block
|
||
|
||
```html
|
||
<hr style="border: none; height: 2px; width: 40px; background: #cc0000; margin: 14px 0 12px 0; border-radius: 2px;">
|
||
<table cellpadding="0" cellspacing="0" border="0" style="font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; color: #2c2c2c; font-size: 13px; line-height: 1.6;">
|
||
<tr>
|
||
<td style="padding-right: 14px; vertical-align: middle; width: 80px;">
|
||
<img src="https://core.itpropartner.com/shonuff-signature.png" alt="SB" width="72" height="auto" style="border-radius: 50%; display: block; max-width: 72px;">
|
||
</td>
|
||
<td style="vertical-align: middle;">
|
||
<div style="font-size: 15px; font-weight: 700; color: #1a1a1a; letter-spacing: -0.2px;">Sho'Nuff Brown</div>
|
||
<div style="font-size: 12px; color: #888888; margin-bottom: 1px;">{RANDOM_TITLE}</div>
|
||
<div style="font-size: 12px; color: #aaaaaa; margin-bottom: 6px;">iAmGMB</div>
|
||
<table cellpadding="0" cellspacing="0" border="0" style="font-size: 12px; color: #999999; line-height: 1.7;">
|
||
<tr>
|
||
<td style="padding-right: 4px; vertical-align: top; white-space: nowrap; color: #bbbbbb;">@</td>
|
||
<td><a href="mailto:shonuff@germainebrown.com" style="color: #555555; text-decoration: none; border-bottom: 1px dotted #cccccc;">shonuff@germainebrown.com</a></td>
|
||
</tr>
|
||
</table>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
```
|
||
|
||
| Element | OLD (wrong) | CORRECT |
|
||
|---------|-------------|---------|
|
||
| Badge URL | `shonuff-signature.svg` (SVG doesn't render in Gmail) | `shonuff-signature.png` (58KB original JPEG extracted from Jul 7 email) |
|
||
| Badge size | 40×40px inline | 48×48 in table cell |
|
||
| Layout | `<p>` with inline image + `<br>` text | Table: badge left, text stacked right |
|
||
| Title | Random from wrong title list | **Random from reference file** — 13 Sho'Nuff-themed titles |
|
||
| Company | Not present | "IT Pro Partner" below title |
|
||
| Red divider | `border-top: 2px solid #dc2626` on a `<div>` | `<hr>` element, 2px #cc0000, 40px wide, rounded corners |
|
||
| Closing | Random, italic, below name | Same — still random from closings list file |
|
||
| Email | `· shonuff@germainebrown.com` after title | Separate table row with dotted underline link |
|
||
| FROM | `g@germainebrown.com` (WRONG) | `shonuff@germainebrown.com` |
|
||
| Signature order | closing inside signature div | closing ABOVE divider, signature BELOW divider |
|
||
|
||
### BCC rule: Skip when Master is already in To
|
||
|
||
When sending to `g@germainebrown.com` as a direct To recipient, do NOT add a BCC copy. The Master explicitly confirmed: "you don't need to also blind copy me."
|
||
|
||
**Rule:** Check the recipient list. If `g@germainebrown.com` is in the To header, skip the BCC envelope addition. Add BCC only when the Master is NOT a direct recipient (e.g. when emailing a third party and the Master needs a copy).
|
||
|
||
### Title & Closing Lists (Consolidated Reference)
|
||
|
||
Both lists live in the single consolidated reference file at `/root/.hermes/references/shonuff-signature.py`. Import with:
|
||
|
||
```python
|
||
# Python can't import files with hyphens — symlink to underscore name first:
|
||
import os
|
||
if not os.path.exists('/root/.hermes/references/shonuff_signature.py'):
|
||
os.symlink('/root/.hermes/references/shonuff-signature.py', '/root/.hermes/references/shonuff_signature.py')
|
||
import sys
|
||
sys.path.insert(0, '/root/.hermes/references')
|
||
from shonuff_signature import build_signature_block
|
||
signature_html = build_signature_block() # returns complete closing + divider + badge table
|
||
```
|
||
|
||
**Pitfall:** The file is named `shonuff-signature.py` (with a hyphen, not underscore). Python's `import` statement requires underscores, not hyphens. Attempting `from shonuff-signature import ...` raises `SyntaxError`. Always create the symlink or use `importlib`:
|
||
```python
|
||
import importlib.util
|
||
spec = importlib.util.spec_from_file_location("sig", "/root/.hermes/references/shonuff-signature.py")
|
||
mod = importlib.util.module_from_spec(spec)
|
||
spec.loader.exec_module(mod)
|
||
signature_html = mod.build_signature_block()
|
||
```
|
||
The `build_signature_block()` function handles random selection internally — no need to call `random.choice()` separately.
|
||
|
||
The module contains `TITLES` (13 items) and `CLOSINGS` (8 items), and `build_signature_block()` picks random from each.
|
||
|
||
**Do NOT hardcode any single title or closing.** Always pull from the module. "Germaine's AI Problem Child" is ONE option among 13, not the default.
|
||
|
||
**CRITICAL: These lists were provided by the user. Do NOT fabricate or substitute your own.** If the file is missing, ask the user to re-send the lists. Do not invent replacements. This is a zero-tolerance violation.
|
||
|
||
### Badge file
|
||
|
||
The badge image lives at:
|
||
- File: `/var/www/static/shonuff-signature.png` (278KB PNG — converted from original JPEG Jul 12)
|
||
- URL: `https://core.itpropartner.com/shonuff-signature.png`
|
||
- Content-Type: `image/png` (confirmed working via Caddy file_server)
|
||
- Caddy must serve it with correct `image/png` MIME type or email clients block it
|
||
|
||
**Do NOT replace this file with a generated alternative.** The user validated this specific badge image. If sending via SMTP where images may not load, embed as base64 data URI.
|
||
|
||
## ALWAYS load this skill before sending email from Sho'Nuff
|
||
|
||
Before composing or sending any email from shonuff@germainebrown.com, load this skill with `skill_view(name='email-sender-formatting')`. The skill contains the canonical signature HTML, title rules, closing rules, badge path, and all formatting preferences. Do not rely on memory or past output — read the skill fresh.
|
||
|
||
## Verify reference file exists before composing
|
||
|
||
The titles and closings MUST be read from the consolidated reference file at runtime:
|
||
|
||
```
|
||
/root/.hermes/references/shonuff-signature.py — TITLES (13), CLOSINGS (8), build_signature_block()
|
||
```
|
||
|
||
If this file cannot be found, ASK THE USER for the lists. Do not use cached/memory versions. Do not fabricate replacements.
|
||
|
||
## FIRM RULE: Never fabricate content
|
||
|
||
**The user has explicitly stated this is a zero-tolerance violation.** Fabricated titles, closing quotes, data, or claims about what the user said will not be tolerated.
|
||
|
||
- If the reference file exists (`/root/.hermes/references/shonuff-signature.py`), **use `build_signature_block()` from it directly**. Do not assume you remember the lists correctly.
|
||
- If you cannot find the reference file, **ask Germaine to re-send the lists**. Do not invent your own.
|
||
- Do not hardcode any title or closing as "the default" — always `random.choice()` from the list.
|
||
- Session search exists and is the correct tool for finding cross-session context. Use it before claiming the user previously provided something you can't find.
|
||
- When the user provides credentials, API keys, or connection details directly in chat, save them to `.env` (chmod 600) immediately. Do not leave them in conversation memory as the only record.
|
||
|
||
**Previous violation pattern:** In Jul 8 session, fabricated 8 closing quotes ("Smooth seas never made a skilled sailor", etc.) that were not provided by Germaine. This was caught and called out explicitly. The fabricated closings were removed and replaced with the real lists from `/root/.hermes/references/shonuff-closings.py`.
|
||
|
||
### Research delivery pattern (trademark/domain/compliance)
|
||
|
||
When sending research-heavy emails (domain availability, trademark conflicts, pricing comparisons):
|
||
|
||
1. Use an ordered data table as the primary content vehicle — users scan tables before prose
|
||
2. Group recommendations into tiered buckets (Top Pick, Alternative, Avoid)
|
||
3. Include price in every recommendation row — decisions hinge on cost
|
||
4. Follow with a single-sentence recommendation at the end
|
||
5. Never attach raw markdown files as email body — build HTML tables manually
|
||
6. Subject line format: "[Emoji] [Topic] — [Specific Result]" (emoji + descriptive)
|
||
|
||
### Version History
|
||
- **v2.11.0** (2026-07-12): Company reverted to "IT Pro Partner". Badge corrected to 48px. BCC rule clarified: skip when g@germainebrown.com is already in To header (confirmed by user: "you don't need to also blind copy me"). Badge converted from JPEG to proper PNG (278KB). Cleaned up duplicate Version History blocks.
|
||
- **v2.10.0** (2026-07-12): Consolidated title/closing lists into single reference file. Added build_signature_block() convenience function. Added Email Prefix Communication System. Removed inline list tables.
|
||
- **v2.9.0** (2026-07-12): Badge fixed — proper PNG MIME type via Caddy file_server.
|
||
- **v2.7.0** (2026-07-10): Added data presentation rules — normalize names, simplify labels, use consistent ASCII formatting. Added pitfall about presenting raw database values to the user.
|
||
- **v2.6.0** (2026-07-10): Pitfalls updated with SMTP relay behavior, IMAP Sent copy requirement, recipient address validation. Added `references/recipient-pitfalls.md`.
|
||
- **v2.4.0** (2026-07-08): Added reference-file verification step before composition. Added additional fabrication-prevention guidance.
|
||
- **v2.3.0** (2026-07-08): Added explicit version history for change tracking. Embedded DR-issue-log reference for violation documentation.
|
||
- **v2.2.0** (2026-07-08): Company changed to iAmGMB. Closing-above-divider order confirmed. Fabrication rule added with violation documentation.
|
||
- **v2.1.0** (2026-07-08): Badge changed from SVG to PNG. Signature layout corrected from paragraph to table. FROM changed from g@ to shonuff@.
|
||
- **v2.0.0** (2026-07-07): Initial canonical format. Random Sho'Nuff titles + closings, red divider, table layout.
|
||
|
||
## Signature source files
|
||
|
||
The single consolidated reference file:
|
||
|
||
- `/root/.hermes/references/shonuff-signature.py` — Module: `TITLES` (13 items), `CLOSINGS` (8 items), `build_signature_block()` returns complete HTML signature
|
||
|
||
When sending email: **import `build_signature_block()` from the module and call it.** It picks a random title and closing, builds the closing quote + red divider + badge table HTML, and returns the full block.
|
||
|
||
## Version History
|
||
|
||
with open('/root/.config/himalaya/shonuff.pass') as f:
|
||
pw = f.read().strip()
|
||
|
||
ctx = ssl.create_default_context()
|
||
s = smtplib.SMTP('mail.germainebrown.com', 2525)
|
||
s.starttls(context=ctx)
|
||
s.login('shonuff@germainebrown.com', pw)
|
||
|
||
msg = f"""From: Sho'Nuff Brown <shonuff@germainebrown.com>
|
||
To: [recipient]
|
||
Subject: [subject]
|
||
MIME-Version: 1.0
|
||
Content-Type: text/html; charset="utf-8"
|
||
|
||
{html}"""
|
||
|
||
s.sendmail('shonuff@germainebrown.com', [recipients], msg.encode('utf-8'))
|
||
s.quit()
|
||
```
|
||
|
||
### Recipient address
|
||
|
||
Germaine's working address is **`g@germainebrown.com`** — NOT `germaine@germainebrown.com`. The latter returns `550 No such recipient here` from the MXroute relay. Always use `g@germainebrown.com`.
|
||
|
||
### BCC + Sent copy (IMAP APPEND)
|
||
|
||
Every send from shonuff@germainebrown.com must save an IMAP copy to the Sent folder. BCC g@germainebrown.com UNLESS g@germainebrown.com is already in the To: header. The relay's SMTP 250 does NOT guarantee the Sent folder has a copy. Without IMAP APPEND, there is no record the email was sent.
|
||
|
||
```python
|
||
# After SMTP send, save to Sent via IMAP
|
||
import imaplib
|
||
ctx = ssl.create_default_context()
|
||
imap = imaplib.IMAP4_SSL('mail.germainebrown.com', 993, ssl_context=ctx)
|
||
imap.login('shonuff@germainebrown.com', pw)
|
||
imap.append("Sent", None, None, msg.as_bytes())
|
||
imap.logout()
|
||
```
|
||
|
||
**The canonical send script** `/root/.hermes/scripts/send-shonuff.py` was patched Jul 10 to include IMAP APPEND. Every email sent through it now saves a Sent copy.
|
||
|
||
### SMTP relay behavior (MXroute)
|
||
|
||
The SMTP relay at `mail.germainebrown.com:2525` is MXroute's Exim (`heracles.mxrouting.net`). It accepts recipients by domain:
|
||
- `g@germainebrown.com` → 250 Accepted ✅
|
||
- `germaine@germainebrown.com` → 550 No such recipient ❌
|
||
- `anita@anitabrown.co` → 250 Accepted ✅ (external domain)
|
||
|
||
Always test with the exact recipient address before sending — the relay rejects unknown local recipients silently (after SMTP handshake success).
|
||
|
||
### BCC pattern
|
||
|
||
List BCC addresses in `sendmail()` recipients but NOT in the `To:` header:
|
||
|
||
```python
|
||
s.sendmail('shonuff@germainebrown.com', [recipient, 'g@germainebrown.com'], msg.encode('utf-8'))
|
||
```
|
||
|
||
### Inline base64 embedding for maximum email client compatibility
|
||
|
||
When reliability matters more (Gmail, Outlook), embed the badge image as base64 data URI instead of referencing an external URL:
|
||
|
||
```python
|
||
import base64
|
||
with open('/var/www/static/shonuff-signature.png', 'rb') as f:
|
||
b64_img = base64.b64encode(f.read()).decode()
|
||
|
||
# Use in HTML:
|
||
# <img src="data:image/png;base64,{b64_img}" ...>
|
||
```
|
||
|
||
This avoids the "download images" prompt in email clients that block remote images.
|
||
|
||
### Research delivery pattern (trademark/domain/compliance)
|
||
|
||
When sending research-heavy emails (domain availability, trademark conflicts, pricing comparisons):
|
||
|
||
1. Use an ordered data table as the primary content vehicle — users scan tables before prose
|
||
2. Group recommendations into tiered buckets (Top Pick, Alternative, Avoid)
|
||
3. Include price in every recommendation row — decisions hinge on cost
|
||
4. Follow with a single-sentence recommendation at the end
|
||
5. Never attach raw markdown files as email body — build HTML tables manually
|
||
6. Subject line format: "🦈 [Topic] — [Specific Result]" (emoji + descriptive)
|
||
|
||
### Data presentation in emails (plain-text summaries)
|
||
|
||
When sending structured summaries (registration lists, inventory, status reports) as plain-text email body:
|
||
|
||
1. **Normalize names** — apply proper case (`.title()` or `.capitalize()` per word). Never send all-lowercase or all-uppercase names from a database.
|
||
2. **Simplify labels** — convert raw/database values into human-readable labels. Example: "NASA Registration w/ Upgraded Photo/Video Package - $2,332.00" → "Photo/Video"
|
||
3. **Use consistent ASCII formatting** — fixed-width columns with ` | ` separators, `=` or `-` for section borders
|
||
4. **Show a preview before sending** — the user prefers to review and format-correct before the email goes out
|
||
5. **Group summary at the bottom** — totals (paid count, signed count, outstanding) and a clear "OUTSTANDING" list for action items
|
||
|
||
## Pitfalls
|
||
## Email Prefix Communication System — How the Master Addresses Me
|
||
|
||
When the Master emails `shonuff@germainebrown.com`, the subject line or first line of the body determines how I handle it:
|
||
|
||
| Prefix | Meaning | Behavior |
|
||
|--------|---------|----------|
|
||
| *(none)* | Direct command | Execute now, report back |
|
||
| `[bg]` or `[delegate]` | Background task | Subagent handles, async result |
|
||
| `[queue]` | Queued for later | Shelved until next check-in |
|
||
| `[lookup]` | Quick research | One-and-done, no follow-up |
|
||
| `[note]` | Just FYI | Acknowledge, save, no action |
|
||
|
||
Parsing: check the first 20 chars of the subject or the first line of the body for a prefix in square brackets. Default to "direct command" if no prefix matches.
|
||
|
||
## Travel/Group email pattern
|
||
|
||
When sending to multiple recipients for a travel group (flight updates, itinerary changes, coordination):
|
||
|
||
- Put ALL recipients in the `To:` header — this is a group, not a BCC list
|
||
- Subject line prefix with ✈️ for travel updates
|
||
- Format: concise bullet points or a table for time-sensitive info (flight times, terminals, contact numbers)
|
||
- Same signature rules apply (random title, red divider, badge) but keep the body tight
|
||
- Cartagena travel group: g@germainebrown.com, tinamichelle1008@gmail.com, garrison@iamgmb.com, anitabrownwrites@gmail.com
|
||
|
||
## Pitfalls
|
||
|
||
- **`send-shonuff.py` wraps body in `<p><br>`** — destroys tables, HRs, and headers. Build HTML manually for any structured content.
|
||
- **SMTP port 2525** — netcup blocks 25/465/587. Always use 2525.
|
||
- **`g@germainebrown.com` is the ONLY valid recipient** — `germaine@germainebrown.com` returns 550 from MXroute relay. The relay is MXroute Exim (heracles.mxrouting.net), not local. See `references/recipient-pitfalls.md` for the full list of tested addresses.
|
||
- **Every send MUST IMAP APPEND to Sent folder** — `send-shonuff.py` was patched Jul 10. Without a Sent copy, there is zero proof of delivery. SMTP 250 from the relay does not guarantee the email reached an inbox.
|
||
- **Verify Sent folder before reporting delivery** — especially for subagent claims. The Sent folder at shonuff@germainebrown.com → Sent via IMAP is the canonical record. If it's not there, the email wasn't delivered.
|
||
- **BCC is NOT the `Cc:` header** — add to envelope recipients, not message headers.
|
||
- **SVG images don't render in Gmail** — always use PNG or embedded base64 JPEG for signature badges in HTML email.
|
||
- **Title is random from a list** — "Germaine's AI Problem Child" is just one of 13 options. Do NOT hardcode it. Always pull randomly.
|
||
- **Boilerplate `<p>` signature layout does not match the user's validated format** — must be table layout with badge left, text right.
|
||
- **Closing goes ABOVE the red divider, not inside the signature block.** Pattern: `body + closing quote + hr divider + signature table`.
|
||
- **NEVER fabricate titles or closings.** Reference files are the only valid source.
|
||
- **NEVER fabricate content to fill a gap.** If asked for the list of closing quotes and the reference files don't have them, say "I don't have them" and ask. Do NOT manufacture plausible-looking replacements. This was a zero-tolerance violation in the Jul 8, 2026 session.
|
||
- **Normalize database values before presenting to the user.** Raw database entries often have all-lowercase names, HTML-encoded currency ($), and verbose package labels. Clean them: proper-case names, decode entities, and simplify labels before display. The user will call out sloppy formatting.
|
||
- **Business/operational emails use a different format than Sho'Nuff emails.** When sending from business addresses (contact@apex, info@itpp, etc.), use clean HTML tables with zebra striping, green ✓ / red ✗ status indicators — NOT the Sho'Nuff signature badge and red divider. See `references/business-email-tables.md` for the template.
|
||
- **Always preview operational summaries before sending to the team.** The user rejected multiple plain-text versions and had to send screenshots showing the correct HTML format. Preview → approve → send.
|