暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

前端使用EmailJS实现邮件发送功能完整指南

原创 浮游 2025-09-10
160

EmailJS简介

EmailJS是一个允许前端应用直接发送邮件的JavaScript库,无需后端服务器支持。它支持多种邮件服务提供商,包括Gmail、Outlook、QQ邮箱、阿里云企业邮箱等。

主要特点

  • 无需后端:纯前端实现邮件发送
  • 多服务商支持:支持主流邮件服务提供商
  • 简单易用:几行代码即可实现邮件发送
  • 免费额度:每月200封免费邮件

EmailJS账号注册与配置

1. 注册EmailJS账号

  1. 访问 EmailJS官网
  2. 点击 “Sign Up” 注册新账号
  3. 使用邮箱验证并完成注册
  4. 登录EmailJS Dashboard

2. 获取Public Key

  1. 登录EmailJS Dashboard
  2. 在左侧菜单中找到 “Account” → “General”
  3. 复制 “Public Key”(格式:user_xxxxxxxxxxxxxxxx
  4. 保存此Public Key,后续代码中需要使用

image.png

邮件服务配置

1. 添加邮件服务

  1. 在EmailJS Dashboard中,点击 “Email Services”
  2. 点击 “Add New Service” 按钮
  3. 选择您要使用的邮件服务提供商

2. 配置Gmail服务(推荐)

步骤1:准备Gmail账号

  1. 确保Gmail账号已启用两步验证
  2. 在Google账号设置中生成应用专用密码
  3. 记录应用专用密码(16位字符)

步骤2:在EmailJS中配置

服务名称: My Gmail Service
Host: smtp.gmail.com
Port: 587
SSL: 不勾选(使用STARTTLS)
User: your-email@gmail.com
App Password: 您的应用专用密码

步骤3:测试连接

  1. 点击 “Test Service” 按钮
  2. 发送测试邮件验证配置
  3. 记录Service ID(格式:service_xxxxxxxx

image.png

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. 创建邮件模板

  1. 在EmailJS Dashboard中,点击 “Email Templates”
  2. 点击 “Create New Template” 按钮
  3. 配置模板内容

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. 保存模板

  1. 填写模板内容后,点击 “Save” 按钮
  2. 记录Template ID(格式:template_xxxxxxxx

image.png

前端代码实现

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. 阿里云企业邮箱多重验证配置

阿里云企业邮箱支持多重验证,需要特殊配置:

配置步骤:

  1. 启用多重验证:在阿里云企业邮箱管理后台启用多重验证功能
  2. 生成客户端授权密码:为第三方应用生成专用的授权密码
  3. 在EmailJS中配置:使用客户端授权密码进行认证

EmailJS配置:

服务名称: Aliyun Mail
Host: smtp.qiye.aliyun.com
Port: 465
SSL: 勾选 "My SMTP server supports SSL"
User: 邮件地址
App Password: 客户端授权密码(不是登录密码)

2. 获取客户端授权密码

在阿里云企业邮箱管理后台:

  1. 登录 阿里云企业邮箱管理后台
  2. 进入"邮箱设置" → “安全设置”
  3. 找到"多重验证"选项
  4. 启用多重验证功能
  5. 生成客户端授权密码
  6. 记录生成的授权密码

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是一个强大的前端邮件发送解决方案,通过本文的详细指南,您可以:

  1. 快速上手:从注册到配置,完整流程指导
  2. 多框架支持:原生JavaScript、Vue.js、React等实现方式
  3. 多服务商支持:Gmail、QQ邮箱、阿里云企业邮箱等配置方法
  4. 问题解决:常见问题的诊断和解决方案
  5. 最佳实践:安全、性能、用户体验的优化建议

通过合理配置和使用EmailJS,您可以在前端应用中轻松实现邮件发送功能,提升用户体验和业务效率。无论是简单的联系表单还是复杂的邮件通知系统,EmailJS都能提供稳定可靠的解决方案。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论