From 06b0e11a8f26debf80c6cdb6aaceaaa1543807b2 Mon Sep 17 00:00:00 2001
From: sasha-astiadi
+
With over 5 years of experience in the tech industry, John has worked on various projects ranging from startups to enterprise applications. He believes in writing clean, maintainable code and is always eager to learn new technologies. diff --git a/docs/gmail-setup-guide.md b/docs/gmail-setup-guide.md new file mode 100644 index 0000000..ba06ab1 --- /dev/null +++ b/docs/gmail-setup-guide.md @@ -0,0 +1,134 @@ +# Gmail Contact Form Setup Guide + +This guide will help you configure your contact form to send emails to your company Gmail inbox. + +## Prerequisites + +- A Gmail account for your company +- Access to Google Account settings +- Basic understanding of environment variables + +## Step 1: Enable 2-Factor Authentication + +1. Go to [Google Account Settings](https://myaccount.google.com/) +2. Navigate to **Security** → **2-Step Verification** +3. Follow the prompts to enable 2FA if not already enabled +4. **Note**: App passwords require 2FA to be enabled + +## Step 2: Generate Gmail App Password + +1. Go to [Google Account Settings](https://myaccount.google.com/) +2. Navigate to **Security** → **2-Step Verification** → **App passwords** +3. Select **Mail** as the app and **Other** as the device +4. Enter "OurWorld Contact Form" as the device name +5. Click **Generate** +6. **Important**: Copy the 16-character app password immediately (you won't see it again) + +## Step 3: Configure Environment Variables + +1. Open the `.env.local` file in your project root +2. Replace the placeholder values with your actual credentials: + +```env +# Your Gmail address (the one that will send emails) +GMAIL_USER=your-company-email@gmail.com + +# The 16-character app password you generated (no spaces) +GMAIL_APP_PASSWORD=abcdabcdabcdabcd + +# Email address where contact form submissions will be sent +COMPANY_EMAIL=info@ourworld.tf +``` + +## Step 4: Security Considerations + +### Environment Variables +- **Never commit `.env.local` to version control** +- The `.env.local` file is already in `.gitignore` +- Use different environment variables for production deployment + +### Production Deployment +For production (Vercel, Netlify, etc.), add these environment variables in your hosting platform's dashboard: +- `GMAIL_USER` +- `GMAIL_APP_PASSWORD` +- `COMPANY_EMAIL` + +## Step 5: Testing the Setup + +1. Start your development server: + ```bash + npm run dev + ``` + +2. Navigate to `/contact` page +3. Fill out and submit the contact form +4. Check your Gmail inbox for the contact form submission + +## Troubleshooting + +### Common Issues + +**"Authentication failed" error:** +- Verify 2FA is enabled on your Google account +- Double-check the app password (no spaces, 16 characters) +- Ensure you're using the app password, not your regular Gmail password + +**"Invalid credentials" error:** +- Verify the `GMAIL_USER` email address is correct +- Check that the app password is correctly copied + +**Emails not being received:** +- Check your spam/junk folder +- Verify the `COMPANY_EMAIL` address is correct +- Test with a different recipient email + +**"Module not found" error:** +- Ensure nodemailer is installed: `npm install nodemailer @types/nodemailer` + +### Email Format + +The contact form sends emails with: +- **Subject**: "New Contact Form Submission from [First Name] [Last Name]" +- **From**: Your Gmail address (GMAIL_USER) +- **To**: Company email address (COMPANY_EMAIL) +- **Content**: Formatted HTML and plain text versions + +## Security Best Practices + +1. **Use App Passwords**: Never use your main Gmail password +2. **Limit Access**: Only share credentials with necessary team members +3. **Regular Rotation**: Consider rotating app passwords periodically +4. **Monitor Usage**: Check Gmail's security activity regularly +5. **Environment Separation**: Use different credentials for development/production + +## Alternative Solutions + +If you prefer not to use Gmail directly, consider these alternatives: + +1. **EmailJS**: Client-side email service +2. **Formspree**: Form handling service +3. **SendGrid**: Professional email API +4. **Mailgun**: Email delivery service +5. **Resend**: Modern email API + +## Support + +If you encounter issues: +1. Check the browser console for error messages +2. Review the server logs for API errors +3. Verify all environment variables are set correctly +4. Test with a simple email first + +## File Structure + +``` +project/ +├── .env.local # Environment variables (not in git) +├── src/app/api/contact/ # API route for form submission +├── src/components/ContactHero.tsx # Contact form component +└── docs/gmail-setup-guide.md # This guide +``` + +--- + +**Important**: Keep your app password secure and never share it publicly. If compromised, revoke it immediately in your Google Account settings and generate a new one. diff --git a/next.config.js b/next.config.js index 767719f..963eedf 100644 --- a/next.config.js +++ b/next.config.js @@ -1,4 +1,13 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {} +const nextConfig = { + output: 'export', + trailingSlash: true, + images: { + unoptimized: true, + }, + // Note: API routes in src/app/api/ will not work with static export + // The contact form API route will need to be handled separately + // Consider using a serverless function or external service for form handling +}; -module.exports = nextConfig +module.exports = nextConfig; diff --git a/package-lock.json b/package-lock.json index 954df6b..2fbb80e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,10 +13,12 @@ "@tailwindcss/forms": "^0.5.3", "@tailwindcss/postcss": "^4.1.7", "@types/node": "^20.10.8", + "@types/nodemailer": "^6.4.17", "@types/react": "^18.2.47", "@types/react-dom": "^18.2.18", "clsx": "^2.1.0", "next": "^14.0.4", + "nodemailer": "^7.0.5", "react": "^18.2.0", "react-dom": "^18.2.0", "tailwindcss": "^4.1.7", @@ -1350,6 +1352,15 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/nodemailer": { + "version": "6.4.17", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.17.tgz", + "integrity": "sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/prop-types": { "version": "15.7.11", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", @@ -3994,6 +4005,15 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/nodemailer": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.5.tgz", + "integrity": "sha512-nsrh2lO3j4GkLLXoeEksAMgAOqxOv6QumNRVQTJwKH4nuiww6iC2y7GyANs9kRAxCexg3+lTWM3PZ91iLlVjfg==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", diff --git a/package.json b/package.json index a44da93..11ab988 100644 --- a/package.json +++ b/package.json @@ -17,10 +17,12 @@ "@tailwindcss/forms": "^0.5.3", "@tailwindcss/postcss": "^4.1.7", "@types/node": "^20.10.8", + "@types/nodemailer": "^6.4.17", "@types/react": "^18.2.47", "@types/react-dom": "^18.2.18", "clsx": "^2.1.0", "next": "^14.0.4", + "nodemailer": "^7.0.5", "react": "^18.2.0", "react-dom": "^18.2.0", "tailwindcss": "^4.1.7", diff --git a/src/app/api/contact/route.ts b/src/app/api/contact/route.ts new file mode 100644 index 0000000..c8fb7b1 --- /dev/null +++ b/src/app/api/contact/route.ts @@ -0,0 +1,80 @@ +import { NextRequest, NextResponse } from 'next/server' +import nodemailer from 'nodemailer' + +export async function POST(request: NextRequest) { + try { + const body = await request.json() + const { firstName, lastName, email, phoneNumber, message } = body + + // Validate required fields + if (!firstName || !lastName || !email || !message) { + return NextResponse.json( + { error: 'Missing required fields' }, + { status: 400 } + ) + } + + // Create transporter using Gmail SMTP + const transporter = nodemailer.createTransport({ + service: 'gmail', + auth: { + user: process.env.GMAIL_USER, + pass: process.env.GMAIL_APP_PASSWORD, + }, + }) + + // Email content + const mailOptions = { + from: process.env.GMAIL_USER, + to: process.env.COMPANY_EMAIL || process.env.GMAIL_USER, + subject: `New Contact Form Submission from ${firstName} ${lastName}`, + html: ` +
Name: ${firstName} ${lastName}
+Email: ${email}
+ ${phoneNumber ? `Phone: ${phoneNumber}
` : ''} +${message}
+This email was sent from the OurWorld contact form on ${new Date().toLocaleString()}.
+