Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions progress.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Progress

## Branded emails (2026-10-06)

### Done

- `templates/emails/trivia_tap_wrapper.html`: TriviaTap wrapper for every auth mail, dark like the app. Near-black card with logo and name, white title, code centered in a mint gradient box, mint gradient pill button, and a "Need help?" footer pointing to developers@bwh.tech. Picked over a minimal light and a playful mascot design.
- `send_mail` sets Reply-To to developers@bwh.tech, so a reply reaches support instead of noreply.
- Test: the queued mail carries the logo, the support link and the Reply-To header.

### Notes

- Styles live in the wrapper's `<style>` and premailer inlines them. A few need `!important` to beat frappe's `email.bundle` rules (`p` margin, `.email-btn-primary` color).
- Gradients have a solid `#20eea0` fallback for clients without `background-image` (Outlook).
- No web font link: premailer fetches external stylesheets on every send. The mail falls back to system fonts.

## README media refresh (2026-10-04)

### Done
Expand Down
4 changes: 2 additions & 2 deletions trivia_tap/email_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def send_mail(email: str, subject: str, template: str, args: dict) -> None:
subject=subject,
template=template,
args=args,
with_container=True,
wrapper="templates/emails/auth_email.html",
reply_to="developers@bwh.tech",
wrapper="templates/emails/trivia_tap_wrapper.html",
now=True,
)
61 changes: 61 additions & 0 deletions trivia_tap/templates/emails/trivia_tap_wrapper.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="color-scheme" content="dark" />
<meta name="supported-color-schemes" content="dark" />
<title>{{ subject or "" }}</title>
<style>
.tt-page { width: 100%; background-color: #070b09; font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }
.tt-page .tt-shell { padding: 40px 16px; }
.tt-page .tt-card { width: 100%; max-width: 520px; background-color: #111a16; border: 1px solid #22302a; border-radius: 20px; }
.tt-page .tt-masthead { padding: 28px 32px 0; }
.tt-page .tt-masthead a { text-decoration: none; }
.tt-page .tt-logo { width: 30px; height: 30px; border: 0; border-radius: 8px; vertical-align: middle; }
.tt-page .tt-wordmark { padding-left: 10px; vertical-align: middle; font-size: 18px; font-weight: 800; color: #ffffff; }
.tt-page .tt-content { padding: 28px 32px 32px; }
.tt-page .email-title { margin: 0 0 12px; font-size: 26px; font-weight: 800; line-height: 1.2; letter-spacing: -0.01em; color: #ffffff; }
.tt-page .email-body p { margin: 0 0 24px !important; font-size: 15px; line-height: 1.6; color: #a7b6af; }
.tt-page .email-body .email-code { margin: 0 0 24px; padding: 20px 0; text-align: center; text-indent: 0.25em; font-family: "SF Mono", Menlo, Consolas, monospace; font-size: 34px; font-weight: 700; letter-spacing: 0.25em; color: #06110c; background-color: #20eea0; background-image: linear-gradient(135deg, #6bf57f, #11ddb9); border-radius: 14px; }
.tt-page .email-body .email-action { margin: 0 0 24px; }
.tt-page .email-body .email-btn { display: inline-block; padding: 14px 26px; font-size: 15px; font-weight: 700 !important; line-height: 1; text-decoration: none !important; color: #06110c !important; background-color: #20eea0; background-image: linear-gradient(135deg, #6bf57f, #11ddb9); border: 0; border-radius: 999px; }
.tt-page .email-body .email-ignore { margin: 0 !important; font-size: 13px; color: #6f7f78; }
.tt-page .tt-help { padding: 18px 32px 24px; font-size: 13px; line-height: 1.6; color: #6f7f78; border-top: 1px solid #22302a; }
.tt-page .tt-help a { color: #6bf57f !important; font-weight: 600; text-decoration: none; }
.tt-page .tt-meta { max-width: 520px; padding-top: 20px; text-align: center; font-size: 12px; line-height: 1.6; color: #6f7f78; }
.tt-page .tt-meta a { color: #a7b6af !important; }
</style>
</head>

<body style="margin: 0; padding: 0; background-color: #070b09;">
<table class="tt-page" role="presentation" cellpadding="0" cellspacing="0">
<tr>
<td class="tt-shell" align="center" valign="top">
<table class="tt-card" role="presentation" cellpadding="0" cellspacing="0">
<tr>
<td class="tt-masthead">
<a href="{{ site_url }}/trivia-tap">
<img class="tt-logo" src="/assets/trivia_tap/images/trivia-tap-logo.png" width="30" height="30" alt="" /><span class="tt-wordmark">TriviaTap</span>
</a>
</td>
</tr>
<tr>
<td class="tt-content">{{ content }}</td>
</tr>
<tr>
<td class="tt-help">
{{ _("Need help? Write to {0}.").format('<a href="mailto:developers@bwh.tech">developers@bwh.tech</a>') }}
</td>
</tr>
</table>
<div class="tt-meta">
<div data-email-footer="true">{{ footer }}</div>
</div>
</td>
</tr>
</table>
</body>

</html>
18 changes: 17 additions & 1 deletion trivia_tap/tests/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
from urllib.parse import parse_qs, urlsplit

import frappe
from frappe.email.email_body import get_formatted_html
from frappe.tests import IntegrationTestCase
from frappe.utils.jinja import get_email_from_template
from frappe.utils.oauth import consume_oauth_state, update_oauth_user
from frappe.utils.password import check_password

Expand All @@ -16,7 +18,7 @@
send_reset_link,
sign_up,
)
from trivia_tap.email_code import MAX_TRIES
from trivia_tap.email_code import MAX_TRIES, send_mail
from trivia_tap.patches import brand_site

EMAIL = "new.host@example.com"
Expand Down Expand Up @@ -303,3 +305,17 @@ def test_google_sign_up_lands_as_a_quiz_host(self):
self.assertIn("Quiz Host", frappe.get_roles(EMAIL))
self.assertEqual(user.user_type, "System User")
self.assertEqual(user.get_social_login_userid("google"), "google-123")


class TestMail(IntegrationTestCase):
@patch("trivia_tap.email_code.frappe.sendmail")
def test_mail_carries_the_brand_and_support_address(self, sendmail):
send_mail(EMAIL, "Your TriviaTap log in code", "trivia_tap_code", {"code": "042917", "minutes": 10})

mail = sendmail.call_args.kwargs
self.assertEqual(mail["reply_to"], "developers@bwh.tech")
content = get_email_from_template(mail["template"], mail["args"])[0]
message = get_formatted_html(mail["subject"], content, wrapper=mail["wrapper"])
self.assertIn("042917", message)
self.assertIn("trivia-tap-logo.png", message)
self.assertIn("mailto:developers@bwh.tech", message)
Loading