EmailJS简介
EmailJS是一个允许前端应用直接发送邮件的JavaScript库,无需后端服务器支持。它支持多种邮件服务提供商,包括Gmail、Outlook、QQ邮箱、阿里云企业邮箱等。
主要特点
- 无需后端:纯前端实现邮件发送
- 多服务商支持:支持主流邮件服务提供商
- 简单易用:几行代码即可实现邮件发送
- 免费额度:每月200封免费邮件
EmailJS账号注册与配置
1. 注册EmailJS账号
- 访问 EmailJS官网
- 点击 “Sign Up” 注册新账号
- 使用邮箱验证并完成注册
- 登录EmailJS Dashboard
2. 获取Public Key
- 登录EmailJS Dashboard
- 在左侧菜单中找到 “Account” → “General”
- 复制 “Public Key”(格式:
user_xxxxxxxxxxxxxxxx) - 保存此Public Key,后续代码中需要使用

邮件服务配置
1. 添加邮件服务
- 在EmailJS Dashboard中,点击 “Email Services”
- 点击 “Add New Service” 按钮
- 选择您要使用的邮件服务提供商
2. 配置Gmail服务(推荐)
步骤1:准备Gmail账号
- 确保Gmail账号已启用两步验证
- 在Google账号设置中生成应用专用密码
- 记录应用专用密码(16位字符)
步骤2:在EmailJS中配置
服务名称: My Gmail Service
Host: smtp.gmail.com
Port: 587
SSL: 不勾选(使用STARTTLS)
User: your-email@gmail.com
App Password: 您的应用专用密码
步骤3:测试连接
- 点击 “Test Service” 按钮
- 发送测试邮件验证配置
- 记录Service ID(格式:
service_xxxxxxxx)

3. 配置其他邮件服务
QQ邮箱配置
Host: smtp.qq.com
Port: 587
SSL: 不勾选
User: your-qq@qq.com
App Password: QQ邮箱授权码
163邮箱配置
Host: smtp.163.com
Port: 587
SSL: 不勾选
User: your-163@163.com
App Password: 163邮箱授权码
邮件模板创建
1. 创建邮件模板
- 在EmailJS Dashboard中,点击 “Email Templates”
- 点击 “Create New Template” 按钮
- 配置模板内容
2. 模板配置示例
模板内容
Subject: {{subject}} Dear {{to_name}}, Thank you for your interest in our product! We have received your message with the following details: - Name: {{from_name}} - Email: {{from_email}} - Company: {{company}} - Phone: {{phone}} - Message: {{message}} We will contact you soon with more information. Best regards, Our Team
模板变量说明
{{to_name}}- 收件人姓名{{from_name}}- 发件人姓名{{from_email}}- 发件人邮箱{{company}}- 公司名称{{phone}}- 电话号码{{message}}- 消息内容{{subject}}- 邮件主题
3. 保存模板
- 填写模板内容后,点击 “Save” 按钮
- 记录Template ID(格式:
template_xxxxxxxx)

