Email retention

This commit is contained in:
Timo Knuth
2026-04-02 11:37:58 +02:00
parent 1cff96a553
commit 7afd39c18c
18 changed files with 4110 additions and 2951 deletions

119
tmp_email_size_test.js Normal file
View File

@@ -0,0 +1,119 @@
// Quick size test for email templates - run with: node tmp_email_size_test.js
const src = require('fs').readFileSync('src/lib/email.ts', 'utf8');
// Extract the constants we need
const clr = {
bg: '#F5F2EC', card: '#FFFFFF', header: '#0B0D14', headerAccent: '#1A1D2E',
gold: '#C8A257', goldDim: '#A07E3A', text: '#1A1A1A', textSoft: '#5A5A5A',
textMuted: '#909090', border: '#E8E3D8', pillBg: '#F0EDE5',
ctaBg: '#0B0D14', ctaText: '#FFFFFF',
};
const dotGridPattern = `url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%221.5%22%20fill%3D%22%23C8A257%22%20fill-opacity%3D%220.18%22%2F%3E%3C%2Fsvg%3E)`;
const webFontHead = `
<style>
@import url('https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Sans:wght@300;400;500;600&display=swap');
.dm-serif { font-family: 'DM Serif Display', Georgia, 'Times New Roman', serif !important; }
.dm-sans { font-family: 'DM Sans', -apple-system, 'Helvetica Neue', Arial, sans-serif !important; }
</style>`;
const appUrl = 'https://www.qrmaster.net';
function emailShell(headExtra, bodyContent) {
return `<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light">
<meta name="supported-color-schemes" content="light">
${webFontHead}
${headExtra}
</head>
<body style="margin:0;padding:0;background-color:${clr.bg};-webkit-text-size-adjust:100%;mso-line-height-rule:exactly;">
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0"
style="background-color:${clr.bg};padding:40px 16px 60px;">
<tr><td align="center">
<!-- Email card -->
<table role="presentation" width="560" cellpadding="0" cellspacing="0" border="0"
style="max-width:560px;width:100%;background-color:${clr.card};border-radius:16px;
overflow:hidden;box-shadow:0 8px 40px rgba(0,0,0,0.12);">
${bodyContent}
</table>
<!-- Footer text -->
<table role="presentation" width="560" cellpadding="0" cellspacing="0" border="0"
style="max-width:560px;width:100%;margin-top:28px;">
<tr>
<td style="text-align:center;padding:0 20px;">
<p style="margin:0 0 6px;font-family:'DM Sans',-apple-system,sans-serif;font-size:12px;color:${clr.textMuted};">
<a href="${appUrl}" style="color:${clr.gold};text-decoration:none;font-weight:500;">www.qrmaster.net</a>
&nbsp;·&nbsp;
<a href="mailto:support@qrmaster.net" style="color:${clr.textMuted};text-decoration:none;">support@qrmaster.net</a>
</p>
<p style="margin:0;font-family:'DM Sans',-apple-system,sans-serif;font-size:11px;color:#B0A898;">
© 2026 QR Master. You're receiving this because you created an account.
</p>
</td>
</tr>
</table>
</td></tr>
</table>
</body>
</html>`;
}
// Build welcome email
const firstName = 'Timo';
const createUrl = `${appUrl}/create`;
const welcomeHtml = emailShell('', `
<!-- ── HEADER ── -->
<tr>
<td style="background-color:${clr.card};background-image:${dotGridPattern};
background-size:24px 24px;padding:60px 48px 50px;text-align:center;">
<table role="presentation" cellpadding="0" cellspacing="0" border="0" align="center">
<tr>
<td style="border:1px solid rgba(200,162,87,0.4);border-radius:6px;padding:6px 16px;background-color:rgba(200,162,87,0.05);">
<span style="font-family:'DM Sans',-apple-system,sans-serif;font-size:10px;font-weight:700;letter-spacing:3px;color:${clr.gold};text-transform:uppercase;">QR Master</span>
</td>
</tr>
</table>
<h1 style="margin:36px 0 0;font-family:'DM Serif Display',Georgia,serif;font-size:42px;font-weight:400;line-height:1.1;color:${clr.text};letter-spacing:-0.5px;">
Welcome,<br>
<em style="color:${clr.gold};font-style:italic;">${firstName}.</em>
</h1>
<p style="margin:24px 0 0;font-family:'DM Sans',-apple-system,sans-serif;font-size:15px;color:${clr.textSoft};letter-spacing:0.3px;">
The physical world is now your canvas.
</p>
</td>
</tr>
<tr>
<td style="padding: 0; text-align: center; background-color: ${clr.card};">
<img src="${appUrl}/email-hero-light.png" width="560" style="display:block;width:100%;max-width:560px;height:auto;border-bottom:3px solid ${clr.gold};" alt="Beautiful QR Code Experience">
</td>
</tr>
<tr>
<td style="padding:56px 48px 0;">
<p style="margin:0 0 24px;font-family:'DM Sans',-apple-system,sans-serif;font-size:16px;line-height:1.8;color:${clr.text};">
Let's be honest: most QR codes are static, look terrible, and break the moment you change a link. We built QR Master to fix that.
</p>
<p style="margin:0 0 24px;font-family:'DM Sans',-apple-system,sans-serif;font-size:16px;line-height:1.8;color:${clr.text};">
Your account is fully activated. You now have the power to create beautiful, dynamic QR codes that adapt to your brand, never expire, and track every single scan (device, location, and time).
</p>
<p style="margin:0;font-family:'DM Sans',-apple-system,sans-serif;font-size:16px;line-height:1.8;color:${clr.textSoft};">
To give you the perfect start, we've loaded your account with everything you need:
</p>
</td>
</tr>
`);
const sizeKB = Buffer.byteLength(welcomeHtml, 'utf8') / 1024;
console.log('Welcome email rendered size:', sizeKB.toFixed(1), 'KB');
console.log('Gmail clips at: 102 KB');
console.log('Status:', sizeKB < 102 ? 'OK - under limit' : 'CLIPPED - over 102KB limit!');
console.log('');
console.log('Shell overhead approx:', Buffer.byteLength(emailShell('', ''), 'utf8') / 1024, 'KB');