feat: echo submitted message back in confirmation email
Task #18 — Send a copy of the submitted message back to the contact in the confirmation email. Changes made to artifacts/api-server/src/routes/contact.ts: - Updated buildConfirmationEmail() signature from (name: string) to ({ name, subject, message }) so it can accept and render the original submission. - Added a visually distinct "Ihre Nachricht" quoted block to the HTML template: - Light gray background (#f8fafc) matching the existing bgField colour - Subtle 3px left border (#e2e8f0) styled as a blockquote - Rounded right corners (border-radius: 0 6px 6px 0) - ALL-CAPS label "IHRE NACHRICHT" in the same style as field labels elsewhere - Optional subject line rendered in semi-bold if provided - Message body with white-space:pre-wrap to preserve line breaks - All user-supplied values (subject, message) passed through the existing escapeHtml() helper — XSS-safe. - Updated the plain-text fallback: adds a "—" delimited quoted section with optional "Betreff:" line before the message body. - Updated the call site to pass { name, subject, message } to buildConfirmationEmail(). No new dependencies. Pre-existing TS error (SendContactMessageBody missing from @workspace/api-zod) is unrelated to this task and unchanged. Replit-Task-Id: 63279220-bb35-4721-bbd6-86182301a697
This commit is contained in:
@@ -67,13 +67,19 @@ router.post("/contact", contactRateLimit, async (req, res) => {
|
|||||||
"",
|
"",
|
||||||
"vielen Dank für Ihre Nachricht! Ich habe Ihre Anfrage erhalten und melde mich in der Regel innerhalb von 1–2 Werktagen bei Ihnen.",
|
"vielen Dank für Ihre Nachricht! Ich habe Ihre Anfrage erhalten und melde mich in der Regel innerhalb von 1–2 Werktagen bei Ihnen.",
|
||||||
"",
|
"",
|
||||||
|
"Zur Erinnerung, hier ist Ihre Nachricht:",
|
||||||
|
"—",
|
||||||
|
...(subject ? [`Betreff: ${subject}`, ""] : []),
|
||||||
|
message,
|
||||||
|
"—",
|
||||||
|
"",
|
||||||
"Mit freundlichen Grüßen",
|
"Mit freundlichen Grüßen",
|
||||||
"Joachim Hummel",
|
"Joachim Hummel",
|
||||||
"",
|
"",
|
||||||
"—",
|
"—",
|
||||||
"jh@unixweb.de",
|
"jh@unixweb.de",
|
||||||
].join("\n"),
|
].join("\n"),
|
||||||
htmlContent: buildConfirmationEmail(name),
|
htmlContent: buildConfirmationEmail({ name, subject, message }),
|
||||||
});
|
});
|
||||||
|
|
||||||
req.log.info({ to: email }, "Confirmation email sent to sender via Brevo");
|
req.log.info({ to: email }, "Confirmation email sent to sender via Brevo");
|
||||||
@@ -255,8 +261,18 @@ function buildNotificationEmail({
|
|||||||
</html>`;
|
</html>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildConfirmationEmail(name: string): string {
|
function buildConfirmationEmail({
|
||||||
|
name,
|
||||||
|
subject,
|
||||||
|
message,
|
||||||
|
}: {
|
||||||
|
name: string;
|
||||||
|
subject?: string;
|
||||||
|
message: string;
|
||||||
|
}): string {
|
||||||
const safeName = escapeHtml(name);
|
const safeName = escapeHtml(name);
|
||||||
|
const safeSubject = subject ? escapeHtml(subject) : null;
|
||||||
|
const safeMessage = escapeHtml(message);
|
||||||
const brandBlue = "#3f4ff4";
|
const brandBlue = "#3f4ff4";
|
||||||
const textDark = "#0f172a";
|
const textDark = "#0f172a";
|
||||||
const textMid = "#334155";
|
const textMid = "#334155";
|
||||||
@@ -265,6 +281,7 @@ function buildConfirmationEmail(name: string): string {
|
|||||||
const borderColor = "#e2e8f0";
|
const borderColor = "#e2e8f0";
|
||||||
const bgPage = "#f1f5f9";
|
const bgPage = "#f1f5f9";
|
||||||
const bgCard = "#ffffff";
|
const bgCard = "#ffffff";
|
||||||
|
const bgQuote = "#f8fafc";
|
||||||
|
|
||||||
return `<!DOCTYPE html>
|
return `<!DOCTYPE html>
|
||||||
<html lang="de" xmlns="http://www.w3.org/1999/xhtml">
|
<html lang="de" xmlns="http://www.w3.org/1999/xhtml">
|
||||||
@@ -301,7 +318,24 @@ function buildConfirmationEmail(name: string): string {
|
|||||||
<p style="margin:0 0 6px;font-size:22px;font-weight:700;color:${textDark};line-height:1.3;">Vielen Dank, ${safeName}!</p>
|
<p style="margin:0 0 6px;font-size:22px;font-weight:700;color:${textDark};line-height:1.3;">Vielen Dank, ${safeName}!</p>
|
||||||
<p style="margin:0 0 20px;font-size:13px;font-weight:500;color:${brandBlue};letter-spacing:0.3px;">Ihre Anfrage ist eingegangen.</p>
|
<p style="margin:0 0 20px;font-size:13px;font-weight:500;color:${brandBlue};letter-spacing:0.3px;">Ihre Anfrage ist eingegangen.</p>
|
||||||
<p style="margin:0 0 16px;font-size:15px;line-height:1.75;color:${textMid};">Schön, dass Sie sich gemeldet haben. Ich habe Ihre Nachricht erhalten und werde mich in der Regel innerhalb von <strong style="color:${textDark};">1–2 Werktagen</strong> bei Ihnen melden.</p>
|
<p style="margin:0 0 16px;font-size:15px;line-height:1.75;color:${textMid};">Schön, dass Sie sich gemeldet haben. Ich habe Ihre Nachricht erhalten und werde mich in der Regel innerhalb von <strong style="color:${textDark};">1–2 Werktagen</strong> bei Ihnen melden.</p>
|
||||||
<p style="margin:0 0 32px;font-size:15px;line-height:1.75;color:${textMid};">Bis dahin können Sie gerne mein Portfolio besuchen oder mir direkt eine E-Mail schicken.</p>
|
<p style="margin:0 0 24px;font-size:15px;line-height:1.75;color:${textMid};">Bis dahin können Sie gerne mein Portfolio besuchen oder mir direkt eine E-Mail schicken.</p>
|
||||||
|
|
||||||
|
<!-- ── Quoted message ── -->
|
||||||
|
<table width="100%" cellpadding="0" cellspacing="0" border="0" role="presentation" style="margin-bottom:32px;">
|
||||||
|
<tr>
|
||||||
|
<td style="padding-left:4px;">
|
||||||
|
<table width="100%" cellpadding="0" cellspacing="0" border="0" role="presentation" style="background-color:${bgQuote};border-left:3px solid ${borderColor};border-radius:0 6px 6px 0;">
|
||||||
|
<tr>
|
||||||
|
<td style="padding:16px 20px;">
|
||||||
|
<p style="margin:0 0 10px;font-size:11px;font-weight:600;color:${textLight};letter-spacing:1px;text-transform:uppercase;">Ihre Nachricht</p>
|
||||||
|
${safeSubject ? `<p style="margin:0 0 8px;font-size:13px;font-weight:600;color:${textMuted};">Betreff: ${safeSubject}</p>` : ""}
|
||||||
|
<p style="margin:0;font-size:14px;line-height:1.75;color:${textMid};white-space:pre-wrap;">${safeMessage}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
<!-- CTA button -->
|
<!-- CTA button -->
|
||||||
<table cellpadding="0" cellspacing="0" border="0" role="presentation">
|
<table cellpadding="0" cellspacing="0" border="0" role="presentation">
|
||||||
|
|||||||
Reference in New Issue
Block a user