← All guides

๐Ÿ“ฌ Mail Setup โ€” Enquiries Form

Wire a website "Get in touch" form to a Google Sheet and two emails โ€” no backend server, no secrets in the repo.

Browser validation Google Sheet row Notify you Acknowledge visitor

โœฆ Sample prompt

Paste this into your coding agent (Claude Code, Cursor, etc.) to have it build the whole flow against your existing site. It tells the agent to keep your current UI untouched and only add the form's functionality.

Full prompt
Update the existing "Get in Touch" section of my website. The section currently contains these fields: * Name * Email * Message * Send Message button When the user clicks "Send Message", implement the following complete workflow: 1. Validate the form * Name is required. * Email is required and must be a valid email address. * Message is required. * Show clear validation messages if any required field is missing or invalid. * Prevent submission if validation fails. * Prevent duplicate submissions while the request is being processed. 2. Save the enquiry to Google Sheets When the form is successfully submitted, add a new row to my Google Sheet. Store the following information: * Submission Date/Time * Name * Email * Message Use a secure integration such as Google Apps Script Web App or another appropriate server-side/API approach. Do not expose Google Sheet credentials, API keys, or other sensitive configuration in the frontend code. 3. Send an email notification to me After successfully saving the enquiry to Google Sheets, send an email notification to my configured email address. The notification email should contain: * Name * Email * Message * Submission date/time Use a professional email subject such as: New Contact Form Message from [Name] 4. Send an acknowledgement email to the visitor After the enquiry is successfully processed, automatically send an acknowledgement email to the email address provided by the visitor. The acknowledgement should be professional and friendly and confirm that their message has been received. Example content: "Hi [Name], Thank you for getting in touch. I have received your message and will get back to you as soon as possible. Regards, Shaji" 5. Success and error handling After everything is successfully completed: * Show a clear success message on the website, such as: "Thank you! Your message has been sent successfully. I'll get back to you soon." * Clear the form fields. * Do not reload the page unless required. If the submission fails: * Show a user-friendly error message. * Do not show technical errors, API credentials, or internal implementation details to the visitor. * Make sure the user can try submitting again. 6. Security and reliability Implement the integration securely and professionally: * Keep API keys, email credentials, Google credentials, and configuration values on the server side. * Add basic spam protection/rate limiting where appropriate. * Sanitize and validate all submitted data. * Prevent malicious HTML/script content from being stored or included in emails. * Use HTTPS. * Ensure CORS is configured correctly if a Google Apps Script Web App or external API is used. 7. Important implementation requirement First inspect the existing website structure and technology stack. Do not redesign or change the existing UI, styling, layout, colors, fonts, animations, or overall look and feel. Only modify the functionality required for the Get in Touch form. Provide the complete implementation, including: 1. Frontend form changes 2. Backend/API or Google Apps Script integration 3. Google Sheet configuration 4. Email notification configuration 5. Visitor acknowledgement email 6. Required environment variables/configuration 7. Step-by-step setup instructions 8. Testing instructions Make the implementation production-ready and explain exactly where I need to enter my Google Sheet ID, email address, and any other required configuration.
๐Ÿ’ก Replace Shaji in step 4 with your own name before sending. The sections below are the reference build this prompt produces.

i How it works

The "Get in touch" form does four things when a visitor clicks Send message:

  1. Validates name / email / message in the browser (blocks invalid or duplicate submits).
  2. Saves the enquiry as a new row in a Google Sheet.
  3. Emails you a notification (New Contact Form Message from <Name>).
  4. Emails the visitor a friendly acknowledgement.

Steps 2โ€“4 run inside a Google Apps Script web app. The website only knows that web app's URL. Your Google account, the Sheet, and email sending never touch the frontend or the repo.

Browser form โ”€โ”€POST JSONโ”€โ”€โ–ถ Apps Script web app โ”€โ”€โ–ถ Google Sheet โ”‚ โ”œโ”€โ”€โ–ถ MailApp: notify you โ””โ”€โ”€โ–ถ MailApp: acknowledge visitor

โœŽ What you need to provide

ValueWhere it goesExample
Google Sheet IDApps Script → Script Property SHEET_ID1AbCdEf... (from the Sheet URL)
Your notification emailApps Script → Script Property NOTIFY_EMAILshajikombanfrancis@hotmail.com
Web app URLwebsite .env → VITE_CONTACT_ENDPOINThttps://script.google.com/macros/s/AKfy.../exec

Everything else has sensible defaults.

1 Part 1 โ€” Google Sheet

  1. Create a Google Sheet, e.g. "Portfolio Enquiries".
  2. From the URL, copy the ID (the long string between /d/ and /edit):
    https://docs.google.com/spreadsheets/d/<SHEET_ID>/edit
  3. You do not need to add headers โ€” the script creates a tab named Enquiries with headers Submitted At | Name | Email | Message | Page on the first submission.

2 Part 2 โ€” Apps Script web app

  1. Go to script.google.com → New project.
  2. Delete the sample Code.gs contents and paste the contents of google-apps-script/Code.gs from the repo.
  3. (Optional but recommended) Click the gear → Project Settings → tick "Show appsscript.json manifest file", then replace it with google-apps-script/appsscript.json. Set timeZone to your preference (default Asia/Bahrain).
  4. Project Settings → Script Properties → Add script property โ€” add:
PropertyValue
SHEET_IDyour Sheet ID from Part 1
NOTIFY_EMAILthe address that should receive enquiries

Optional properties

