整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

10分钟搞定Java实现邮箱验证,坦率讲,别被他人割韭菜

率讲邮箱验证功能应该大多数人都使用过,比如:对用户账号密码进行找回,注册某网站以邮箱作为登录名激活账号.....等多个应用场景都需要我们通过邮件进行验证。此篇教程就是讲解如何用Java实现邮箱验证功能,10分钟就搞定了,简单得一匹!

在日常生活中,我们在一个网站中注册一个账户时,往往在提交个人信息后,网站还要求我们通过手机或邮件来验证,邮件的话大概会是下面这个样子的:

用户通过点击链接从而完成注册,然后才能登录。也许你会想,为什么要这么麻烦直接提交注册不就行了吗?这其中很大一部分原因是为了防止恶意注册。接下来让我们一起来使用最简单的JSP+Servlet的方式来完成一个通过邮箱验证注册的小案例吧。

准备工作

1、了解相关协议:动手实践之前,你最好对JSP、Servlet、SMTP协议POP3协议知识有所了解,如果对邮件收发过程完全不了解的话,可以花点时间仔细看一下如下图:

2、邮箱授权准备:在了解的上述内容之后,要实现这个案例,首先我们还得有两个邮箱账号,一个用来发送邮件,一个用来接收邮件。本案例使用QQ邮箱向163邮箱发送激活邮件,因此需要登录QQ邮箱,在设置->账户面板中开启POP3/SMTP服务,以允许我们通过第三方客户端发送邮件:进入发件人邮件空间 -> 设置 -> 账户 –> 开启(POP3/SMT)服务 注意:仅限QQ邮箱

图一

图二

图三

还要注意的是,登录以下服务: POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务时,需要用到授权码而不是QQ密码,授权码是用于登录第三方邮件客户端的专用密码。因此我们需要获得授权码,以在后面的程序中使用。

3、需要一个jar包:mail-1.4.7.jar

下载地址:https://mvnrepository.com/artifact/javax.mail/mail/1.4.7

Demo代码实现

具体步骤如下:

1. 首先创建一个web工程,并加入相关依赖包:

mail-1.4.7.jar 下载地址:https://mvnrepository.com/artifact/javax.mail/mail/1.4.7

2. 使用MySQL创建一张简单的用户表:t_user

create table t_user(
    id int(11) primary key auto_increment comment '用户id',
    userName varchar(100) not null comment '用户名',
    userEmail varchar(100) not null comment '用户邮箱',
    userPwd varchar(50) not null comment '用户密码',
    state int(1) not null default 0 comment '用户激活状态:0表示未激活,1表示激活',
    code varchar(255) not null comment '激活码'
);

PS:state字段(用来判断用户账号是否激活)和code字段(激活码)

3. 创建一个注册页面

使用JSP创建一个最简单的注册页面(过于简单,代码省略):

页面效果

4. 注册业务逻辑分析

1、用户填写相关信息,点击注册按钮

2、系统先将用户记录保存到数据库中,其中用户状态为未激活

3、系统发送一封邮件并通知用户去验证

4、用户登录邮箱并点击激活链接

5、系统将用户状态更改为已激活并通知用户注册成功

.................搞清楚了整个流程,实现起来应该就不难了...................

项目目录结构

通过JavaMail发送邮件,具体代码如下:

public class Constants {
    public static final int CODE_STATUS_EXPIRED = 400;//验证码过期或者没有点击发送验证码
    public static final String SEND_EMAIL_ACCOUNT = "2921272303@qq.com";//发件人邮箱账号
    public static final String SEND_EMAIL_CODE = "arnsutissvofzfdshj";//授权码(自己的)
}
public class UserServiceImpl implements UserService {
    private UserDao userDao = new UserDaoImpl();
    @Override
    public int addUser(Users users) {
        //注册生成唯一标识符
        String code = UUID.randomUUID().toString().replaceAll("-","");
        try {
            String newpwd =  MD5.getMD5(users.getUser_pwd()).toString();
            users.setUser_pwd(newpwd);
            users.setCode(code);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        int result = userDao.addUser(users);
        if(result > 0){//注册成功
           //获取发送邮件对象
           EmailUtil emailUtil = new EmailUtil(users.getUser_email(),code);
          //发起邮箱验证
           new Thread(emailUtil).start();
        }
        return result;
    }
}


package com.cnlm.utils;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.mail.*;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.security.GeneralSecurityException;
import java.util.Properties;
import java.util.UUID;
/**
 * Created with IntelliJ IDEA.
 * User: cnlm
 * Date: 2020/09/014 22:30
 * Description: JavaMail发送邮件工具类
 * QQ邮箱账户为发送方,首先需要进入QQ邮箱,找到左上方的设置,然后选择账户,找到POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务,开启pop3,获得授权码
 * Version: V1.0
 */
public class EmailUtil implements Runnable{
    private String receiveEmail;             // 收件人邮箱
    private String uuidCode;              // uuid唯一激活码
    public EmailUtil(String receiveEmail, String uuidCode) {
        this.receiveEmail = receiveEmail;
        this.uuidCode = uuidCode;  // 生成唯一随机码;
    }

