Skip to content

Migrating from EmailJS

This guide helps you migrate your email forms from EmailJS to mailiam, providing better performance, security, and developer experience.

FeatureEmailJSmailiam
ConfigurationDashboard onlyDeclarative YAML config
SecurityClient-side keysServer-side API keys
Rate LimitingBasicAdvanced with IP-based rules
Spam ProtectionMinimalComprehensive built-in
Email ForwardingNot supportedFull email forwarding
Custom TemplatesLimitedComplete HTML/CSS support
PricingPer emailSaaS model with higher limits
Developer UXManual setupCLI-based workflow
  • Better Security: No exposed API keys in frontend
  • Improved Performance: Faster form processing
  • Enhanced Spam Protection: Built-in honeypot and filtering
  • Email Forwarding: Route emails to multiple destinations
  • Version Control: Configuration as code
  • Team Collaboration: Shared configuration files
  1. List all forms using EmailJS
  2. Document email templates you’re using
  3. Note recipient addresses for each form
  4. Identify custom styling or features
  5. Review current usage volume

Export your EmailJS configuration:

  1. Log into EmailJS dashboard
  2. Note your Service ID and Template IDs
  3. Document email recipients
  4. Save template content and styling
  5. Record any custom JavaScript integration
Terminal window
npm install -g mailiam
Terminal window
mailiam signup
# Follow the prompts to create your account and get API key
Terminal window
mkdir my-website && cd my-website
mailiam init

Add your domain to the configuration:

mailiam.config.yaml
project:
name: "My Website"
slug: "my-website"
domains:
example.com:
forms:
contact:
name: "Contact Form"
replies: true
replyTo: "hello@example.com"
acknowledgment:
enabled: true
template: "contact-acknowledgment"
subject: "Thanks for contacting us!"
forwarding:
"hello@example.com": "team@company.com"
"support@example.com": "support@company.com"
templates:
contact-acknowledgment:
type: "acknowledgment"
subject: "Thanks for contacting us!"
text: |
Hi {{ form.name }},
Thanks for reaching out! We received your message and will get back to you soon.
Best regards,
The Team
Terminal window
mailiam push
Terminal window
mailiam domains setup example.com
# Follow the instructions to add DNS records

Before (EmailJS):

<form id="contact-form">
<input type="text" name="user_name" placeholder="Name" required>
<input type="email" name="user_email" placeholder="Email" required>
<textarea name="message" placeholder="Message" required></textarea>
<button type="submit">Send</button>
</form>
<script type="text/javascript">
(function() {
emailjs.init("YOUR_USER_ID");
})();
document.getElementById('contact-form').addEventListener('submit', function(event) {
event.preventDefault();
emailjs.sendForm('service_abc123', 'template_xyz789', this)
.then(function() {
alert('SUCCESS!');
}, function(error) {
alert('FAILED...', error);
});
});
</script>

After (mailiam):

<form action="https://api.mailiam.dev/example.com/contact" method="POST">
<input type="text" name="name" placeholder="Name" required>
<input type="email" name="email" placeholder="Email" required>
<textarea name="message" placeholder="Message" required></textarea>
<!-- Spam protection honeypot -->
<input type="text" name="_mailiam_honeypot" style="display:none" tabindex="-1" autocomplete="off">
<button type="submit">Send</button>
</form>

For dynamic form handling:

mailiam with JavaScript:

<form id="contact-form">
<input type="text" name="name" placeholder="Name" required>
<input type="email" name="email" placeholder="Email" required>
<textarea name="message" placeholder="Message" required></textarea>
<input type="text" name="_mailiam_honeypot" style="display:none" tabindex="-1" autocomplete="off">
<button type="submit">Send</button>
<div id="form-status"></div>
</form>
<script>
document.getElementById('contact-form').addEventListener('submit', async function(event) {
event.preventDefault();
const formData = new FormData(this);
const statusDiv = document.getElementById('form-status');
try {
const response = await fetch('https://api.mailiam.dev/example.com/contact', {
method: 'POST',
body: formData
});
if (response.ok) {
statusDiv.innerHTML = '<p style="color: green;">Message sent successfully!</p>';
this.reset();
} else {
statusDiv.innerHTML = '<p style="color: red;">Failed to send message. Please try again.</p>';
}
} catch (error) {
statusDiv.innerHTML = '<p style="color: red;">Network error. Please try again.</p>';
}
});
</script>

Map EmailJS field names to mailiam conventions:

EmailJSmailiamNotes
user_namenameStandardized field name
user_emailemailMust be valid email format
messagemessageMain message content
subjectsubjectOptional subject line
companycompanyCompany/organization
phonephonePhone number

