Website Forms Integration

Connect your website contact forms to Mailoo for secure message processing and automated responses

Quick Start

  1. 1. Create a project and integration in your Mailoo dashboard
  2. 2. Copy your project API key from the integration settings
  3. 3. Add the form HTML to your website
  4. 4. Configure the JavaScript handler
  5. 5. Test your form submission

Prerequisites

Mailoo Account Setup

You need an active Mailoo account with a project and email integration configured.

Website Access

Ability to edit HTML and JavaScript on your website.

Step 1: Get Your API Key

Navigate to your integration settings in the Mailoo dashboard to find your API key:

Dashboard → [Your Project] → [Your Integration] → Settings

Security: Keep your API key secure and never expose it in client-side code.

Step 2: Create Your HTML Form

Add this HTML form to your website. The form will capture user messages and send them to Mailoo:

<form id="mailoo-contact-form" class="space-y-4">
  <div>
    <label for="name" class="block text-sm font-medium">Name *</label>
    <input 
      type="text" 
      id="name" 
      name="name" 
      required 
      maxlength="100"
      class="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2"
    />
  </div>

  <div>
    <label for="email" class="block text-sm font-medium">Email *</label>
    <input 
      type="email" 
      id="email" 
      name="email" 
      required
      class="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2"
    />
  </div>

  <div>
    <label for="subject" class="block text-sm font-medium">Subject</label>
    <input 
      type="text" 
      id="subject" 
      name="subject" 
      maxlength="200"
      class="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2"
    />
  </div>

  <div>
    <label for="message" class="block text-sm font-medium">Message *</label>
    <textarea 
      id="message" 
      name="message" 
      required 
      maxlength="5000"
      rows="5"
      class="mt-1 block w-full rounded-md border border-gray-300 px-3 py-2"
    ></textarea>
  </div>

  <button 
    type="submit" 
    class="w-full rounded-md bg-blue-600 px-4 py-2 text-white hover:bg-blue-700"
  >
    Send Message
  </button>
</form>

<div id="mailoo-status" style="display: none;" class="mt-4 p-3 rounded-md">
  <span id="mailoo-status-text"></span>
</div>

Step 3: Add JavaScript Handler

Add this JavaScript code to handle form submissions securely:

<script>
document.addEventListener('DOMContentLoaded', function() {
  const form = document.getElementById('mailoo-contact-form');
  const statusDiv = document.getElementById('mailoo-status');
  const statusText = document.getElementById('mailoo-status-text');
  
  // Replace with your actual values (project UID and integration ID from dashboard)
  const MAILOO_API_URL = 'https://api.mailoo.app/api/v1';
  const PROJECT_UID = 'your-project-uid';
  const INTEGRATION_ID = 'your-form-integration-id';
  const API_KEY = 'your-api-key';

  form.addEventListener('submit', async function(e) {
    e.preventDefault();
    
    // Show loading state
    const submitBtn = form.querySelector('button[type="submit"]');
    const originalText = submitBtn.textContent;
    submitBtn.textContent = 'Sending...';
    submitBtn.disabled = true;
    
    try {
      // Collect form data (only email required; name optional; notification is built from template)
      const formData = {
        email: form.email.value.trim(),
        name: form.name.value.trim() || undefined,
        source: window.location.href,
        metadata: {
          timestamp: new Date().toISOString(),
          userAgent: navigator.userAgent,
          referrer: document.referrer
        }
      };
      
      // Submit to Mailoo (project UID and integration ID required)
      const response = await fetch(`${MAILOO_API_URL}/webhooks/forms/${PROJECT_UID}/${INTEGRATION_ID}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': API_KEY,
          'Origin': window.location.origin
        },
        body: JSON.stringify(formData)
      });
      
      const result = await response.json();
      
      if (response.ok && result.success) {
        // Success
        showStatus('success', 'Message sent successfully! We\'ll get back to you soon.');
        form.reset();
      } else if (response.status === 503 && result.message?.includes('not ready')) {
        showStatus('error', 'Subscription form is not ready. Please try again later or contact support.');
      } else {
        // API error
        throw new Error(result.message || 'Failed to send message');
      }
      
    } catch (error) {
      console.error('Form submission error:', error);
      showStatus('error', 'Failed to send message. Please try again or contact us directly.');
    } finally {
      // Reset button
      submitBtn.textContent = originalText;
      submitBtn.disabled = false;
    }
  });
  
  function showStatus(type, message) {
    statusText.textContent = message;
    statusDiv.className = `mt-4 p-3 rounded-md ${
      type === 'success' 
        ? 'bg-green-100 text-green-800 border border-green-200' 
        : 'bg-red-100 text-red-800 border border-red-200'
    }`;
    statusDiv.style.display = 'block';
    
    // Auto-hide after 5 seconds
    setTimeout(() => {
      statusDiv.style.display = 'none';
    }, 5000);
  }
});
</script>

Step 4: Configuration

Required Configuration

MAILOO_API_URLhttps://api.mailoo.app/api/v1 (production)
PROJECT_UIDYour project UID from dashboard
INTEGRATION_IDYour form integration ID (from dashboard when viewing the integration)
API_KEYYour integration API key

Optional Fields

You can add custom fields to collect additional information:

<!-- Add to your form -->
<div>
  <label for="company" class="block text-sm font-medium">Company</label>
  <input type="text" id="company" name="company" maxlength="100" />
</div>

<div>
  <label for="phone" class="block text-sm font-medium">Phone</label>
  <input type="tel" id="phone" name="phone" maxlength="20" />
</div>

<!-- Update JavaScript to include custom fields -->
metadata: {
  timestamp: new Date().toISOString(),
  userAgent: navigator.userAgent,
  referrer: document.referrer,
  company: form.company?.value || '',
  phone: form.phone?.value || ''
}

Security Best Practices

API Key Security

  • Never expose API keys in client-side JavaScript
  • Use environment variables in server-side implementations
  • Rotate API keys regularly
  • Restrict API key permissions to minimum required

CORS Configuration

Mailoo validates the Origin header to prevent unauthorized cross-origin requests. Configure allowed origins in your integration settings.

Rate Limiting

API endpoints are rate-limited to prevent abuse. Implement client-side throttling to avoid hitting rate limits during high traffic periods.

Input Validation

Always validate form inputs on both client and server side. Use appropriate maxlength attributes and sanitize user input before display.

Secure Server-Side Implementation

For better security, implement form processing on your server instead of client-side:

Node.js/Express Example

// server.js
const express = require('express');
const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.post('/contact', async (req, res) => {
  try {
    const { email, name } = req.body;

    // Validate required fields (only email is required)
    if (!email || !email.includes('@')) {
      return res.status(400).json({
        error: 'Valid email is required'
      });
    }
    
    // Submit to Mailoo (project UID and integration ID required)
    const response = await fetch(`${process.env.MAILOO_API_URL}/webhooks/forms/${process.env.PROJECT_UID}/${process.env.INTEGRATION_ID}`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-API-Key': process.env.MAILOO_API_KEY,
        'Origin': process.env.WEBSITE_ORIGIN
      },
      body: JSON.stringify({
        email: email.trim(),
        name: name?.trim() || undefined,
        source: req.headers.referer,
        metadata: {
          ip: req.ip,
          userAgent: req.headers['user-agent']
        }
      })
    });
    
    const result = await response.json();
    
    if (response.ok && result.success) {
      res.json({ success: true, message: 'Message sent successfully' });
    } else {
      throw new Error(result.message || 'Failed to send message');
    }
    
  } catch (error) {
    console.error('Contact form error:', error);
    res.status(500).json({ 
      error: 'Failed to send message' 
    });
  }
});

Environment Variables

# .env
MAILOO_API_URL=https://api.mailoo.app/api/v1
PROJECT_UID=proj_your_project_uid
INTEGRATION_ID=your_form_integration_id
MAILOO_API_KEY=mai_your_api_key_here
WEBSITE_ORIGIN=https://yourdomain.com

API Reference

Form Submission Endpoint

POST /api/v1/webhooks/forms/{projectUid}/{integrationId}

Submit form data from external websites. Both project UID and integration ID are required in the path.

Request Headers

HeaderRequiredDescription
Content-TypeYesapplication/json
X-API-KeyYesYour project API key
OriginRecommendedFor CORS validation

Request Body

{
  "name": "John Doe",                    // Required: 1-100 chars
  "email": "john@example.com",           // Required: valid email
  "subject": "Contact inquiry",          // Optional: 1-200 chars  
  "message": "Hello, I need help...",    // Required: 1-5000 chars
  "source": "https://yoursite.com/contact", // Optional: source URL
  "metadata": {                          // Optional: additional data
    "company": "Acme Corp",
    "phone": "+1234567890"
  }
}

Response Format

// Success (200)
{
  "success": true,
  "messageId": "msg_abc123def",
  "message": "Form submission processed successfully"
}

// Error (400/401/403/429)
{
  "error": "VALIDATION_ERROR",
  "message": "Request validation failed",
  "details": [
    {
      "field": "email",
      "message": "Invalid email format",
      "code": "invalid_string"
    }
  ]
}

Testing Your Integration

1. Test Form Submission

Fill out your form and submit it. Check your Mailoo dashboard for the new message in the integration inbox.

2. Check Integration Status

Use the status endpoint to verify your integration is active:

curl -X GET "https://api.mailoo.app/api/v1/webhooks/status/{integrationId}" \
  -H "X-API-Key: your-api-key"

3. Monitor Logs

Check your browser's developer console and network tab for any JavaScript errors or failed requests.

Troubleshooting

401 - Invalid API Key

Verify your API key is correct and the integration is active in your dashboard.

403 - Origin Not Allowed

Add your website domain to the allowed origins list in your integration settings.

429 - Rate Limited

Too many requests. Wait before retrying and consider implementing client-side throttling.

CORS Errors

Ensure your domain is whitelisted and the Origin header matches exactly (including protocol and port).

Advanced Usage

Multiple Forms

You can use the same integration for multiple forms on your website:

// Add form identifier to metadata
metadata: {
  formType: 'contact',        // or 'newsletter', 'support', etc.
  pageUrl: window.location.href,
  formId: 'contact-page-form'
}

Custom Success/Error Handling

// Custom success handler
if (response.ok && result.success) {
  // Redirect to thank you page
  window.location.href = '/thank-you';
  
  // Or show custom modal
  showCustomModal('Thank you for contacting us!');
  
  // Or trigger analytics event
  gtag('event', 'form_submit', {
    event_category: 'contact',
    event_label: 'success'
  });
}

Form Validation

// Client-side validation before submission (only email required; name optional)
function validateForm(formData) {
  const errors = [];

  if (!formData.email.trim() || !isValidEmail(formData.email)) {
    errors.push('Valid email is required');
  }

  return errors;
}

function isValidEmail(email) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}

Next Steps

Your form integration is ready! Consider setting up automated responses and email campaigns to engage with your form submissions.

Need Help?

If you run into issues or have questions about the integration, our support team is here to help.