前端代码实现
1. 安装EmailJS
使用npm安装
npm install @emailjs/browser
使用CDN引入
<script src="https://cdn.jsdelivr.net/npm/@emailjs/browser@3/dist/email.min.js"></script>
2. 基础实现
HTML结构
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>邮件发送示例</title>
</head>
<body>
<div class="container">
<h1>联系我们</h1>
<form id="contact-form">
<div class="form-group">
<label for="name">姓名 *</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="email">邮箱 *</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="company">公司</label>
<input type="text" id="company" name="company">
</div>
<div class="form-group">
<label for="phone">电话</label>
<input type="tel" id="phone" name="phone">
</div>
<div class="form-group">
<label for="message">消息 *</label>
<textarea id="message" name="message" rows="5" required></textarea>
</div>
<button type="submit">发送邮件</button>
</form>
<div id="message-container"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/@emailjs/browser@3/dist/email.min.js"></script>
<script src="script.js"></script>
</body>
</html>
JavaScript实现
// 初始化EmailJS
(function() {
emailjs.init("YOUR_PUBLIC_KEY_HERE");
})();
// 获取表单元素
const form = document.getElementById('contact-form');
const messageContainer = document.getElementById('message-container');
// 表单提交事件
form.addEventListener('submit', function(e) {
e.preventDefault();
// 显示加载状态
showMessage('正在发送邮件...', 'info');
// 获取表单数据
const formData = new FormData(form);
const templateParams = {
to_name: 'Admin',
from_name: formData.get('name'),
from_email: formData.get('email'),
company: formData.get('company') || 'Not provided',
phone: formData.get('phone') || 'Not provided',
message: formData.get('message'),
subject: 'New Contact Form Submission',
reply_to: formData.get('email')
};
// 发送邮件
emailjs.send('YOUR_SERVICE_ID_HERE', 'YOUR_TEMPLATE_ID_HERE', templateParams)
.then(function(response) {
console.log('SUCCESS!', response.status, response.text);
showMessage('邮件发送成功!我们会尽快回复您。', 'success');
form.reset();
}, function(error) {
console.log('FAILED...', error);
showMessage('邮件发送失败,请稍后重试或直接联系我们。', 'error');
});
});
// 显示消息函数
function showMessage(message, type) {
messageContainer.innerHTML = `<div class="message ${type}">${message}</div>`;
// 3秒后自动隐藏成功消息
if (type === 'success') {
setTimeout(() => {
messageContainer.innerHTML = '';
}, 3000);
}
}
3. Vue.js实现
安装依赖
npm install @emailjs/browser
Vue组件实现
<template>
<div class="contact-form">
<h2>联系我们</h2>
<form @submit.prevent="submitForm" class="form">
<div class="form-group" :class="{ 'error': fieldErrors.name }">
<label for="name">姓名 *</label>
<input
type="text"
id="name"
v-model="form.name"
@input="clearFieldError('name')"
required
>
<div v-if="fieldErrors.name" class="field-error">{{ fieldErrors.name }}</div>
</div>
<div class="form-group" :class="{ 'error': fieldErrors.email }">
<label for="email">邮箱 *</label>
<input
type="email"
id="email"
v-model="form.email"
@input="clearFieldError('email')"
required
>
<div v-if="fieldErrors.email" class="field-error">{{ fieldErrors.email }}</div>
</div>
<div class="form-group">
<label for="company">公司</label>
<input type="text" id="company" v-model="form.company">
</div>
<div class="form-group">
<label for="phone">电话</label>
<input type="tel" id="phone" v-model="form.phone">
</div>
<div class="form-group" :class="{ 'error': fieldErrors.message }">
<label for="message">消息 *</label>
<textarea
id="message"
v-model="form.message"
@input="clearFieldError('message')"
rows="5"
required
></textarea>
<div v-if="fieldErrors.message" class="field-error">{{ fieldErrors.message }}</div>
</div>
<button type="submit" :disabled="isSubmitting" class="submit-btn">
{{ isSubmitting ? '发送中...' : '发送邮件' }}
</button>
</form>
<div v-if="message" :class="['message', messageType]">
{{ message }}
</div>
</div>
</template>
<script>
import emailjs from '@emailjs/browser';
export default {
name: 'ContactForm',
data() {
return {
form: {
name: '',
email: '',
company: '',
phone: '',
message: ''
},
isSubmitting: false,
message: '',
messageType: 'success',
fieldErrors: {
name: '',
email: '',
message: ''
}
};
},
mounted() {
// 初始化EmailJS
emailjs.init('YOUR_PUBLIC_KEY_HERE');
},
methods: {
async submitForm() {
// 清除之前的消息和错误
this.message = '';
this.clearAllFieldErrors();
// 验证表单
if (!this.validateForm()) {
return;
}
this.isSubmitting = true;
try {
// 构建邮件参数
const templateParams = {
to_name: 'Admin',
from_name: this.form.name,
from_email: this.form.email,
company: this.form.company || 'Not provided',
phone: this.form.phone || 'Not provided',
message: this.form.message,
subject: 'New Contact Form Submission',
reply_to: this.form.email
};
// 发送邮件
const response = await emailjs.send(
'YOUR_SERVICE_ID_HERE',
'YOUR_TEMPLATE_ID_HERE',
templateParams
);
console.log('SUCCESS!', response.status, response.text);
this.message = '邮件发送成功!我们会尽快回复您。';
this.messageType = 'success';
this.resetForm();
} catch (error) {
console.error('FAILED...', error);
this.message = '邮件发送失败,请稍后重试或直接联系我们。';
this.messageType = 'error';
} finally {
this.isSubmitting = false;
}
},
validateForm() {
let isValid = true;
if (!this.form.name.trim()) {
this.fieldErrors.name = '请输入您的姓名';
isValid = false;
}
if (!this.form.email.trim()) {
this.fieldErrors.email = '请输入您的邮箱';
isValid = false;
} else if (!this.isValidEmail(this.form.email)) {
this.fieldErrors.email = '请输入有效的邮箱地址';
isValid = false;
}
if (!this.form.message.trim()) {
this.fieldErrors.message = '请输入您的消息';
isValid = false;
}
return isValid;
},
isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
},
clearFieldError(fieldName) {
if (this.fieldErrors[fieldName]) {
this.fieldErrors[fieldName] = '';
}
},
clearAllFieldErrors() {
Object.keys(this.fieldErrors).forEach(key => {
this.fieldErrors[key] = '';
});
},
resetForm() {
this.form = {
name: '',
email: '',
company: '',
phone: '',
message: ''
};
}
}
};
</script>
<style scoped>
.contact-form {
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input,
.form-group textarea {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
.form-group.error input,
.form-group.error textarea {
border-color: #e74c3c;
}
.field-error {
color: #e74c3c;
font-size: 14px;
margin-top: 5px;
}
.submit-btn {
background-color: #3498db;
color: white;
padding: 12px 24px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
.submit-btn:disabled {
background-color: #bdc3c7;
cursor: not-allowed;
}
.message {
padding: 10px;
margin-top: 20px;
border-radius: 4px;
}
.message.success {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.message.error {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
</style>
4. React实现
安装依赖
npm install @emailjs/browser
React组件实现
import React, { useState, useEffect } from 'react';
import emailjs from '@emailjs/browser';
const ContactForm = () => {
const [form, setForm] = useState({
name: '',
email: '',
company: '',
phone: '',
message: ''
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [message, setMessage] = useState('');
const [messageType, setMessageType] = useState('success');
const [fieldErrors, setFieldErrors] = useState({
name: '',
email: '',
message: ''
});
useEffect(() => {
// 初始化EmailJS
emailjs.init('YOUR_PUBLIC_KEY_HERE');
}, []);
const handleInputChange = (e) => {
const { name, value } = e.target;
setForm(prev => ({
...prev,
[name]: value
}));
// 清除字段错误
if (fieldErrors[name]) {
setFieldErrors(prev => ({
...prev,
[name]: ''
}));
}
};
const validateForm = () => {
const errors = {};
let isValid = true;
if (!form.name.trim()) {
errors.name = '请输入您的姓名';
isValid = false;
}
if (!form.email.trim()) {
errors.email = '请输入您的邮箱';
isValid = false;
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email)) {
errors.email = '请输入有效的邮箱地址';
isValid = false;
}
if (!form.message.trim()) {
errors.message = '请输入您的消息';
isValid = false;
}
setFieldErrors(errors);
return isValid;
};
const handleSubmit = async (e) => {
e.preventDefault();
setMessage('');
if (!validateForm()) {
return;
}
setIsSubmitting(true);
try {
const templateParams = {
to_name: 'Admin',
from_name: form.name,
from_email: form.email,
company: form.company || 'Not provided',
phone: form.phone || 'Not provided',
message: form.message,
subject: 'New Contact Form Submission',
reply_to: form.email
};
const response = await emailjs.send(
'YOUR_SERVICE_ID_HERE',
'YOUR_TEMPLATE_ID_HERE',
templateParams
);
console.log('SUCCESS!', response.status, response.text);
setMessage('邮件发送成功!我们会尽快回复您。');
setMessageType('success');
setForm({
name: '',
email: '',
company: '',
phone: '',
message: ''
});
} catch (error) {
console.error('FAILED...', error);
setMessage('邮件发送失败,请稍后重试或直接联系我们。');
setMessageType('error');
} finally {
setIsSubmitting(false);
}
};
return (
<div className="contact-form">
<h2>联系我们</h2>
<form onSubmit={handleSubmit} className="form">
<div className={`form-group ${fieldErrors.name ? 'error' : ''}`}>
<label htmlFor="name">姓名 *</label>
<input
type="text"
id="name"
name="name"
value={form.name}
onChange={handleInputChange}
required
/>
{fieldErrors.name && <div className="field-error">{fieldErrors.name}</div>}
</div>
<div className={`form-group ${fieldErrors.email ? 'error' : ''}`}>
<label htmlFor="email">邮箱 *</label>
<input
type="email"
id="email"
name="email"
value={form.email}
onChange={handleInputChange}
required
/>
{fieldErrors.email && <div className="field-error">{fieldErrors.email}</div>}
</div>
<div className="form-group">
<label htmlFor="company">公司</label>
<input
type="text"
id="company"
name="company"
value={form.company}
onChange={handleInputChange}
/>
</div>
<div className="form-group">
<label htmlFor="phone">电话</label>
<input
type="tel"
id="phone"
name="phone"
value={form.phone}
onChange={handleInputChange}
/>
</div>
<div className={`form-group ${fieldErrors.message ? 'error' : ''}`}>
<label htmlFor="message">消息 *</label>
<textarea
id="message"
name="message"
value={form.message}
onChange={handleInputChange}
rows="5"
required
/>
{fieldErrors.message && <div className="field-error">{fieldErrors.message}</div>}
</div>
<button type="submit" disabled={isSubmitting} className="submit-btn">
{isSubmitting ? '发送中...' : '发送邮件'}
</button>
</form>
{message && (
<div className={`message ${messageType}`}>
{message}
</div>
)}
</div>
);
};
export default ContactForm;
阿里云企业邮箱特殊配置
1. 阿里云企业邮箱多重验证配置
阿里云企业邮箱支持多重验证,需要特殊配置:
配置步骤:
- 启用多重验证:在阿里云企业邮箱管理后台启用多重验证功能
- 生成客户端授权密码:为第三方应用生成专用的授权密码
- 在EmailJS中配置:使用客户端授权密码进行认证
EmailJS配置:
服务名称: Aliyun Mail
Host: smtp.qiye.aliyun.com
Port: 465
SSL: 勾选 "My SMTP server supports SSL"
User: 邮件地址
App Password: 客户端授权密码(不是登录密码)
2. 获取客户端授权密码
在阿里云企业邮箱管理后台:
- 登录 阿里云企业邮箱管理后台
- 进入"邮箱设置" → “安全设置”
- 找到"多重验证"选项
- 启用多重验证功能
- 生成客户端授权密码
- 记录生成的授权密码
3. 配置注意事项
重要提醒:
- 必须勾选SSL:阿里云企业邮箱要求SSL加密连接
- 使用465端口:SSL加密的标准端口
- 使用授权密码:不是邮箱登录密码,而是专门生成的客户端授权密码
- 多重验证:确保在阿里云后台启用了多重验证功能
配置示例:
Host: smtp.qiye.aliyun.com
Port: 465
SSL: ✅ 勾选 "My SMTP server supports SSL"
User: 邮箱地址
App Password: 您的客户端授权密码
4. 阿里云邮箱端口说明
根据阿里云官方文档:
- 25端口:被ECS封禁 ❌
- 465端口:SSL加密端口 ✅
- 587端口:STARTTLS端口 ✅
- 80端口:非加密端口 ✅
推荐配置:
方案1(推荐):
Host: smtp.qiye.aliyun.com
Port: 465
SSL: 勾选
方案2:
Host: smtp.qiye.aliyun.com
Port: 587
SSL: 不勾选(使用STARTTLS)
常见问题解决
1. 连接超时问题
问题:412 SMTP: Connection timeout
解决方案:
- 检查网络连接
- 尝试不同的端口(587, 465, 25)
- 检查防火墙设置
- 使用VPN测试
- 确认使用正确的SMTP服务器地址
2. 认证失败问题
问题:412 SMTP: Invalid login: 535 Authentication failure
解决方案:
- 检查用户名和密码是否正确
- 确认使用应用专用密码而不是登录密码
- 检查邮箱服务是否已开启
- 重新生成授权密码
- 对于阿里云邮箱,确保使用客户端授权密码
3. 邮件发送失败
问题:邮件发送后没有收到
解决方案:
- 检查垃圾邮件文件夹
- 确认收件人邮箱地址正确
- 检查邮件模板配置
- 查看EmailJS发送日志
4. 跨域问题
问题:CORS错误
解决方案:
- 在EmailJS Dashboard中添加域名到允许列表
- 检查nuxt.config.js中的域名配置
- 使用HTTPS协议
5. 阿里云邮箱特殊问题
问题:阿里云邮箱连接失败
解决方案:
- 确认启用了多重验证
- 使用客户端授权密码
- 检查SSL配置
- 尝试不同的端口组合
最佳实践建议
1. 安全配置
环境变量管理
// 使用环境变量存储敏感信息
const emailjsConfig = {
publicKey: process.env.EMAILJS_PUBLIC_KEY,
serviceId: process.env.EMAILJS_SERVICE_ID,
templateId: process.env.EMAILJS_TEMPLATE_ID
};
输入验证
// 验证邮箱格式
function isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
// 防止XSS攻击
function sanitizeInput(input) {
return input.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
}
2. 错误处理
完善的错误处理
try {
const response = await emailjs.send(serviceId, templateId, templateParams);
console.log('SUCCESS!', response.status, response.text);
showMessage('邮件发送成功!', 'success');
} catch (error) {
console.error('FAILED...', error);
// 根据错误类型显示不同消息
if (error.status === 400) {
showMessage('请求参数错误,请检查表单内容。', 'error');
} else if (error.status === 401) {
showMessage('认证失败,请稍后重试。', 'error');
} else if (error.status === 403) {
showMessage('服务暂时不可用,请稍后重试。', 'error');
} else {
showMessage('邮件发送失败,请稍后重试或直接联系我们。', 'error');
}
}
3. 用户体验优化
加载状态
// 显示加载状态
const [isSubmitting, setIsSubmitting] = useState(false);
// 提交按钮状态
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? '发送中...' : '发送邮件'}
</button>
表单验证
// 实时验证
const handleInputChange = (e) => {
const { name, value } = e.target;
setForm(prev => ({ ...prev, [name]: value }));
// 清除字段错误
if (fieldErrors[name]) {
setFieldErrors(prev => ({ ...prev, [name]: '' }));
}
};
4. 性能优化
懒加载
// 动态导入EmailJS
const sendEmail = async () => {
const emailjs = await import('@emailjs/browser');
// 使用emailjs发送邮件
};
防抖处理
// 防抖提交
const debouncedSubmit = useCallback(
debounce((formData) => {
// 发送邮件逻辑
}, 300),
[]
);
5. 邮件服务商选择建议
开发测试阶段
- Gmail:配置简单,稳定性好
- QQ邮箱:国内访问稳定
生产环境
- 企业邮箱:专业形象,品牌一致性
- Gmail:全球稳定性好
- 阿里云企业邮箱:国内企业首选
总结
EmailJS是一个强大的前端邮件发送解决方案,通过本文的详细指南,您可以:
- 快速上手:从注册到配置,完整流程指导
- 多框架支持:原生JavaScript、Vue.js、React等实现方式
- 多服务商支持:Gmail、QQ邮箱、阿里云企业邮箱等配置方法
- 问题解决:常见问题的诊断和解决方案
- 最佳实践:安全、性能、用户体验的优化建议
通过合理配置和使用EmailJS,您可以在前端应用中轻松实现邮件发送功能,提升用户体验和业务效率。无论是简单的联系表单还是复杂的邮件通知系统,EmailJS都能提供稳定可靠的解决方案。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




