3.3 KiB
3.3 KiB
Task 02 — Contact page with MailPit form
- Status: Done — 2026-08-20
- Depends on: 01
- Size: M
Goal
Create the Contact page at /Contact with a form that emails its submission to MailPit (tools.host.domain:1025, recipient [email protected]) via the existing MailSender.
Files
- Create:
plushealthtech/Pages/Contact.cshtml - Create:
plushealthtech/Pages/Contact.cshtml.cs
Steps
-
PageModel (
ContactModel : PageModel)- Inject
MailSender(+ILogger<ContactModel>). [BindProperty]fields with DataAnnotations:Name—[Required],[StringLength(200)]Email—[Required],[EmailAddress],[StringLength(320)]Organization—[StringLength(200)](optional)Phone—[StringLength(50)](optional)Message—[Required],[StringLength(5000)]
public string? Success { get; set; }andpublic string? Error { get; set; }(simple re-render flags).OnGet()— reset flags.OnPost():- If
!ModelState.IsValid→ returnPage()(validation messages re-render). - Else build a plain-text body: one
Field: valueline per non-empty field, blank line, then the message. await _mailSender.SendAsync($"New contact form message — {Model.Name}", body);- On success:
Success = "Thanks — your message has been sent. We'll reply to {Email}."(re-render page with the panel). - Catch
SmtpException(or generalException) → log the exception, setErrorto a generic "Your message could not be sent right now. Please try again or email us directly." — never surface SMTP details to the user.
- If
- Inject
-
View (
Contact.cshtml)@page,@model ContactModel,ViewData["Title"] = "Contact".- Layout consistent with the Index page: light hero (heading + one-line intro), then a single form card (
bg-white p-8 rounded-2xl border border-slate-100 shadow-sm) with the fields, Tailwind classes matching the site's existing inputs (rounded-xl,border-slate-200,focus:border-brandstyle), a submit button in brand color (bg-[#1c8098] hover:bg-[#145f72] rounded-xl). @Html.AntiforgeryToken()in the form.- Validation messages per field (
<span asp-validation-for="...">);Successpanel (green, replaces/above the form) andErrorbanner (red) rendered when set. - A short side note block: "We reply to the email address you provide — nothing else is stored."
Acceptance criteria
GET /Contactrenders with all five fields; build green.- Empty required fields / invalid email → validation messages, no mail sent.
- Valid submit → success panel shown; MailPit shows the message from
[email protected]to[email protected]with subjectNew contact form message — {Name}(e2e verified 2026-08-20, ahead of Task 13). - With MailPit down → friendly error banner, exception in app log, no stack trace in the browser.
Notes
- Antiforgery: the form uses
asp-page="/Contact", which auto-injects__RequestVerificationToken— the explicit@Html.AntiforgeryToken()from the spec is unnecessary and would duplicate the field. - SMTP-down path verified by running the app with
Smtp__Port=1(env override, no config change): banner rendered,SmtpException (SocketException 10061)logged, response body clean.