Email Verifier Util

public class VerifyEmailUtil {
	
	private static Logger logger = LoggerFactory.getLogger(VerifyEmailUtil.class);

	private static final String EMAIL_REGEX = new StringBuffer().append("^([a-zA-Z0-9_.+-]").append("|").append("[")
			.append("`").append("~").append("!").append("#").append("$").append("%").append("^").append("&").append("*").append("=")
			.append(",").append(".").append("<").append(">").append(";").append(":").append("'").append("\"").append("")
			.append("\\[").append("\\]").append("\\(").append("\\)").append("\\{").append("\\}").append("\\|").append("\\").append("\\/")
			.append("]").append(")+").append("@(([a-zA-Z0-9-])+.)+").append("([a-zA-Z0-9]{2,4})+$").toString();
			
	//"^([a-zA-Z0-9_.+-]|[*`~!#%&=,.<>;:'"?$^\[\]\(\)\{\}\|\\\/])+@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$";
	
	private static final String EMAIL_DOMAIN_REGEX = "@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?";
	
	private static Record[] records = null;
	
	private static List<String> domainWhiteList = null;
	
	static {
		domainWhiteList = Arrays.asList(ConfigProperties.getInstance().getValue("domain_whitelist").split(","));
	}
	
	/**
	 * 语法检验
	 * @param email
	 * @return
	 */
	public static boolean isValidFormat(String email) {
		if (StringUtils.isEmpty(email)) {
			return false;
		}
		if (Pattern.matches(EMAIL_REGEX, email)) {
			// 语法校验通过
			return true;
		} else {
			// 语法校验未通过
			return false;
		}
	}
	
	/**
	 * 域名语法校验
	 * @param domain
	 * @return
	 */
	public static boolean isValidDomainFormat(String domain) {
		if (StringUtils.isEmpty(domain)) {
			return false;
		}
		if (Pattern.matches(EMAIL_DOMAIN_REGEX, domain)) {
			// 语法校验通过
			return true;
		} else {
			// 语法校验未通过
			return false;
		}
	}
	
	/**
	 * 是否存在白名单种
	 * @param domain
	 * @return
	 */
	public static boolean isInDomainWhiteList(String domain) {
		if (domainWhiteList.contains(domain)) {
			return true;// 存在域名白名单中,直接跳过
		} 
		return false;
	}
	
	/**
	 * MX记录分析
	 * @param email
	 * @return
	 */
	public static boolean isValidDomain(String email) {
		String domain = email.split(StringConstant.AT)[1].toLowerCase();
		Lookup lookup = null;
		try {
			lookup = new Lookup(domain, Type.MX);
		} catch (TextParseException e) {
			logger.error(e.getMessage(), e);
		}
		lookup.run();
		if (lookup.getResult() != Lookup.SUCCESSFUL) {
			// 找不到MX记录
			logger.info(domain + "'s mx not exists.");
			return false;
		} else {
			// MX记录存在
			logger.info(domain + "'s mx exists.");
			records = lookup.getAnswers();
			/*if (!ArrayUtils.isEmpty(records)) {
				for (Record record : records) {
					logger.info(email + "'s MX record: " + record.getAdditionalName().toString());
				}
			}*/
			return true;
		}
	}
	