mailiam automatically validates:

  • Email addresses must be valid format
  • Required fields must be present
  • Honeypot fields must be empty
  • Message content for spam patterns

EmailJS template example:

Subject: New contact from {{user_name}}
Name: {{user_name}}
Email: {{user_email}}
Message: {{message}}

Equivalent mailiam template:

# In mailiam.config.yaml
templates:
contact-form:
type: "form"
subject: "New contact from {{ form.name }}"
text: |
Name: {{ form.name }}
Email: {{ form.email }}
Message: {{ form.message }}
html: |
<h2>New Contact Form Submission</h2>
<p><strong>Name:</strong> {{ form.name }}</p>
<p><strong>Email:</strong> {{ form.email }}</p>
<p><strong>Message:</strong></p>
<p>{{ form.message }}</p>
# Reference in form configuration
domains:
example.com:
forms:
contact:
name: "Contact Form"
template: "contact-form"

mailiam templates support additional features:

templates:
enhanced-contact:
type: "form"
subject: "New contact from {{ form.name }} - {{ form.subject || 'General Inquiry' }}"
variables:
company_name: "My Company"
support_email: "support@company.com"
html: |
<div style="font-family: Arial, sans-serif; max-width: 600px;">
<h1 style="color: #333;">{{ company_name }}</h1>
<h2>New Contact Form Submission</h2>
<table style="border-collapse: collapse; width: 100%;">
<tr>
<td style="border: 1px solid #ddd; padding: 8px;"><strong>Name</strong></td>
<td style="border: 1px solid #ddd; padding: 8px;">{{ form.name }}</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 8px;"><strong>Email</strong></td>
<td style="border: 1px solid #ddd; padding: 8px;">{{ form.email }}</td>
</tr>
{% if form.company %}
<tr>
<td style="border: 1px solid #ddd; padding: 8px;"><strong>Company</strong></td>
<td style="border: 1px solid #ddd; padding: 8px;">{{ form.company }}</td>
</tr>
{% endif %}
</table>
<h3>Message:</h3>
<div style="background: #f9f9f9; padding: 15px; border-left: 4px solid #007cba;">
{{ form.message | nl2br }}
</div>
<hr>
<p style="color: #666; font-size: 12px;">
Submitted: {{ timestamp | date: '%Y-%m-%d %H:%M:%S' }}<br>
IP Address: {{ ip }}<br>
Form: {{ domain }}/contact
</p>
</div>

EmailJS React Component:

import emailjs from 'emailjs-com';
function ContactForm() {
const sendEmail = (e) => {
e.preventDefault();
emailjs.sendForm('service_id', 'template_id', e.target, 'user_id')
.then((result) => {
console.log(result.text);
}, (error) => {
console.log(error.text);
});
};
return (
<form onSubmit={sendEmail}>
<input type="text" name="user_name" />
<input type="email" name="user_email" />
<textarea name="message" />
<button type="submit">Send</button>
</form>
);
}

mailiam React Component:

import { useState } from 'react';
function ContactForm() {
const [status, setStatus] = useState('');
const [loading, setLoading] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
const formData = new FormData(e.target);
try {
const response = await fetch('https://api.mailiam.dev/example.com/contact', {
method: 'POST',
body: formData
});
if (response.ok) {
setStatus('success');
e.target.reset();
} else {
setStatus('error');
}
} catch (error) {
setStatus('error');
} finally {
setLoading(false);
}
};
return (
<form onSubmit={handleSubmit}>
<input type="text" name="name" placeholder="Name" required />
<input type="email" name="email" placeholder="Email" required />
<textarea name="message" placeholder="Message" required />
{/* Honeypot for spam protection */}
<input type="text" name="_mailiam_honeypot" style={{ display: 'none' }} tabIndex="-1" autoComplete="off" />
<button type="submit" disabled={loading}>
{loading ? 'Sending...' : 'Send'}
</button>
{status === 'success' && <p style={{color: 'green'}}>Message sent successfully!</p>}
{status === 'error' && <p style={{color: 'red'}}>Failed to send message. Please try again.</p>}
</form>
);
}

EmailJS Vue Component:

<template>
<form @submit="sendEmail">
<input type="text" name="user_name" v-model="form.name">
<input type="email" name="user_email" v-model="form.email">
<textarea name="message" v-model="form.message"></textarea>
<button type="submit">Send</button>
</form>
</template>
<script>
import emailjs from 'emailjs-com';
export default {
data() {
return {
form: { name: '', email: '', message: '' }
};
},
methods: {
sendEmail(e) {
e.preventDefault();
emailjs.sendForm('service_id', 'template_id', e.target, 'user_id');
}
}
};
</script>

