Update TypeScript version and enhance ContactForm and email handling

- Upgraded TypeScript dependency from 5.7.3 to 5.8.3 for improved type checking and features.
- Modified ContactForm component to include a hidden input for the domain, capturing the current hostname.
- Updated API contact handling to log and utilize the domain information in email notifications.
- Refactored email sending functions to conditionally include the domain in the sender's address for better context.
This commit is contained in:
2025-06-26 23:40:44 +02:00
parent 559bd3e983
commit 246edb3952
5 changed files with 31 additions and 13 deletions

2
package-lock.json generated
View File

@@ -67,7 +67,7 @@
"sharp": "0.33.5", "sharp": "0.33.5",
"tailwind-merge": "^2.6.0", "tailwind-merge": "^2.6.0",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"typescript": "^5.7.3", "typescript": "^5.8.3",
"typescript-eslint": "^8.21.0", "typescript-eslint": "^8.21.0",
"unist-util-visit": "^5.0.0" "unist-util-visit": "^5.0.0"
}, },

View File

@@ -15,10 +15,10 @@
"astro": "astro", "astro": "astro",
"check": "npm run check:astro && npm run check:eslint && npm run check:prettier", "check": "npm run check:astro && npm run check:eslint && npm run check:prettier",
"check:astro": "astro check", "check:astro": "astro check",
"check:eslint": "eslint .", "check:eslint": "npx eslint .",
"check:prettier": "prettier --check .", "check:prettier": "prettier --check .",
"fix": "npm run fix:eslint && npm run fix:prettier", "fix": "npm run fix:eslint && npm run fix:prettier",
"fix:eslint": "eslint --fix .", "fix:eslint": "npx eslint --fix .",
"fix:prettier": "prettier -w ." "fix:prettier": "prettier -w ."
}, },
"dependencies": { "dependencies": {
@@ -81,7 +81,7 @@
"sharp": "0.33.5", "sharp": "0.33.5",
"tailwind-merge": "^2.6.0", "tailwind-merge": "^2.6.0",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"typescript": "^5.7.3", "typescript": "^5.8.3",
"typescript-eslint": "^8.21.0", "typescript-eslint": "^8.21.0",
"unist-util-visit": "^5.0.0" "unist-util-visit": "^5.0.0"
} }

View File

@@ -1,5 +1,6 @@
<form id="contact-form"> <form id="contact-form">
<input type="hidden" name="csrf_token" id="csrf_token" /> <input type="hidden" name="csrf_token" id="csrf_token" />
<input type="hidden" name="domain" id="domain" />
<label for="email">Email</label> <label for="email">Email</label>
<input type="email" name="email" id="email" required aria-describedby="email-help" /> <input type="email" name="email" id="email" required aria-describedby="email-help" />
<div id="email-help" class="sr-only">Enter your email address</div> <div id="email-help" class="sr-only">Enter your email address</div>
@@ -43,7 +44,17 @@ async function fetchCsrfToken() {
} }
} }
document.addEventListener('DOMContentLoaded', fetchCsrfToken); function setDomainHiddenField() {
const domainInput = document.getElementById('domain');
if (domainInput) {
(domainInput as HTMLInputElement).value = window.location.hostname;
}
}
document.addEventListener('DOMContentLoaded', () => {
fetchCsrfToken();
setDomainHiddenField();
});
const contactForm = document.getElementById('contact-form'); const contactForm = document.getElementById('contact-form');
const feedbackDiv = document.getElementById('form-feedback'); const feedbackDiv = document.getElementById('form-feedback');

View File

