Sending Contact Form Email with Amplify Gen 2
Build an Amplify Gen 2 contact form that validates input, sends server-side email, protects secrets, and reports delivery failures.
A contact form has two users: the visitor who needs a clear result and the site owner who needs a trustworthy message. I keep email delivery behind an Amplify Function so browser code never receives provider credentials. The server route validates and stores a small payload, then a DynamoDB stream invokes the function to send the notification. The interface confirms that the submission was accepted and queued; it does not claim that email delivery has completed.
I treat submission acceptance and email delivery as separate events. A 200 response from an API should mean the workflow reached a defined state, not that the handler swallowed an exception.
Minimize the submitted fields
I ask only for the information needed to reply: a name, reply address, subject or service choice, and message. Server-side validation repeats browser checks because a caller can bypass the form. Length limits protect logs and downstream providers from oversized input.
I normalize whitespace and reject malformed values. I do not accept a recipient address from the browser; the destination belongs in server configuration. Hidden fields, timing checks, and rate limits can reduce simple abuse without collecting more personal data.
Put delivery in a focused function
The Amplify Functions documentation shows how Amplify defines a function resource and handler. I give the function one job and grant only the permissions required to send the notification. It does not need broad data access if it only sends mail.
The handler records a request ID, outcome, and provider error category. It does not log the message body or full email address. Those fields create unnecessary privacy exposure in long-lived logs.
Keep addresses and credentials out of the client
The owner address and provider configuration stay in environment-specific server settings. Secret values use Amplify's secret mechanism rather than plain environment values that can appear in build artifacts. The Amplify environment variables and secrets documentation explains that distinction.
I set the verified sender address under my control and use the visitor's address as reply-to after validation. Using user input as the sender can fail domain authentication checks and makes spoofing easier.
Return useful states to the visitor
The interface needs pending, accepted, and validation-error states. In this asynchronous workflow, accepted means the record was stored and the notification was queued; later delivery failures belong in server-side retries and monitoring. I disable duplicate submissions while the request is pending and restore the form when submission fails.
I avoid revealing provider internals. The visitor gets a safe next step, while the server retains a request ID that can be matched to sanitized logs.
Plan abuse and retry behavior
Retries must match the failure. A timeout may justify one bounded retry; an invalid recipient or rejected sender configuration needs intervention. Blind retries can send duplicate email, so I attach an idempotency key or record the submission state when the workflow requires stronger delivery guarantees.
For higher-volume forms I queue delivery and acknowledge receipt after the queue accepts the job. A small site may use a direct function call, but it still needs rate limits and alarms.
Test the complete path
I test valid input, invalid input, provider rejection, timeout, duplicate submission, and a request that bypasses the browser. I verify that production sends to the approved mailbox and staging uses a safe destination.
- No secret or recipient is shipped to browser code.
- Server validation has length limits.
- Logs omit message content.
- The visitor sees delivery failures.
- Alerts cover repeated send errors.
Need help with Amplify?
Terry Hunt Dev builds server-backed forms and integrations as part of its AWS development services. If your contact form loses messages or exposes delivery logic in the browser, use the contact form to request a review.