Skip to main content

Overview

The Plugin Agency contact form requires several environment variables for email delivery and spam protection via Google reCAPTCHA. This guide covers all required and optional variables, plus setup instructions.

Required Variables

Critical - The contact form will not work without these variables configured:

EMAIL_USER

Description: Email account username for sending contact form submissions.
.env
EMAIL_USER=[email protected]
Usage: Authenticates with the SMTP server to send emails.

EMAIL_PASS

Description: Email account password or app-specific password.
.env
EMAIL_PASS=your-app-password-here
Security: Never commit .env files to Git. Use .env.local for local development and configure variables in Vercel for production.
For Gmail: Use an App Password, not your regular Gmail password.

VITE_RECAPTCHA_SITE_KEY

Description: Google reCAPTCHA v2 site key (public key).
.env
VITE_RECAPTCHA_SITE_KEY=6LdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Variables prefixed with VITE_ are exposed to the browser. This is intentional for the site key (it’s public).
Usage: Renders the reCAPTCHA widget on the contact form.

RECAPTCHA_SECRET_KEY

Description: Google reCAPTCHA v2 secret key (private key).
.env
RECAPTCHA_SECRET_KEY=6LdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Security: This key must remain secret. Do NOT prefix it with VITE_ or it will be exposed to the browser.
Usage: Server-side validation of reCAPTCHA responses.

Optional Variables

EMAIL_TO

Description: Comma-separated list of recipient email addresses. Default: If not set, emails are sent to: Code Reference:
api/send-email.js
to: process.env.EMAIL_TO 
  ? process.env.EMAIL_TO.split(',').map(e => e.trim()) 
  : ['[email protected]', '[email protected]']

EMAIL_CC

Description: CC recipients for contact form emails (currently commented out).
.env
Code Reference:
api/send-email.js
// If uncommented:
if (process.env.EMAIL_CC) { 
  mailOptions.cc = process.env.EMAIL_CC; 
}

Setup Guides

Gmail App Password Setup

Google requires app-specific passwords for third-party applications.
1

Enable 2-Factor Authentication

  1. Go to Google Account Security
  2. Enable 2-Step Verification if not already enabled
  3. Complete the setup process
2

Generate App Password

  1. Go to App Passwords
  2. Select App: “Mail”
  3. Select Device: “Other (Custom name)”
  4. Enter name: “Plugin Agency Contact Form”
  5. Click Generate
3

Copy Password

Google will display a 16-character password:
abcd efgh ijkl mnop
Copy this password (without spaces) to your .env file:
.env
EMAIL_PASS=abcdefghijklmnop
4

Test Configuration

Run your development server and test the contact form:
npm run dev
Submit a test message to verify email delivery.
Security Note: App passwords bypass 2FA. Treat them like your main password. If compromised, revoke them immediately in your Google Account settings.

reCAPTCHA Key Setup

Protect your contact form from spam with Google reCAPTCHA v2.
1

Create reCAPTCHA Site

  1. Go to Google reCAPTCHA Admin
  2. Sign in with your Google account
  3. Fill out the registration form:
    • Label: “Plugin Agency Contact Form”
    • reCAPTCHA type: reCAPTCHA v2 → “I’m not a robot” Checkbox
    • Domains:
      • localhost (for development)
      • plugin.uy (your production domain)
      • *.vercel.app (for Vercel preview deployments)
  4. Accept the Terms of Service
  5. Click Submit
2

Copy Keys

Google will display two keys:Site Key (Public)
6LdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Secret Key (Private)
6LdYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
3

Add to Environment

Add both keys to your .env file:
.env
VITE_RECAPTCHA_SITE_KEY=6LdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
RECAPTCHA_SECRET_KEY=6LdYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
The site key has the VITE_ prefix (exposed to browser). The secret key does NOT (server-side only).
4

Configure in Vercel

For production deployment:
  1. Go to Vercel project → SettingsEnvironment Variables
  2. Add both keys
  3. Set environment: Production, Preview, and Development
  4. Redeploy the site
Client-side (Contact.jsx):
import ReCAPTCHA from 'react-google-recaptcha'

<ReCAPTCHA
  sitekey={import.meta.env.VITE_RECAPTCHA_SITE_KEY}
  onChange={(token) => setCaptchaToken(token)}
/>
Server-side (api/send-email.js):
const verifyUrl = `https://www.google.com/recaptcha/api/siteverify?secret=${process.env.RECAPTCHA_SECRET_KEY}&response=${captchaToken}`

const captchaRes = await fetch(verifyUrl, { method: 'POST' })
const captchaData = await captchaRes.json()

if (!captchaData.success) {
  return res.status(400).json({ error: 'Captcha inválido' })
}

Email Configuration Details

The contact form uses Nodemailer with custom SMTP settings.

