电子邮箱格式问题

问题现象

邮箱校验请求类如下:

package com.test.vo.request;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;

/**
 * 邮箱校验请求类
 *
 * @author ageovb
 * @date 22/05/30 14:28
 */
@Data
@ApiModel(value = "邮箱校验请求")
public class EmailCheckReq {

    /**
     * 邮箱地址
     */
    @ApiModelProperty(value = "邮箱地址(最长 320 位)", required = true, example = "ageovb@test.com")
    @NotBlank
    @Email(message = "邮箱格式不合法")
    // 下面的长度校验可以不加,上面的注解会校验
    @Length(max = 320, message = "邮箱长度超限,最长 320 位")
    private String email;
}

提测后,测试找过来说设置 320 位邮箱报错,遂要来邮箱,格式如下:
{64位用户标识}@{251位字母}.com

问题分析

本地复现,错误信息如下:

2022-06-02 16:24:39,451 ERROR [http-nio-8081-exec-6] com.goodwe.sebu.web.starter.config.advice.BaseControllerAdvice: Validation Error:Validation failed for argument [0] in public com.goodwe.sebu.common.core.dto.response.Result<java.lang.String> com.goodwe.sebu.api.controller.UserController.checkEmailAndSendVerifyCode(com.goodwe.sebu.beans.vo.request.EmailCheckReq): [Field error in object 'emailCheckReq' on field 'email': rejected value [semsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsappte@semsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsa.ptestgo]; codes [Email.emailCheckReq.email,Email.email,Email.java.lang.String,Email]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [emailCheckReq.email,email]; arguments []; default message [email],[Ljavax.validation.constraints.Pattern$Flag;@7233d654,.*]; default message [user_email_illegal]] 
org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public com.goodwe.sebu.common.core.dto.response.Result<java.lang.String> com.goodwe.sebu.api.controller.UserController.checkEmailAndSendVerifyCode(com.goodwe.sebu.beans.vo.request.EmailCheckReq): [Field error in object 'emailCheckReq' on field 'email': rejected value [semsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsappte@semsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsapptestsemsa.ptestgo]; codes [Email.emailCheckReq.email,Email.email,Email.java.lang.String,Email]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [emailCheckReq.email,email]; arguments []; default message [email],[Ljavax.validation.constraints.Pattern$Flag;@7233d654,.*]; default message [user_email_illegal]] 
	at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:139)
	at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
	at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:170)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1063)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)

只是显示校验未通过,没有其他有效信息。

打开注解类,随便找一个成员变量,查看引用:
Email

发现校验方法:
EmailValidator

继续查看域名部分校验:
AbstractEmailValidator

域名字符串转换为 ASCII:
DomainNameUtil

继续调用内部转换方法:
java.net.IDN#toASCII(java.lang.String, int)

长度校验,若是长度超过 63,报错 The label in the input is too long(label 指域名两个点之间的字符):
java.net.IDN#toASCIIInternal

问题原因

邮箱域名长度超限导致校验失败。

解决方案

最长邮箱格式如下:

进阶

邮箱 @ 后面的为域名,而每一级域名长度限制不能超过 63,邮箱的总长度为 64(用户标识符) + 1(@) + 255(域名) = 320。

扩展阅读

posted @ 2022-06-04 10:56  ageovb  阅读(187)  评论(0编辑  收藏  举报