PropertyDefaultPurpose
SHEET_NAMEEnquiriesworksheet / tab name
OWNER_NAMEShajisignature inside the acknowledgement email
ALLOWED_ORIGIN(unset)e.g. https://yourdomain.com โ€” rejects posts whose origin field doesn't start with this
MAX_PER_EMAIL_PER_DAY5per-address daily cap
ACK_FROM_ADDRESS(unset)send the visitor acknowledgement from this address, e.g. no-reply@shajikfrancis.com โ€” requires the "Send mail as" setup in Part 2b
ACK_FROM_NAMEOWNER_NAMEdisplay name on the acknowledgement, e.g. Shaji Komban Francis
ACK_REPLY_TO(unset)Reply-To on the acknowledgement, e.g. info@shajikfrancis.com

2b Send the acknowledgement from a custom address (optional)

Google Apps Script can only send "from" an address that the script-running Google account has registered as a verified sender. It cannot spoof an arbitrary address.

  1. Sign in to the Gmail account that runs this script (the account you deploy with โ€” executeAs: USER_DEPLOYING).
  2. Gmail → Settings โš™ → See all settings → Accounts and Import → "Send mail as" → Add another email address.
  3. Enter Shaji Komban Francis and no-reply@shajikfrancis.com, leave "Treat as an alias" ticked, Next.
  4. Google sends a confirmation code to no-reply@shajikfrancis.com. You must be able to receive mail there โ€” set up a catch-all or a real mailbox/alias on the shajikfrancis.com domain, get the code, and confirm.
    (If the domain is Google Workspace, an admin can instead add it as a send-as alias without a code.)
  5. Once it shows as verified, add the Script Properties:
    PropertyValue
    ACK_FROM_ADDRESSno-reply@shajikfrancis.com
    ACK_FROM_NAMEShaji Komban Francis
    ACK_REPLY_TOinfo@shajikfrancis.com (optional โ€” where replies should land)
  6. Redeploy a new version (the manifest gained the gmail.settings.basic scope, so Google will ask you to re-authorize once).
๐Ÿ“ฎ Deliverability: keep an SPF record for shajikfrancis.com that includes include:_spf.google.com, and โ€” recommended โ€” set up DKIM. Without SPF alignment some providers may put the acknowledgement in spam. If ACK_FROM_ADDRESS is not a verified sender, the script logs a warning and sends from the account's default address instead (the enquiry and your notification are unaffected).

3 Deploy & backend check

  1. Deploy → New deployment → type Web app:
    • Description: contact form v1
    • Execute as: Me
    • Who has access: Anyone
    • Click Deploy.
  2. Google will prompt for authorization (Sheets + send email). Approve it. If you see "Google hasn't verified this app", click Advanced → Go to <project> (unsafe) โ€” this is your own script.
  3. Copy the Web app URL (ends in /exec).

Quick backend check

Open the /exec URL in a browser. You should see:

{"ok":true,"service":"contact","ts":"2026-..."}

4 Part 3 โ€” Point the website at it

  1. In the project root, copy the example env file:
    cp .env.example .env
  2. Edit .env and set the URL from Part 2:
    VITE_CONTACT_ENDPOINT=https://script.google.com/macros/s/AKfy.../exec
  3. Rebuild / redeploy the site:
    npm run build
โš ๏ธ Vite inlines VITE_* values at build time. After changing .env you must rebuild (and redeploy). On Vercel/Netlify, set VITE_CONTACT_ENDPOINT as an environment variable in the project settings and trigger a redeploy.

.env is git-ignored. Only .env.example is committed.

โ†ป Updating the script later

Edit the code in the Apps Script editor, then Deploy → Manage deployments → edit (pencil) → Version: New version → Deploy. The /exec URL stays the same, so no website change is needed. Creating a new deployment instead would give a new URL and require updating .env.

โœ“ Testing

1. Validation (no backend needed)

Run npm run dev and open the Contact section:

ActionExpected
Click Send message with all fields emptyThree inline errors; nothing sent
Enter name + not-an-email + message, submit"Please enter a valid email address."
Fix a fieldIts error clears as you type
Submit valid data with no VITE_CONTACT_ENDPOINT setFriendly error + mailto: link; can retry

2. End-to-end (after Parts 1โ€“3)

  1. Fill the form with a real email you can check and submit.
  2. Button shows "Sendingโ€ฆ" and is disabled (no double submit).
  3. On success: green "Thank you! Your message has been sent successfullyโ€ฆ" and the fields clear. The page does not reload.
  4. Within a few seconds:
    • a new row appears in the Google Sheet,
    • your NOTIFY_EMAIL inbox gets "New Contact Form Message from <Name>" (reply-to is set to the visitor),
    • the visitor address gets the acknowledgement email โ€” check its From: no-reply@shajikfrancis.com if ACK_FROM_ADDRESS is set and verified, otherwise the script account's default address (see Executions for a "not a verified Send mail as alias" warning if you expected the former).
  5. Submit again immediately → "You've just sent a message. Please wait a minuteโ€ฆ" (client + server rate limit).

3. Security checks

TestExpected
Put <script>alert(1)</script> in the messageStored/emailed as plain text, tags stripped; no HTML runs
Start the message with =SUM(1+1)Sheet cell stores it as literal text (leading '), not a formula
Inspect the built JS / network tabOnly the /exec URL is visible โ€” no Sheet ID, no email credentials
Submit from an unlisted origin (if ALLOWED_ORIGIN set){"ok":false,"error":"forbidden"} → generic error on site

Apps Script logs

Apps Script editor → Executions (left sidebar) shows every doPost run, its status, and console.error output for failures.

! Limits & notes