mailiam Vue Component:

<template>
<form @submit="handleSubmit">
<input type="text" name="name" v-model="form.name" placeholder="Name" required>
<input type="email" name="email" v-model="form.email" placeholder="Email" required>
<textarea name="message" v-model="form.message" placeholder="Message" required></textarea>
<!-- Honeypot -->
<input type="text" name="_mailiam_honeypot" style="display: none" tabindex="-1" autocomplete="off">
<button type="submit" :disabled="loading">
{{ loading ? 'Sending...' : 'Send' }}
</button>
<p v-if="status === 'success'" style="color: green;">Message sent successfully!</p>
<p v-if="status === 'error'" style="color: red;">Failed to send message. Please try again.</p>
</form>
</template>
<script>
export default {
data() {
return {
form: { name: '', email: '', message: '' },
status: '',
loading: false
};
},
methods: {
async handleSubmit(e) {
e.preventDefault();
this.loading = true;
const formData = new FormData(e.target);
try {
const response = await fetch('https://api.mailiam.dev/example.com/contact', {
method: 'POST',
body: formData
});
if (response.ok) {
this.status = 'success';
this.form = { name: '', email: '', message: '' };
} else {
this.status = 'error';
}
} catch (error) {
this.status = 'error';
} finally {
this.loading = false;
}
}
}
};
</script>

mailiam provides better spam protection than EmailJS:

domains:
example.com:
forms:
contact:
name: "Contact Form"
# Built-in spam protection
spam_protection:
level: "normal"
honeypot: "_mailiam_honeypot"
rate_limit: 10
content_filter: true

Configure appropriate rate limits:

forms:
contact:
rateLimit: 10 # 10 submissions per hour per IP
newsletter:
rateLimit: 2 # 2 signups per hour per IP
Terminal window
# Test with curl
curl -X POST https://api.mailiam.dev/example.com/contact \
-F "name=Test User" \
-F "email=test@example.com" \
-F "message=Testing migration from EmailJS"
Terminal window
# Test honeypot (should be blocked)
curl -X POST https://api.mailiam.dev/example.com/contact \
-F "name=Spam Bot" \
-F "email=spam@example.com" \
-F "message=Spam content" \
-F "_mailiam_honeypot=bot-content"
Terminal window
# Test rate limiting (should be blocked after limit)
for i in {1..15}; do
curl -X POST https://api.mailiam.dev/example.com/contact \
-F "name=Test $i" \
-F "email=test$i@example.com" \
-F "message=Rate limit test $i"
done
Terminal window
# Send test email
mailiam test send your@email.com

Ensure your domain is properly configured:

Terminal window
mailiam domains verify example.com
mailiam domains status

Track form submissions and performance:

Terminal window
# View recent submissions
mailiam instant list
# Generate analytics report
mailiam analytics --last-30d

Once migration is complete:

  1. Remove EmailJS JavaScript from your site
  2. Delete unused EmailJS templates
  3. Cancel EmailJS subscription
  4. Update documentation

Ensure your team knows how to:

  • Update form configurations
  • Deploy changes with mailiam push
  • Monitor form submissions
  • Troubleshoot issues

Problem: Forms not sending emails

Solution:

Terminal window
# Check domain verification
mailiam domains verify example.com
# Test form endpoint
curl -X POST https://api.mailiam.dev/example.com/contact \
-F "name=Test" \
-F "email=test@example.com" \
-F "message=Test"
# Check configuration
mailiam test config

Problem: Browser blocking requests

Solution: mailiam automatically handles CORS for verified domains. Ensure your domain is verified:

Terminal window
mailiam domains status

Problem: Email templates not rendering variables

Solution: Check template syntax and variable names:

templates:
contact:
type: "form"
subject: "New contact from {{ form.name }}" # Use form.name, not user_name
text: "Email: {{ form.email }}" # Use form.email, not user_email
  • mailiam account created and CLI installed
  • Domain configured and DNS records added
  • Forms migrated and tested
  • Templates converted and verified
  • Spam protection configured
  • Rate limiting set up appropriately
  • Team trained on new workflow
  • EmailJS code removed from site
  • EmailJS subscription cancelled

Migrating from EmailJS to mailiam provides better security, performance, and developer experience. Take advantage of mailiam’s advanced features like email forwarding, comprehensive spam protection, and configuration as code.