inbox / make_examples.py
cetusian's picture
Deploy inbox
36b48a2 verified
Raw History Blame Contribute Delete
7.52 kB
"""Render the sample emails for What the Inbox Sees: python make_examples.py (needs Playwright and qrcode).
Every brand, person, domain and phone number here is invented. Each email is drawn inside a plain mail
client frame, the way the person reading it sees it.
"""
import base64
import io
import json
from pathlib import Path
import qrcode
HERE = Path(__file__).parent
OUT = HERE / "examples"
COMPANY = "brightwell.co.uk"
def qr(url):
buf = io.BytesIO()
qrcode.make(url, box_size=6, border=2).save(buf, "PNG")
return "data:image/png;base64," + base64.b64encode(buf.getvalue()).decode()
def picture(inner, width=560):
"""An email body that is one picture: text drawn inside an image, nothing a text filter can read."""
return f"<div style='width:{width}px;border:1px solid #ddd;border-radius:6px;overflow:hidden'>{inner}</div>"
EMAILS = {
"mfa-qr": {
"label": "MFA reset with a QR code", "sender": "it-helpdesk@brightwell-security.help",
"name": "Brightwell IT Service Desk", "subject": "Action required: re-register your MFA by 17:00 today",
"body": picture(f"""<div style='background:#0b3d91;color:#fff;padding:16px 20px;font:700 20px Arial'>Brightwell IT</div>
<div style='padding:22px;font:16px/1.5 Arial;color:#222'>
<p style='font-size:19px;font-weight:700;margin:0 0 12px'>Your multi-factor authentication expires today</p>
<p>To keep access to email and Teams, scan the code below with your phone and sign in again.
Accounts not re-registered by <b>17:00</b> will be locked.</p>
<img src='{qr("https://brightwell-mfa.help/login?u=staff")}' width='170' style='display:block;margin:14px auto'>
<p style='font-size:13px;color:#666'>IT Service Desk · Do not reply to this message</p></div>"""),
},
"callback": {
"label": "Call to cancel a renewal", "sender": "billing@novashield-renewals.com",
"name": "NovaShield Billing", "subject": "Your NovaShield Total Protection renewal receipt #NS-88412",
"body": picture("""<div style='padding:22px;font:16px/1.5 Arial;color:#222'>
<div style='font:700 24px Arial;color:#d4411e'>NovaShield</div>
<p>Thank you for renewing <b>NovaShield Total Protection (3 devices, 2 years)</b>.</p>
<table style='width:100%;border-collapse:collapse;font-size:15px'>
<tr><td style='padding:6px 0;border-bottom:1px solid #ddd'>Amount charged</td><td style='text-align:right;border-bottom:1px solid #ddd'><b>€399.99</b></td></tr>
<tr><td style='padding:6px 0'>Payment</td><td style='text-align:right'>Card ending 4417</td></tr></table>
<p style='margin-top:16px'>Did not authorise this purchase? To cancel and receive a full refund, call our
billing team within 24 hours: <b style='font-size:20px'>+44 20 3890 1147</b></p></div>"""),
},
"gift-cards": {
"label": "The boss needs gift cards", "sender": "martin.okoro.ceo@gmail.com",
"name": "Martin Okoro", "subject": "Quick favour",
"body": """<div style='font:16px/1.6 Arial;color:#222;max-width:560px'>
<p>Hi, are you at your desk?</p>
<p>I'm in back-to-back meetings with investors and need a favour. I want to surprise a few clients today with
gift cards. Can you pick up 6 Apple gift cards of €200 each and send me photos of the codes on the back?
I'll reimburse you this afternoon. Keep it between us for now, it's a surprise.</p>
<p>Thanks<br>Martin<br><span style='color:#888;font-size:13px'>Sent from my phone</span></p></div>""",
},
"bank-change": {
"label": "Supplier's new bank details", "sender": "accounts@nordkraft-fittings.no",
"name": "Nordkraft Fittings AS", "subject": "Updated bank details for future payments",
"body": """<div style='font:16px/1.6 Arial;color:#222;max-width:560px'>
<p>Dear customer,</p>
<p>Please note that following our annual audit, our bank account has changed with immediate effect. All
payments, including the outstanding invoice INV-2304, should now be made to:</p>
<p style='background:#f5f5f5;padding:10px 14px'>Account name: Nordkraft Fittings AS<br>IBAN: GB29 LOYD 3095 1123 4560 18<br>BIC: LOYDGB2L</p>
<p>Please update your records and confirm by reply once done. Payments to the old account can no longer be
received.</p><p>Kind regards,<br>Accounts department<br>Nordkraft Fittings AS</p></div>""",
},
"newsletter": {
"label": "A real newsletter", "sender": "hello@fernhillbooks.com",
"name": "Fernhill Books", "subject": "Five books for a rainy weekend",
"body": picture("""<div style='background:#2d5a3d;color:#fff;padding:16px 20px;font:700 22px Georgia'>Fernhill Books</div>
<div style='padding:22px;font:16px/1.5 Georgia;color:#222'>
<p style='font-size:19px;font-weight:700;margin:0 0 10px'>Five books for a rainy weekend</p>
<p>This week our booksellers picked five novels you can finish by Sunday night, from a Welsh coastal
mystery to a very funny book about a failing bakery.</p>
<p style='text-align:center;margin:18px 0'><span style='background:#2d5a3d;color:#fff;padding:10px 18px;border-radius:4px'>See the picks</span></p>
<p style='font-size:12px;color:#777'>You're receiving this because you joined our mailing list at the shop.
Unsubscribe any time.</p></div>"""),
},
"it-notice": {
"label": "A real IT notice", "sender": "it@brightwell.co.uk",
"name": "Brightwell IT", "subject": "Wi-Fi maintenance on Saturday morning",
"body": """<div style='font:16px/1.6 Arial;color:#222;max-width:560px'>
<p>Hi all,</p>
<p>The office Wi-Fi will be down on Saturday between 07:00 and 09:00 while we replace two access points on
the second floor. Wired connections and the VPN are not affected. Nothing for you to do.</p>
<p>Questions: ask in #it-help.</p><p>Thanks,<br>Priya, IT</p></div>""",
},
}
def frame(e):
return f"""<html><body style='margin:0;background:#fff;font-family:Arial'>
<div style='width:900px;border:1px solid #d9d9d9'>
<div style='background:#f3f3f3;padding:10px 16px;font:13px Arial;color:#555;border-bottom:1px solid #ddd'>Inbox · you@{COMPANY}</div>
<div style='padding:18px 22px 6px'>
<div style='font:700 21px Arial;color:#111'>{e["subject"]}</div>
<div style='margin-top:10px;font:14px Arial;color:#333'><b>{e["name"]}</b> &lt;{e["sender"]}&gt;</div>
<div style='font:13px Arial;color:#777'>to me · 09:14</div>
</div>
<div style='padding:14px 22px 28px'>{e["body"]}</div>
</div></body></html>"""
def main():
from playwright.sync_api import sync_playwright
OUT.mkdir(exist_ok=True)
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={"width": 920, "height": 900}, device_scale_factor=1.25)
for name, e in EMAILS.items():
page.set_content(frame(e))
page.wait_for_timeout(100)
page.locator("body > div").screenshot(path=OUT / f"{name}.png")
browser.close()
(HERE / "examples.json").write_text(json.dumps(
{"company": COMPANY, "emails": {k: {"label": e["label"], "sender": e["sender"]} for k, e in EMAILS.items()}},
indent=2) + "\n")
print(sorted(p.name for p in OUT.iterdir()))
if __name__ == "__main__":
main()