From 5b9bbace8be23a9c814710265bb101171632b014 Mon Sep 17 00:00:00 2001 From: Alex Polo Date: Wed, 29 Oct 2025 10:40:50 +0100 Subject: [PATCH] fix(contact): send from authenticated mailbox and set Reply-To for Office365 SMTP; update env example and README with app-password notes --- .env.example | 6 +++++- README.md | 22 ++++++++++++++++++++++ src/app/api/contact/route.ts | 11 +++++++++-- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/.env.example b/.env.example index 9e97a2c..e823dea 100644 --- a/.env.example +++ b/.env.example @@ -19,4 +19,8 @@ SMTP_USER=your-smtp-user@example.com SMTP_PASS=your-smtp-password # The recipient for booking messages (defaults to christian@warme.dk) -BOOKING_EMAIL=christian@warme.dk \ No newline at end of file +BOOKING_EMAIL=christian@warme.dk +SENDER_EMAIL=christian@warme.dk + +# Notes: If your account uses MFA, create an app password for SMTP and use it in SMTP_PASS. +# Office365 settings: SMTP_HOST=smtp.office365.com, SMTP_PORT=587 (STARTTLS) \ No newline at end of file diff --git a/README.md b/README.md index a4259bc..f6d18c2 100644 --- a/README.md +++ b/README.md @@ -80,3 +80,25 @@ Notes: - Generated images can be large; a small number of generated images were removed from git and the project ignores `public/img/generated/`. If you want generated images checked into the repo, move them into `public/img/` and commit explicitly. - For production process management the project includes PM2 scripts in `package.json` (see `pm2:*` scripts). +### Office365 / SMTP (app password) + +If you plan to use an Office365 mailbox with SMTP (app password): + +1. Enable SMTP AUTH for the mailbox (tenant settings may block it by default). +2. If the mailbox has MFA enabled, create an app password for the mailbox and use it as `SMTP_PASS`. + - Microsoft 365: My account -> Security info -> Add method -> App password (or use admin center to manage). +3. Set these env vars in your local `.env`: + +```bash +SMTP_HOST=smtp.office365.com +SMTP_PORT=587 +SMTP_USER=christian@warme.dk +SMTP_PASS=your-app-password +SENDER_EMAIL=christian@warme.dk +BOOKING_EMAIL=christian@warme.dk +``` + +4. The contact API will send mail using the authenticated mailbox as the From address and set Reply-To to the visitor's email so replies go to them. + +If you prefer a more modern and robust approach we can switch to Microsoft Graph API with OAuth2 (recommended for production). + diff --git a/src/app/api/contact/route.ts b/src/app/api/contact/route.ts index 2067be0..d1b07e9 100644 --- a/src/app/api/contact/route.ts +++ b/src/app/api/contact/route.ts @@ -49,11 +49,18 @@ export async function POST(req: Request) {
${message.replace(/\n/g, '
')}
` + // For Office365 SMTP with an app-password, the 'from' address usually + // must be the authenticated mailbox. Use SENDER_EMAIL (or SMTP_USER) + // as the From, and set Reply-To to the form submitter so replies go to them. + const senderEmail = process.env.SENDER_EMAIL || user + await transporter.sendMail({ - from: `${name} <${email}>`, + from: senderEmail, + replyTo: `${name} <${email}>`, to, subject, - html + html, + text: `${name} (${email})\n\n${message}` }) return NextResponse.json({ ok: true })