	/**
	 * SMTP
	 * @param email
	 * @return
	 */
	public static boolean isValidUser(String email) {
		final String SENDER_EMAIL = "no-reply@qq.com";
		final String SENDER_EMAIL_DOMAIN = SENDER_EMAIL.split(StringConstant.AT)[1];
		if (!ArrayUtils.isEmpty(records)) {
			int count = 0;// 计数器
			SMTPClient client = new SMTPClient(); 
			for (Record record : records) {
				String hostname =  record.getAdditionalName().toString();
				try {
					client.connect(hostname);// 连接到接收邮箱地址的邮箱服务器  
				} catch (Exception e) {
					count++;
					if (count >= records.length) {
						// 如果由MX得到的result服务器都连接不上,则判定email无效
						return false;
					}
				}
				if (!SMTPReply.isPositiveCompletion(client.getReplyCode())) {
					// 服务器通信失败
					try {
						client.disconnect();
						continue;
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
				} else {
					logger.info("MX record about " + hostname + "exists. ");
					logger.info("Connection succeeded to " + hostname + " SMTP.");
					logger.info(client.getReplyString());
					try {
						client.login(SENDER_EMAIL_DOMAIN);
						logger.info("> HELO " + hostname);
						logger.info(client.getReplyString());
						client.setSender(SENDER_EMAIL);
						if (client.getReplyCode() != 250) {
							client.disconnect();
							continue;
						}
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
					logger.info("> MAIL FROM: <" + SENDER_EMAIL + ">");
					logger.info(client.getReplyString());
					try {
						client.disconnect();
						continue;
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
					logger.info("> RCPT TO: <" + email + ">");
					logger.info(client.getReplyString());
					
					if (client.getReplyCode() == 250) {
						// SMTP通讯成功
						return true;
					}
					try {
						client.disconnect();
						continue;
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
				}
			}
		} else {
			// SMTP失败
			return false;
		}
		return false;
	}
	
	public static void main(String[] args) {
		System.out.println(isValidFormat("*********@qq.com"));
		System.out.println(isValidFormat("$---@qq.com"));
		System.out.println(isValidFormat("#*****$@qq.com"));
		System.out.println(isValidFormat("!123******@qq.com"));
		System.out.println(isValidDomain("@qq.com"));
		System.out.println(isValidDomainFormat("@aapindustries.com.au"));
	}
}

 

OAuth 2.0授权码模式深度解析与Spring Boot实战 在现代分布式应用和微服务架构中,安全授权是保障系统安全的核心环节。OAuth 2.0作为一种行业标准的授权框架,其核心原理在于通过令牌(Token)机制,实现安全的资源访问委托,避免了密码共享的风险。这一机制为应用集成、API安全调用提供了标准化解决方案,具有极高的技术价值。其典型的应用场景包括第三方登录、服务间通信和企业应用集成。本文聚焦于OAuth 2.0中安全等级最高的授权码模式(Authorization Code Grant),该模式通过分离前端授权与后端令牌交换,有效防止了令牌泄露。我们将结合S 阅读详情

相关推荐

微服务契约测试实战:基于Pact的消费者驱动契约与提供者验证

在微服务架构中,服务间接口的稳定性和可靠性是保障系统整体质量的关键。消费者驱动契约测试作为一种先进的测试策略,其核心原理是通过定义并验证服务间的交互契约,来确保接口的兼容性。该技术通过解耦消费者与提供者的测试依赖,允许双方并行开发和独立验证,从而显著提升交付速度和测试可靠性。在工程实践中,结合Pact等成熟工具链,可以高效地实现契约的生成、发布与验证,并集成到CI/CD流水线中,成为重要的质量门禁。本文聚焦于微服务E2E测试中的Consumer Pact Test和Provider Verification

weixin_34234721的博客 581

[ SpringBoot ]

Spring虽然有很多优点, 但是Spring框架的1. 配置麻烦,而且很多都是模版化的配置(固定的)2. 需要添加很多依赖, 例如web层依赖jackson组件,需要我们自己添加, 版本也可能不匹配基于以上两点,spring官方推出了SpringBoot .

yang20060116的博客 845

【信息科学与工程学】【安全领域】第八十三篇 云安全解决方案02

企业中“搞人”与“搞事情”常见问题的分析框架。我将选取4个典型场景,每个场景都从实际管理现象出发,逐步推导出数学模型、参数设定及关联知识。

weixin_49199313的博客 324

Hermes Agent:5 分钟跑通第一个任务,看懂它的工具调用循环

你让一个 AI 查个问题,它回你一句"你可以用 grep 试试",然后就没有然后了。Hermes Agent 不一样:它自己调工具、读文件、跑命令,每一步的输出都喂回模型,直到任务做完才收工。你发完消息就可以关终端去吃饭。 ## Hermes Agent 一句话定位:和只会动嘴的聊天机器人差在哪 不用它,你拿到的是"建议";用它,你拿到的是结果。你丢一句"把仓库里的 TODO 整理成清单",普

gitblog_00271的博客 871

【信息科学与工程学】【安全领域】 第八十八篇 网络空间安全21

如果员工认为安全政策和流程(如复杂的密码规则、频繁的认证、繁琐的软件安装审批)阻碍了工作效率,他们可能会寻找变通方法,例如:写下密码、共享账户、使用未经批准的云服务(影子IT)、绕过安全控制。例如,一个用于显示用户列表的API,可能返回每个用户的完整个人资料,包括邮箱、地址、电话等敏感字段,而前端可能只显示了姓名。:在OAuth 2.0或OIDC流程中,攻击者可能截获授权请求中的“授权码”,或窃取“访问令牌”,然后将其用于另一个客户端(非原始授权的客户端),从而以用户身份访问受保护的资源。

weixin_49199313的博客 445

2、瑞丽-伯纳德对流的拉格朗日拟序结构(FTLE场结果对比)

在中,我简单比较了瑞丽伯纳德对流的FTLE场,但是因为粒子追踪采用的是欧拉方法,所以精度不是很高, 因此与文献中的结果还是有些差别。下面放一张文献中的FTLE场,参数与上篇文章是一致的,Ra = 1e8;Pr = 1;本文将详细的介绍如何得到这样的图片,好吧,其实也不是很详细。总之,先展示以下我个人的结果。可以看出,上图基本上与文献是一致的,因为这里展示的是瞬时场,所以当然不可能是完全一致,至于提取的LCS结构,我在下面也会提及。本着详细介绍的原则,所以这里我很良心的从流场计算开始介绍。

ambu1230的博客 1786

JWT与nimbus-jose-jwt实战:Java中令牌认证与加密完整指南

在分布式系统和微服务架构中,API认证与授权是保障服务安全交互的核心机制。传统的Session-Cookie模式因状态管理复杂、扩展性差,逐渐被无状态的令牌机制所取代。JSON Web Token(JWT)作为一种开放标准,通过数字签名或加密,将声明信息编码为紧凑的URL安全字符串,实现了跨域、跨服务的身份与权限安全传递。其核心价值在于服务端无需存储会话状态,显著降低了分布式环境下的存储压力与协调成本。JWT通常由头部、载荷和签名三部分组成,支持HS256、RS256等多种签名算法,并可进一步通过JWE实现

weixin_34199405的博客 339

【RK3588 NPU性能调优实战】多线程异步推理YOLOv5,榨干6TOPS算力

本文详细解析了如何在RK3588 NPU上通过多线程异步推理优化YOLOv5目标检测性能,实现6TOPS算力的最大化利用。通过线程池设计、流水线化帧处理及避开内存带宽瓶颈等技巧,将NPU利用率从30%提升至82%,帧率显著提高至61.2FPS。文章还提供了环境配置、代码实现及性能对比数据,助力开发者高效部署AI模型。

weixin_29034963的博客 341

OAuth2.0单点登录:原理、安全设计与Spring实战

在现代分布式系统和微服务架构中,身份认证与授权是保障应用安全的核心基础。OAuth2.0协议通过标准化的授权流程,实现了安全的第三方应用访问控制,其核心思想是资源所有者在不暴露凭证的前提下,授权客户端访问特定资源。这一机制在单点登录场景中展现出巨大技术价值,用户只需在统一认证中心登录一次,即可安全访问所有接入的业务系统,极大提升了用户体验并降低了密码管理风险。从原理层面,OAuth2.0定义了资源所有者、客户端、授权服务器和资源服务器四大角色,并通过授权码模式等流程确保安全性。在工程实践中,结合JWT令牌和

weixin_33716941的博客 401

MTK平台LCD驱动开发实战:从零开始点亮你的Android屏幕

本文详细介绍了在MTK平台进行Android LCD驱动开发的完整流程。从理解LK与Kernel双核驱动框架入手,手把手讲解驱动结构体、屏幕参数配置、初始化序列编写以及PLL_CLOCK计算等核心步骤,并提供了系统集成配置与实用的调试避坑指南,帮助开发者高效点亮新屏幕。

terraform7cloud的博客 293

Moodle平台题库建设技术

Moodle平台题库建设技术简述1新的改变1功能快捷键1合理的创建标题,有助于目录的生成1如何改变文本的样式1插入链接与图片1如何插入一段漂亮的代码片1生成一个适合你的列表1创建一个表格1设定内容居中、居左、居右1SmartyPants1创建一个自定义列表1如何创建一个注脚注释也是必不可少的1KaTeX数学公式1新的甘特图功能,丰富你的文章1UML 图表1FLowchart流程图1导出与导入导出1...

lxf78的博客 4534

InnoDB 内存结构总览:Change Buffer、AHI 与 Log Buffer

本文系统梳理InnoDB内存结构中的ChangeBuffer、Adaptive Hash Index(AHI)与LogBuffer。ChangeBuffer缓存二级索引页不在内存时的变更,减少随机IO,仅在页加载时合并;聚簇索引修改立即执行,因数据本身不可延后。AHI基于高频等值查询自动构建哈希索引,加速定位,仅支持等值操作。LogBuffer为redo log内存缓冲,配合磁盘日志实现崩溃恢复。三者均服务于性能优化,其中ChangeBuffer与AHI共享BufferPool空间,而LogBuffer独立

bksczm的博客 293

深度测评:Accio Work——目前普通用户最友好的多 Agent 协同工具

摘要:Accio Work是阿里国际站推出的多Agent协同工具,通过借鉴古代"三省六部制"构建高效协作框架。该工具支持主流大模型,可配置专业Agent角色,实现40分钟内完成复杂产品PRD等高效协作。其亮点在于直观的UI设计和流程驱动机制,能强制各Agent从专业视角深度思考。虽然超长对话稳定性有待优化,但作为目前最用户友好的多Agent工具,显著降低了构建复杂AI团队的门槛,成为提升个人和小微企业生产力的利器。

Maynor的博客 1738

V8 机制、手写核心函数与 TypeScript 类型体操

或固定初始化(如数组先定长、对象先给全字段)保持类型与形状稳定;这些都比"换框架"更基础。只能处理纯数据(丢函数、Date、RegExp、循环引用报错)。生产级深拷贝要处理:原始值短路、循环引用、V8(Chrome / Node 的 JS 引擎)不是"解释一行跑一行"那么简单,它用。图:V8 执行流程——解释执行 + 热点优化,优化失败会 Deopt 回退。JS 内存自动管理,但"自动"不等于"不会漏"。是"固定间隔最多执行一次"。手写 Promise 是"懂异步"的试金石。是"停下后才执行最后一次",

qq_38468358的博客 350

我的python学习之路

Python 是一门功能强大且易于学习的编程语言,广泛应用于数据分析、人工智能、Web 开发、自动化等领域。以下是一个 Python 学习路径的总结,帮助你系统地掌握 Python 编程。

数据知道的博客 3万+

损失函数大汇总(五十三)(Boundary Loss附公式推导与代码)

摘要 Boundary Loss是一种针对图像分割任务的新型损失函数,特别适用于高度类别不平衡的细粒度分割场景。与传统的区域型损失(如Dice、交叉熵)不同,它通过计算预测边界与真实边界之间的距离来优化模型,更关注边界精度而非区域重叠。核心思想是利用距离图(distance map)将边界约束转化为区域积分形式,实现端到端训练。具体实现中,损失函数为预测概率与距离图的点积,梯度仅取决于距离图,具有明确的空间引导性。相比区域型损失,Boundary Loss能更好处理小目标、细长结构等边界敏感任务,可与Dic

悦学共鸣,温柔以待,汇聚光芒,共同成长 240

Spring Boot 数据源与 MyBatis(-Plus) 自定义配置详解

本文详解 Spring Boot 中单数据源环境下 HikariCP 与 MyBatis-Plus 的自定义配置。通过手动声明 SqlSessionFactory,实现下划线转驼峰、日志输出、一级缓存策略等精细化控制。结合 HikariCP 核心参数调优(如最大连接数、连接生命周期),确保高性能与稳定性。适用于仅需访问单一数据库的场景,避免多数据源复杂性,兼顾性能与可维护性。

BADAO_LIUMANG_QIZHI的博客 208

反光柱定位算法实战03:VEnus代码解析和纯反光柱定位中的可改进方向

本文深入解析了开源框架VEnus的反光柱定位与建图实现流程,包括强度提取、聚类、数据关联、位姿优化等核心模块。同时指出其三大局限:匹配质量脆弱性、单一传感器依赖和地图扩展逻辑缺失,并提出改进方向:融合里程计/IMU数据、引入图优化后端、建立动态地图维护机制。该分析为基于反光柱的定位系统优化提供了实用参考,有助于提升工业场景下的定位鲁棒性和精确性。

Studying…… 520

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

要努力去发光,而不是被照亮~ 148

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

LeetCode Hot 100 二叉树专题(二)3 题(Java)

本篇文章共 3 题:543. 二叉树的直径、102. 二叉树的层序遍历、108. 将有序数组转换为二叉搜索树。 每道题都统一按「① 题目分析 & 解题思路 → ② 常见解法(附代码)及讲解 → ③ 知识点总结」的顺序组织;代码使用 Java 编写,节点定义沿用 LeetCode 默认的 TreeNode。

2401_88612756的博客 369

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

【从零理解 Spring AI · 12】MCP 的两种角色:做客户端还是做服务端

上一篇讲了 MCP 的概念:标准协议、三大角色、M+N 替代 M×N。

nice_lcj520的博客 517

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

JDK 下载安装:装完 Java 提示「不是内部或外部命令」?环境变量没配

JDK 是写 Java 程序必须装的东西。它包含运行 Java 的虚拟机(JRE)和编译 Java 的编译器(javac)——装了它,能跑、.java文件能编译成可执行程序。免费,学习和小规模生产都不花钱。

科小怪的博客 639

Java 集合容器高频面试题全解:HashMap 树化阈值、1.7 死循环与 ConcurrentHashMap 演进(2026 招聘 JD 真题复盘)

HashMap 树化阈值 8 的泊松分布依据、退化阈值 6 的防抖设计、JDK 1.7 头插成环死循环的排查与修复、1.8 尾插后为何仍线程不安全、ConcurrentHashMap 放弃分段锁的原因与 ForwardingNode 协作扩容、computeIfAbsent 死锁陷阱、大集合找重复的场景题选型,附三层追问链自测。题目来源为 38 期公开招聘 JD 样本与字节、拼多多、建行、美团、快手公开面经。

蒙眼过河 412

java框架大全

java框架大全

qq_39326137的博客 185

Java 多态 学习笔记

多态是面向对象编程的重要特性,指同一操作作用于不同对象时产生不同行为。其核心在于“父类引用指向子类对象”,结合方法重写实现运行时动态绑定。多态使代码更灵活、可扩展,如用Person p = new Student();统一处理各类人员注册,无需修改调用逻辑。但多态无法直接调用子类特有方法,需通过instanceof判断并强制转换。编译时看左边(类型),运行时看右边(实际对象),实现解耦与维护便利。

AA_AA114514的博客 366
上一篇: Hive工具类
HogwartsRow
博客等级 码龄15年 0粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值