@@ -169,6 +169,7 @@ export const POST: APIRoute = async ({ request, clientAddress }) => {
const message = formData.get('message')?.toString() || ''; const message = formData.get('message')?.toString() || '';
const disclaimer = formData.get('disclaimer')?.toString() === 'on'; const disclaimer = formData.get('disclaimer')?.toString() === 'on';
const csrfToken = formData.get('csrf_token')?.toString() || ''; const csrfToken = formData.get('csrf_token')?.toString() || '';
const domain = formData.get('domain')?.toString() || '';
console.log('Form data values:', { console.log('Form data values:', {
name, name,
@@ -176,6 +177,7 @@ export const POST: APIRoute = async ({ request, clientAddress }) => {
messageLength: message.length, messageLength: message.length,
disclaimer, disclaimer,
csrfToken: csrfToken ? 'present' : 'missing', csrfToken: csrfToken ? 'present' : 'missing',
domain,
}); });
// Get user agent for logging and spam detection // Get user agent for logging and spam detection
@@ -255,11 +257,11 @@ export const POST: APIRoute = async ({ request, clientAddress }) => {
// Send emails // Send emails
console.log('Attempting to send admin notification email'); console.log('Attempting to send admin notification email');
const adminEmailSent = await sendAdminNotification(name, email, message, ipAddress, userAgent); const adminEmailSent = await sendAdminNotification(name, email, message, ipAddress, userAgent, domain);
console.log('Admin email sent result:', adminEmailSent); console.log('Admin email sent result:', adminEmailSent);
console.log('Attempting to send user confirmation email'); console.log('Attempting to send user confirmation email');
const userEmailSent = await sendUserConfirmation(name, email, message); const userEmailSent = await sendUserConfirmation(name, email, message, domain);
console.log('User email sent result:', userEmailSent); console.log('User email sent result:', userEmailSent);
// Check if emails were sent successfully // Check if emails were sent successfully

View File

@@ -140,14 +140,18 @@ export function logEmailAttempt(success: boolean, recipient: string, subject: st
} }
// Send an email // Send an email
export async function sendEmail(to: string, subject: string, html: string, text: string): Promise<boolean> { export async function sendEmail(to: string, subject: string, html: string, text: string, domain?: string): Promise<boolean> {
// Initialize transporter if not already done // Initialize transporter if not already done
if (!transporter) { if (!transporter) {
initializeTransporter(); initializeTransporter();
} }
try { try {
const fromAddress = isProduction ? `"${WEBSITE_NAME}" <${SMTP_USER || 'noreply@' + WEBSITE_NAME}>` : `"${WEBSITE_NAME}" <${ADMIN_EMAIL}>`; const fromAddress = isProduction
? domain
? `"${WEBSITE_NAME}" <${SMTP_USER || 'info'}@${domain}>`
: `"${WEBSITE_NAME}" <${SMTP_USER || 'noreply@' + WEBSITE_NAME}>`
: `"${WEBSITE_NAME}" <${ADMIN_EMAIL}>`;
const mailOptions = { const mailOptions = {
from: fromAddress, from: fromAddress,
@@ -197,7 +201,8 @@ export async function sendAdminNotification(
email: string, email: string,
message: string, message: string,
ipAddress?: string, ipAddress?: string,
userAgent?: string userAgent?: string,
domain?: string
): Promise<boolean> { ): Promise<boolean> {
// Validate inputs // Validate inputs
if (!name || name.trim() === '') { if (!name || name.trim() === '') {
@@ -239,11 +244,11 @@ Time: ${new Date().toLocaleString()}
This message was sent from the contact form on ${WEBSITE_NAME} This message was sent from the contact form on ${WEBSITE_NAME}
`; `;
return sendEmail(ADMIN_EMAIL, subject, html, text); return sendEmail(ADMIN_EMAIL, subject, html, text, domain);
} }
// Send user confirmation email // Send user confirmation email
export async function sendUserConfirmation(name: string, email: string, message: string): Promise<boolean> { export async function sendUserConfirmation(name: string, email: string, message: string, domain?: string): Promise<boolean> {
// Validate inputs // Validate inputs
if (!name || name.trim() === '') { if (!name || name.trim() === '') {
console.error('Cannot send user confirmation: name is empty'); console.error('Cannot send user confirmation: name is empty');
@@ -280,7 +285,7 @@ ${WEBSITE_NAME} Team
This is an automated message, please do not reply directly to this email. This is an automated message, please do not reply directly to this email.
`; `;
return sendEmail(email, subject, html, text); return sendEmail(email, subject, html, text, domain);
} }
// Initialize the email system // Initialize the email system