    @Override
    public void run() {
         // 1.创建连接对象javax.mail.Session
        // 2.创建邮件对象 javax.mail.Message
        // 3.发送一封激活邮件
        String host = "smtp.qq.com"; // 指定发送邮件的主机smtp.qq.com(QQ)|smtp.163.com(网易)
        Properties properties = System.getProperties();// 获取系统属性
        properties.setProperty("mail.smtp.host", host);// 设置邮件服务器
        properties.setProperty("mail.smtp.auth", "true");// 打开认证
        //QQ邮箱需要下面这段代码,163邮箱不需要
        try {
            //QQ邮箱需要下面这段代码,163邮箱不需要
            MailSSLSocketFactory sf = new MailSSLSocketFactory();
            sf.setTrustAllHosts(true);
            properties.put("mail.smtp.ssl.enable", "true");
            properties.put("mail.smtp.ssl.socketFactory", sf);

            // 1.获取默认session对象
            Session session = Session.getDefaultInstance(properties, new Authenticator() {
                public PasswordAuthentication getPasswordAuthentication() {
                     // 发件人邮箱账号、授权码
                    return new PasswordAuthentication(Constant.SEND_EMAIL_ACCOUNT, Constant.SEND_EMAIL_CODE);
                }
            });
            // 2.创建邮件对象
            Message message = new MimeMessage(session);
            // 3.设置发件人
            message.setFrom(new InternetAddress(Constant.SEND_EMAIL_ACCOUNT));
           // 4.设置收件人
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(receiveEmail));
            // 5.设置邮件主题
            message.setSubject("账号激活");
            String content = "<html><head></head><body>" +
                    "<h1>这是一封激活邮件,激活请点击以下链接</h1><h3>" +
                    "<a href='http://localhost:8080/register/checkRegister.do?code="
                    + uuidCode + "'>http://localhost:8080/register/checkRegister.do?code=" + uuidCode
                    + "</a></h3></body></html>";
            message.setContent(content, "text/html;charset=UTF-8");
            // 7.发送邮件
            Transport.send(message);   // 阻塞方法
            System.out.println("邮件成功发送!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

PS:自己测试时需修改账号与授权码。

完成后,再有用户提交注册信息时,应该就能收到验证邮件了。用户点击链接后,我们要做的工作就是根据code(利用UUID生成)更改数据库中相应用户的状态,然后提示用户注册结果了。

最后总结:

简单介绍了如何使用JavaMail完成了一个带邮箱验证的注册案例,当然在实际开发中还有许多细节要注意,例如对用户提交信息的校验,密码进行加密等,此处的简单案例并未详尽处理这些细节。

学会了吗?谁在最需要的时候轻轻拍着我肩膀,谁在最快乐的时候愿意和我分享。我是一个包夜敲代码,想靠技术苟且的程序员。如果觉得有点用的话,请毫不留情地关注、点赞、转发。这将是我写出更多优质文章的最强动力!

码重置、两步验证、商业机密、私人对话……电子邮件是大多数生活和商业活动的中心,因此我们必须确保它是可信和真实的。

如果你在使用自己的域名邮箱,证明邮箱真实性的工作就会转移到你自己的头上。本指南旨在为你提供所需的相关信息和实践操作,以保证你域名邮箱的真实性,并减少你受上当受骗的风险。

该指南将介绍域名邮箱安全的三个主要组成部分:用于签名的DKIM、用于发件人验证的SPF和用于更严格执行其他两个部分的DMARC。请确保你对DNS有基本的了解,并有使用域名邮箱的经验。

1. SPF

SPF,全称“Sender Policy Framework”,即“发送方策略框架”,是最基本的电子邮件验证技术之一,是最简单、最常见的保护。通常,服务提供商会提供DNS记录内容,您只需在设置过程中简单地复制、粘贴即可。

在DNS解析中,SPF的记录类型为 TXT。基本格式如下:

"v=spf1 include:spf.httpsmail.com -all"

SPF的核心是一个IP地址列表,被授权从你的域名发送邮件。除此之外,还有其它几种不同的选项:

  • include: 执行递归查找包括来自不同主机名的所有IP;
  • ip4或ip6: 直接引用ip地址;
  • a, mx, ptr, exists等: 不经常使用,暂时忽略;
  • all: 用于捕获所有匹配的IP地址。默认情况下,这主要用于封锁所有内容,我们将在下面进行详细解释。

以上面的地址spf.httpsmail.com为例,该网址下的所有A类型的解析记录通过include:选项包含在SPF策略之中。

除了ip地址和包含的主机名之外,还有其它限定符来作为选项的前缀。

每个符号都会向邮件服务器推荐一个不同的策略,默认情况下,如果没有符号,它被视为等同于“+”,即“通过”。(其它限定符可见:https://datatracker.ietf.org/doc/html/rfc7208#section-4.6.2,主要包括4个:+、-、~和?等,好像“~”用得较多,为“soft-failure”,字面意思是“软失败”,接收但是会标记)

在上面的示例中,主要有两个机制选项:

  1. include:spf.httpsmail.com: 包含该网址下的所有ip,没有限定符,所以默认为“+”,即通过,接收邮件;
  2. -all: 带有限制符“-”,即拒绝。

SPF是一个非常简单的工具,提供了基本的电子邮件验证(“允许哪些IP可以发送我的电子邮件”)来进行基本的垃圾邮件过滤。即使只是单独设置SPF,也会对你的邮件成功投递有很大帮助。

2. DKIM

DKIM,全称“Domain Keys Identified Mail”,即“域名密钥识别邮件标准”,另一种安全机制,通过使用非对称密钥以加密的方式验证为你域名邮箱发送邮件的服务器是否有权这样做。配置DKIM后,接收你邮件的服务器可以在DNS中查找公钥,并验证邮件是否从你的域合法发送。

DKIM可防止IP易手或大型服务提供商在客户之间共享IP空间。如果你说“谷歌IP可以发送我的电子邮件”,是什么阻止其他人从你的域中欺骗电子邮件并从他们自己的谷歌帐户发送?由于这些IP是共享的,所以它仍将通过SPF检查,但不会通过DKIM。

DKIM有两个主要部分:一个是带有公钥的DNS记录,另一个是添加到每个已发送电子邮件中的header(头部信息),其中包含加密签名和有关如何查找上述DNS记录的详细信息。

DKIM的DNS解析记录就是一个普通的TXT记录类型,但目前主要以CNAME记录类型为主,通用格式为:

<selector>._domainkey.<domain>

“selector”通常由您的电子邮件服务提供商设置,并在您启用DKIM时提供给您。一些提供商,如Fastmail和Microsoft 365,甚至提供多个选择器供您设置。例如,对于谷歌来说,它只是一个“google”:

google._domainkey.example.com

DKIM头部信息被添加在你所发送的每一封邮件中,包含的内容很多,但最主要的是以下两个部分(其它可见https://datatracker.ietf.org/doc/html/rfc6376#section-3.5):

  1. d=<domain>: 列出邮件发送的域名以备验证;
  2. s=<selector>: 与DNS中的子域名匹配。

通过这两段元数据,收件人的服务器可以重建包含DKIM密钥的子域并解析它,并根据此密钥以验证DKIM签名和消息是否真实。

DKIM是一个比SPF强得多的检测垃圾邮件的方法,因为它涉及到实际的数学运算,而不仅仅是一个IP列表。即使你的域名邮箱只配置了SPF和DKIM也已经非常不错了,但还可以更进一步。

3. DMARC

DKIM仅在邮件中有头部信息时才适用。这意味着非法消息将不会有头部信息,因此不会发生DKIM验证。这导致DKIM验证是“中性”的,而不是“失败”,因为它被简单地忽略了。

添加DMARC策略使我们能够:

  • 强迫对声称来自我们域名的所有电子邮件执行SPF和DKIM检查;
  • 向接收服务器提示如何处理失败的检查;
  • 提供报告地址,以便我们可以从电子邮件提供商处接收有关这些检查的报告。

DMARC记录与其他两个记录的格式相同,而且非常简单。下面是一个非常基本的示例:

v=DMARC1; p=quarantine; adkim=s; aspf=s; rua=mailto: test@dmarc.postmarkapp.com;

  • p=quarantine: 为处理未通过身份验证检查的电子邮件所设置的全局策略,可以是none,quarantine或reject,即不采取措施、将验证失败的邮件标记为垃圾邮件和拒收验证失败的邮件。
  • adkim=s: 强制执行DKIM检查的策略,可以是r或s,r为relaxed,宽松;s为strict,严格。
  • aspf=s: 强制执行SPF检查的策略,选项同adkim。
  • rua=mailto: 接收综合报告的邮箱地址,一般会以周为单位。

DMARC是现代电子邮件安全性中最强大的一部分,它的报告可以令人难以置信地洞察哪些垃圾邮件伪装成你。如果您从本指南中得到了什么,我希望您应该花时间和精力制定严格的DMARC政策。

4. 加餐

如果你的域名不想发送邮件,可以通过以下设置来防止垃圾邮件以你的名义发送出去。

  • SPF设置:v=spf1 -all
  • DMARC设置记录:v=DMARC1; p=reject; adkim=s; aspf=s;

本文翻译自:Email Authenticity 101: DKIM, DMARC, and SPF,部分内容有改动,已获得原作者授权。

现代web开发中,表单是用户与网站互动的重要方式之一。HTML5为表单提交提供了强大的功能和丰富的输入类型,让收集和验证用户输入数据变得更加容易和安全。本文将详细介绍HTML5表单的各个方面,包括基本结构、输入类型、验证方法和提交过程。

基本结构

HTML表单由<form>标签定义,它可以包含输入字段、标签、按钮等元素。一个基本的表单结构如下所示:

<form action="/submit_form" method="post">
  <label for="name">姓名:</label>
  <input type="text" id="name" name="name" required>
  
  <label for="email">电子邮箱:</label>
  <input type="email" id="email" name="email" required>
  
  <input type="submit" value="提交">
</form>

在这个例子中,表单有两个输入字段:姓名和电子邮箱。每个输入字段都有一个<label>标签,这不仅有助于用户理解输入的内容,也有助于屏幕阅读器等辅助技术。<form>标签的action属性定义了数据提交到服务器的URL,method属性定义了提交数据的HTTP方法(通常是post或get)。

输入类型

HTML5提供了多种输入类型,以支持不同的数据格式和设备。

文本输入

<!-- 单行文本 -->
<input type="text" name="username" placeholder="请输入用户名" required>

<!-- 密码 -->
<input type="password" name="password" required minlength="8">

<!-- 邮箱 -->
<input type="email" name="email" required placeholder="example@domain.com">

<!-- 搜索框 -->
<input type="search" name="search" placeholder="搜索...">

数值输入

<!-- 数值 -->
<input type="number" name="age" min="18" max="100" step="1" required>

<!-- 滑动条 -->
<input type="range" name="volume" min="0" max="100" step="1">

<!-- 电话号码 -->
<input type="tel" name="phone" pattern="^\+?\d{0,13}" placeholder="+8613800000000">

日期和时间输入

<!-- 日期 -->
<input type="date" name="birthdate" required>

<!-- 时间 -->
<input type="time" name="appointmenttime">

<!-- 日期和时间 -->
<input type="datetime-local" name="appointmentdatetime">

选择输入

<!-- 复选框 -->
<label><input type="checkbox" name="interest" value="coding"> 编程</label>
<label><input type="checkbox" name="interest" value="music"> 音乐</label>

<!-- 单选按钮 -->
<label><input type="radio" name="gender" value="male" required> 男性</label>
<label><input type="radio" name="gender" value="female"> 女性</label>

<!-- 下拉选择 -->
<select name="country" required>
  <option value="china">中国</option>
  <option value="usa">美国</option>
</select>

特殊输入

<!-- 颜色选择器 -->
<input type="color" name="favcolor" value="#ff0000">

<!-- 文件上传 -->
<input type="file" name="resume" accept=".pdf,.docx" multiple>

验证方法

HTML5表单提供了内置的验证功能,可以在数据提交到服务器之前进行检查。

必填字段

<input type="text" name="username" required>

正则表达式

<input type="text" name="zipcode" pattern="\d{5}(-\d{4})?" title="请输入5位数的邮政编码">

数值范围

<input type="number" name="age" min="18" max="99">

长度限制

<input type="text" name="username" minlength="4" maxlength="8">

表单提交

当用户填写完表单并点击提交按钮时,浏览器会自动检查所有输入字段的有效性。如果所有字段都满足要求,表单数据将被发送到服务器。否则,浏览器会显示错误信息,并阻止表单提交。

<input type="submit" value="提交">

可以使用JavaScript来自定义验证或处理提交事件:

document.querySelector('form').addEventListener('submit', function(event) {
  // 检查表单数据
  if (!this.checkValidity()) {
    event.preventDefault(); // 阻止表单提交
    // 自定义错误处理
  }
  // 可以在这里添加额外的逻辑,比如发送数据到服务器的Ajax请求
});

完整例子

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>表单提交并显示JSON</title>
</head>
<body>

<!-- 表单定义 -->
<form id="myForm">
  <label for="name">姓名:</label>
  <input type="text" id="name" name="name">
  <br>

  <label for="email">电子邮件:</label>
  <input type="email" id="email" name="email">
  <br>

  <input type="button" value="提交" onclick="submitForm()">
</form>

<script>
// JavaScript函数,处理表单提交
function submitForm() {
  // 获取表单元素
  var form = document.getElementById('myForm');
  
  // 创建一个FormData对象
  var formData = new FormData(form);
  
  // 创建一个空对象来存储表单数据
  var formObject = {};
  
  // 将FormData转换为普通对象
  formData.forEach(function(value, key){
    formObject[key] = value;
  });
  
  // 将对象转换为JSON字符串
  var jsonString = JSON.stringify(formObject);
  
  // 弹出包含JSON字符串的对话框
  alert(jsonString);
  
  // 阻止表单的默认提交行为
  return false;
}
</script>

</body>
</html>

在这个例子中:

  1. 我们定义了一个包含姓名和电子邮件输入字段的表单,以及一个按钮,当点击按钮时会调用submitForm函数。
  2. 在submitForm函数中,我们首先获取表单元素并创建一个FormData对象。然后,我们遍历FormData对象,将表单数据复制到一个普通的JavaScript对象formObject中。
  3. 接着,我们使用JSON.stringify方法将formObject转换成JSON字符串。
  4. 最后,我们使用alert函数弹出一个包含JSON字符串的对话框。

注意,这个例子中我们使用了type="button"而不是type="submit",因为我们不希望表单有默认的提交行为。我们的JavaScript函数submitForm会处理所有的逻辑,并且通过返回false来阻止默认的表单提交。如果你想要使用type="submit",你需要在<form>标签上添加一个onsubmit="return submitForm()"属性来代替按钮上的onclick事件。

结论

HTML5的表单功能为开发者提供了强大的工具,以便创建功能丰富、用户友好且安全的网站。通过使用HTML5的输入类型和验证方法,可以确保用户输入的数据是有效的,同时提高用户体验。随着技术的不断进步,HTML5表单和相关API将继续发展,为前端工程师提供更多的可能性。