Validate the guest e-mail before the booking is saved

An address like "asdf" used to be accepted: the field was type="text" with
only `required`, and there was no server-side check. createBooking() runs
long before sendEmail(), so the failure was silent rather than loud -
reproduced end to end on test:

  - the booking row WAS created, with a manage_token
  - PHPMailer's addAddress() threw, so nothing was ever sent
  - the Location header was already queued, so the guest was redirected to
    the normal "booking finished" page and saw success
  - Evelin is a CC on that same message, so the salon was not told either
  - the guest had no manage link, so they could not cancel

Fixes
- booking_process() rejects an empty or malformed address BEFORE any write,
  returning invalid_email / HTTP 400. Message added in all three languages,
  worded to say why it matters (the confirmation and the manage link go
  there). filter_var is equal-or-stricter than PHPMailer's own validator -
  checked against it on ten cases - so anything accepted here cannot throw
  later.
- The three public booking forms use type="email", so most typos never
  reach the server.
- Removed three debug echoes from User_model::sendEmail() that leaked $lang
  and Hungarian strings ("Üzenet elküldve", "Üzenetküldési hiba. Mailer
  Error: ...") into the guest-facing response.

Scope
- Public flow only. 508 existing bookings have an empty guest_email because
  admin-created block bookings legitimately have none; those go through
  Admin::booking_process(), which is untouched, and its form stays
  type="text".
- Not covered: a valid address whose SMTP delivery fails still leaves the
  booking created and the guest seeing success, logged only via
  log_message(). Different failure mode, needs a separate decision.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Ubuntu
2026-08-15 09:55:33 +00:00
co-authored by Claude Opus 5
parent 7f51a795a5
commit 35115404be
8 changed files with 28 additions and 7 deletions
@@ -178,7 +178,7 @@ if (is_array($services) && count($services) > 0) {
</div>
<div class="formRow">
<label class="bookingEmailTitle">E-mail:</label>
<input type="text" class="bookingEmail" name="guest_email" value="" required>
<input type="email" class="bookingEmail" name="guest_email" value="" required>
</div>
<div class="formRow">
<label class="bookingPhoneTitle">Telefon:</label>