SMTP Configuration

api/send-email.js
const transporter = nodemailer.createTransport({
  host: 'mail.plugin.uy',
  port: 465,
  secure: true, // true for port 465, false for other ports
  auth: {
    user: process.env.EMAIL_USER,
    pass: process.env.EMAIL_PASS,
  },
})
If you want to use Gmail’s SMTP server instead of a custom domain:
const transporter = nodemailer.createTransport({
  service: 'gmail',
  auth: {
    user: process.env.EMAIL_USER,
    pass: process.env.EMAIL_PASS,
  },
})
Or with explicit settings:
const transporter = nodemailer.createTransport({
  host: 'smtp.gmail.com',
  port: 587,
  secure: false, // Use TLS
  auth: {
    user: process.env.EMAIL_USER,
    pass: process.env.EMAIL_PASS,
  },
})

Email Template

api/send-email.js
const mailOptions = {
  from: `"Plugin Contacto" <${process.env.EMAIL_USER}>`,
  replyTo: email, // User's email from form
  to: process.env.EMAIL_TO ? process.env.EMAIL_TO.split(',').map(e => e.trim()) : ['[email protected]', '[email protected]'],
  subject: `Nuevo mensaje de contacto de: ${nombre} ${apellido}`,
  text: `
    Has recibido un nuevo mensaje desde el formulario de contacto:
    
    Nombre: ${nombre} ${apellido}
    Email: ${email}
    Teléfono: ${telefono}
    
    Mensaje:
    ${message}
  `,
  html: `
    <h3>Nuevo mensaje de contacto</h3>
    <p><strong>De:</strong> ${nombre} ${apellido}</p>
    <p><strong>Email:</strong> ${email}</p>
    <p><strong>Teléfono:</strong> ${telefono}</p>
    <p><strong>Mensaje:</strong><br/>${message}</p>
  `,
}

Security Best Practices

Never Commit Secrets

Add .env* to .gitignore. Never commit API keys, passwords, or tokens to version control.

Use App Passwords

For Gmail, always use app-specific passwords instead of your main account password.

Rotate Keys Regularly

Periodically regenerate reCAPTCHA keys and email passwords, especially after team changes.

Limit Domain Access

Configure reCAPTCHA to only work on your specific domains to prevent unauthorized use.

Vercel Configuration

For production deployment, add variables in Vercel:
1

Open Project Settings

Navigate to your project in Vercel → SettingsEnvironment Variables
2

Add Each Variable

For each variable:
  1. Enter Key: e.g., EMAIL_USER
  2. Enter Value: e.g., [email protected]
  3. Select environments: Production, Preview, Development
  4. Click Save
3

Redeploy

After adding all variables:
  1. Go to Deployments tab
  2. Click ··· on latest deployment
  3. Select Redeploy
Or push a new commit to trigger automatic deployment.
Environment variables are encrypted at rest and in transit by Vercel. They are only decrypted during build and runtime.

Troubleshooting

Check:
  • EMAIL_USER and EMAIL_PASS are correctly set
  • App password is valid (not regular Gmail password)
  • SMTP host and port are correct
  • No firewall blocking port 465/587
Test locally:
npm run dev
Check console for error messages.
Check:
  • Both VITE_RECAPTCHA_SITE_KEY and RECAPTCHA_SECRET_KEY are set
  • Keys match the reCAPTCHA version (v2)
  • Domain is registered in reCAPTCHA admin
  • localhost is added for local development
Test in browser console:
console.log(import.meta.env.VITE_RECAPTCHA_SITE_KEY)
Should output the site key (not undefined).
Check:
  • Variables are set for correct environment (Production/Preview)
  • Site has been redeployed after adding variables
  • Variable names match exactly (case-sensitive)
  • No typos in variable values
View build logs: Go to Vercel deployment → Building → View logs to see if variables are detected.
Rule:
  • VITE_ prefix = exposed to browser (public)
  • No prefix = server-side only (secret)
Example:
  • VITE_RECAPTCHA_SITE_KEY - Safe to expose (public key)
  • VITE_RECAPTCHA_SECRET_KEY - NEVER expose (private key)
  • RECAPTCHA_SECRET_KEY - Correct (server-side only)

Example .env File

.env
# Email Configuration
EMAIL_USER=[email protected]
EMAIL_PASS=abcdefghijklmnop

# Optional: Override default recipients
EMAIL_TO=[email protected],[email protected]

# reCAPTCHA Keys
VITE_RECAPTCHA_SITE_KEY=6LdXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
RECAPTCHA_SECRET_KEY=6LdYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
Never commit this file! Add to .gitignore:
.env
.env.local
.env*.local

Next Steps

Deployment Guide

Deploy to Vercel with environment variables

Contact Component

Learn how the contact form component works

Build docs developers (and LLMs) love