当前位置: 首页 > news >正文

Java使用企业邮箱发送预警邮件

前言:最近接到一个需求,需要根据所监控设备的信息,在出现问题时发送企业微信进行预警。

POM依赖

<!--  邮件   -->
<dependency><groupId>com.sun.mail</groupId><artifactId>jakarta.mail</artifactId><version>1.6.7</version>
</dependency>

yml配置项 

mail:service:smtpSslEnable: truesmtpAuth: truesmtpHost: smtp.exmail.qq.com # 企业微信的hostsmtpPort: 465account: 发信人邮箱名password: 发信人邮箱密码

邮箱工具类

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Data
@Component
@ConfigurationProperties(prefix = "mail.service")
public class MailServiceProperties {private String account;/*** 登录密码*/private String password;/*** 邮件服务器地址*/private String smtpHost;/*** 发信端口*/private String smtpPort;/*** 是否认证*/private String smtpAuth;private String smtpSslEnable;}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class MailContent {private String aliasName;private String recipients;private String subject;private String content;
}
import com.ruoyi.common.config.MailServiceProperties;
import com.ruoyi.common.constant.MailContent;
import com.sun.mail.util.MailSSLSocketFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.security.GeneralSecurityException;
import java.util.Date;
import java.util.Properties;@Slf4j
@Component
public class MailUtils {@Autowiredprivate MailServiceProperties properties;/*** 批量发送邮件** @param aliasName 别名* @param subject   主题* @param content   内容*/public void batchSendEmail(String recipientList, String aliasName, String subject, String content) {if (!StringUtils.isEmpty(recipientList)) {String[] arrs = recipientList.split(",");for (String arr : arrs) {send(new MailContent(aliasName, arr, subject, content));}} else {log.error("收件人为空,发送失败。");}}/*** 批量发送邮件 带图片** @param aliasName 别名* @param subject   主题* @param content   内容* @param  is       图片*/public void batchSendEmail(String recipientList, String aliasName, String subject, String content,InputStream is) {if (!StringUtils.isEmpty(recipientList)) {String[] arrs = recipientList.split(",");for (String arr : arrs) {send(new MailContent(aliasName, arr, subject, content),is);}} else {log.error("收件人为空,发送失败。");}}/*** 发送邮件** @param content*/private void send(MailContent content) {// 设置邮件属性Properties prop = new Properties();prop.setProperty("mail.transport.protocol", "smtp");prop.setProperty("mail.smtp.host", properties.getSmtpHost());prop.setProperty("mail.smtp.port", properties.getSmtpPort());prop.setProperty("mail.smtp.auth", properties.getSmtpAuth());prop.setProperty("mail.smtp.ssl.protocols", "TLSv1.2");MailSSLSocketFactory sslSocketFactory = null;try {sslSocketFactory = new MailSSLSocketFactory();sslSocketFactory.setTrustAllHosts(true);} catch (GeneralSecurityException e1) {log.error("开启 MailSSLSocketFactory 失败", e1);}if (sslSocketFactory == null) {log.error("开启 MailSSLSocketFactory 失败");} else {prop.put("mail.smtp.ssl.enable", properties.getSmtpSslEnable());prop.put("mail.smtp.ssl.socketFactory", sslSocketFactory);// 创建邮件会话(注意,如果要在一个进程中切换多个邮箱账号发信,应该用 Session.getInstance)Session session = Session.getDefaultInstance(prop, new MyAuthenticator(properties.getAccount(), properties.getPassword()));try {MimeMessage mimeMessage = new MimeMessage(session);// 设置发件人别名(如果未设置别名就默认为发件人邮箱)if (content.getAliasName() != null && !content.getAliasName().trim().isEmpty()) {mimeMessage.setFrom(new InternetAddress(properties.getAccount(), content.getAliasName()));} else {mimeMessage.setFrom(new InternetAddress(properties.getAccount(), properties.getAccount()));}// 设置主题和收件人、发信时间等信息mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(content.getRecipients()));mimeMessage.setSubject(content.getSubject());mimeMessage.setSentDate(new Date());// 添加正文信息MimeMultipart multipart = new MimeMultipart();MimeBodyPart body = new MimeBodyPart();body.setContent(content.getContent(), "text/html; charset=UTF-8");multipart.addBodyPart(body);mimeMessage.setContent(multipart);// 开始发信mimeMessage.saveChanges();Transport.send(mimeMessage);} catch (Exception e) {log.error("发送邮件错误:", e);}}}/*** 发送邮件(带图片)** @param content 文本内容* @param inputStream 图片内容*/private void send(MailContent content, InputStream inputStream) {// 设置邮件属性Properties prop = new Properties();prop.setProperty("mail.transport.protocol", "smtp");prop.setProperty("mail.smtp.host", properties.getSmtpHost());prop.setProperty("mail.smtp.port", properties.getSmtpPort());prop.setProperty("mail.smtp.auth", properties.getSmtpAuth());prop.setProperty("mail.smtp.ssl.protocols", "TLSv1.2");MailSSLSocketFactory sslSocketFactory = null;try {sslSocketFactory = new MailSSLSocketFactory();sslSocketFactory.setTrustAllHosts(true);} catch (GeneralSecurityException e1) {log.error("开启 MailSSLSocketFactory 失败", e1);}if (sslSocketFactory == null) {log.error("开启 MailSSLSocketFactory 失败");} else {prop.put("mail.smtp.ssl.enable", properties.getSmtpSslEnable());prop.put("mail.smtp.ssl.socketFactory", sslSocketFactory);// 创建邮件会话(注意,如果要在一个进程中切换多个邮箱账号发信,应该用 Session.getInstance)Session session = Session.getDefaultInstance(prop, new MyAuthenticator(properties.getAccount(), properties.getPassword()));try {MimeMessage mimeMessage = new MimeMessage(session);// 设置发件人别名(如果未设置别名就默认为发件人邮箱)if (content.getAliasName() != null && !content.getAliasName().trim().isEmpty()) {mimeMessage.setFrom(new InternetAddress(properties.getAccount(), content.getAliasName()));} else {mimeMessage.setFrom(new InternetAddress(properties.getAccount(), properties.getAccount()));}// 设置主题和收件人、发信时间等信息mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(content.getRecipients()));mimeMessage.setSubject(content.getSubject());mimeMessage.setSentDate(new Date());// 添加正文信息MimeMultipart multipart = new MimeMultipart();//邮件内容//准备图片数据MimeBodyPart image=new MimeBodyPart();File tmpFile =File.createTempFile("123",".jpg");Files.copy(inputStream,tmpFile.toPath(), StandardCopyOption.REPLACE_EXISTING);DataHandler dh=new DataHandler(new FileDataSource(tmpFile));image.setDataHandler(dh);//id自己设置image.setContentID("123");//image.setFileName("999.png");//正文MimeBodyPart text=new MimeBodyPart();text.setContent(content.getContent()+"<br/><a><img src='cid:123'></a>","text/html;charset=UTF-8");// text.setContent("<h1 style='color:red'>带图片的邮件<img src='cid:bz.jpg'></h1>","text/html;charset=UTF-8");MimeMultipart mmTextImage = new MimeMultipart();mmTextImage.addBodyPart(text);mmTextImage.addBodyPart(image);// 关联关系mmTextImage.setSubType("related");MimeBodyPart textImage = new MimeBodyPart();textImage.setContent(mmTextImage);multipart.addBodyPart(textImage);multipart.setSubType("mixed");mimeMessage.setContent(multipart);// 开始发信mimeMessage.saveChanges();Transport.send(mimeMessage);tmpFile.deleteOnExit();} catch (Exception e) {log.error("发送邮件错误:", e);}}}/*** 认证信息*/static class MyAuthenticator extends Authenticator {/*** 用户名*/String username = null;/*** 密码*/String password = null;/*** 构造器** @param username 用户名* @param password 密码*/public MyAuthenticator(String username, String password) {this.username = username;this.password = password;}@Overrideprotected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication(username, password);}}}

Controller

import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.MailUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/aicut")
@Slf4j
public class MailController {@Autowiredprivate MailUtils mailUtils;@PostMapping("/sendMail")public R sendMail() {String recipientList = "xxx@xx.com"; //收件人邮箱,以逗号分割,可同时发给多个人String aliasName = "测试邮件";String subject = "邮件主题";String content = "邮件内容";mailUtils.batchSendEmail(recipientList, aliasName, subject, content);return R.ok();}
}

测试结果

相关文章:

Java使用企业邮箱发送预警邮件

前言&#xff1a;最近接到一个需求&#xff0c;需要根据所监控设备的信息&#xff0c;在出现问题时发送企业微信进行预警。 POM依赖 <!-- 邮件 --> <dependency><groupId>com.sun.mail</groupId><artifactId>jakarta.mail</artifactId>…...

Unity编辑器扩展之是否勾选Text组件BestFit选项工具(此篇教程也可以操作其他组件的属性)

想要批量化是否勾选项目预制体资源中Text组件BestFit属性&#xff08;此篇教程也可以操作其他组件的属性&#xff0c;只不过需要修改其中对应的代码&#xff09;&#xff0c;可以采用以下步骤。 1、在项目的Editor文件中&#xff0c;新建一个名为TextBestFitBatchProcessor的…...

分布式场景怎么Join | 京东云技术团队

背景 最近在阅读查询优化器的论文&#xff0c;发现System R中对于Join操作的定义一般分为了两种&#xff0c;即嵌套循环、排序-合并联接。在原文中&#xff0c;更倾向使用排序-合并联接逻辑。 考虑到我的领域是在处理分库分表或者其他的分区模式&#xff0c;这让我开始不由得…...

24-k8s的附件组件-Metrics-server组件与hpa资源pod水平伸缩

一、概述 Metrics-Server组件目的&#xff1a;获取集群中pod、节点等负载信息&#xff1b; hpa资源目的&#xff1a;通过metrics-server获取的pod负载信息&#xff0c;自动伸缩创建pod&#xff1b; 参考链接&#xff1a; 资源指标管道 | Kubernetes https://github.com/kuberne…...

Spring RabbitMQ 配置多个虚拟主机(vhost)

文章目录 前言一、相关文章二、相关代码1.yml文件配置2.RabbitMq配置类3.接收MQ消息前言 在日常开发中,同时需要用到RabbitMQ多个虚拟机(vhost)。应用场景:需要接收多个交换机的数据,而交换机都在不同的虚拟机(vhost) 一、相关文章 Docker安装RabbitMQ 【SpringCloud…...

「Qt Widget中文示例指南」如何实现文档查看器?(一)

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写&#xff0c;所有平台无差别运行&#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今&#xff0c;Qt已被运用于超过70个行业、数千家企业&#xff0c;支持数百万设备及应用。 文档查看器是一个显…...

如何创建WordPress付款表单(简单方法)

您是否正在寻找一种简单的方法来创建付款功能WordPress表单&#xff1f; 小企业主通常需要创建一种简单的方法来在其网站上接受付款&#xff0c;而无需设置复杂的购物车。简单的付款表格使您可以轻松接受自定义付款金额、设置定期付款并收集自定义详细信息。 在本文中&#x…...

虹科方案 | 释放总线潜力:汽车总线离线模拟解决方案

来源&#xff1a;虹科汽车智能互联 虹科方案 | 释放总线潜力&#xff1a;汽车总线离线模拟解决方案 原文链接&#xff1a;https://mp.weixin.qq.com/s/KGv2ZOuQMLIXlOiivvY6aQ 欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; #汽车总线 #ECU #汽车网关 导读 传统的…...

欲速则不达,慢就是快!

引言 随着生活水平的提高&#xff0c;不少人的目标从原先的解决温饱转变为追求内心充实&#xff0c;但由于现在的时间过得越来越快以及其他外部因素&#xff0c;我们对很多东西的获取越来越没耐心&#xff0c;例如书店经常会看到《7天精通Java》、《3天掌握XXX》等等之类的书籍…...

ubuntu22.04@Jetson OpenCV安装

ubuntu22.04Jetson OpenCV安装 1. 源由2. 分析3. 证实3.1 jtop安装3.2 jtop指令3.3 GPU支持情况 4. 安装OpenCV4.1 修改内容4.2 Python2环境【不需要】4.3 ubuntu22.04环境4.4 国内/本地环境问题4.5 cudnn版本问题 5. 总结6. 参考资料 1. 源由 昨天用Jetson跑demo程序发现帧率…...

OpenGL学习——17.模型

前情提要&#xff1a;本文代码源自Github上的学习文档“LearnOpenGL”&#xff0c;我仅在源码的基础上加上中文注释。本文章不以该学习文档做任何商业盈利活动&#xff0c;一切著作权归原作者所有&#xff0c;本文仅供学习交流&#xff0c;如有侵权&#xff0c;请联系我删除。L…...

6.2 数据库

本节介绍Android的数据库存储方式--SQLite的使用方法&#xff0c;包括&#xff1a;SQLite用到了哪些SQL语法&#xff0c;如何使用数据库管理操纵SQLitem&#xff0c;如何使用数据库帮助器简化数据库操作&#xff0c;以及如何利用SQLite改进登录页面的记住密码功能。 6.2.1 SQ…...

计算机设计大赛 深度学习人体跌倒检测 -yolo 机器视觉 opencv python

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习的人体跌倒检测算法研究与实现 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满…...

本地模拟发送、接收RabbitMQ数据

文章目录 前言一、相关文章二、相关代码1.模拟的 Channel 类2.接收消息3.模拟推送MQ数据前言 日常开发中,当线上RabbitMQ坏境还没准备好时,可在本地模拟发送、接收消息 一、相关文章 Docker安装RabbitMQ 【SpringCloud】整合RabbitMQ六大模式应用(入门到精通) Spring R…...

前端 webSocket 的使用

webSocket使用 注意要去监听websocket 对象事件&#xff0c;处理我们需要的数据 我是放在了最外层的index 内&#xff0c;监听编辑状态&#xff0c;去触发定义的方法。因为我这个项目是组件化开发&#xff0c;全部只有一个总编辑按钮&#xff0c;我只需监听是否触发了编辑即可…...

opencv图像处理(一)

一. OpenCV 简介 OpenCV 是一个跨平台计算机视觉库&#xff0c;可以运行在Linux、Windows、Android和Mac OS操作系统上。 应用领域 1、人机互动 2、物体识别 3、图像分割 4、人脸识别 5、动作识别 6、运动跟踪 7、机器人 8、运动分析 9、机器视觉 10、…...

消息队列-RabbitMQ:workQueues—工作队列、消息应答机制、RabbitMQ 持久化、不公平分发(能者多劳)

4、Work Queues Work Queues— 工作队列 (又称任务队列) 的主要思想是避免立即执行资源密集型任务&#xff0c;而不得不等待它完成。我们把任务封装为消息并将其发送到队列&#xff0c;在后台运行的工作进程将弹出任务并最终执行作业。当有多个工作线程时&#xff0c;这些工作…...

前端秘法基础式(HTML)(第二卷)

目录 一.表单标签 1.表单域 2.表单控件 2.1input标签 2.2label/select/textarea标签 2.3无语义标签 三.特殊字符 一.表单标签 用来完成与用户的交互,例如登录系统 1.表单域 <form>通过action属性,将用户填写的数据转交给服务器 2.表单控件 2.1input标签 type…...

PTA-统计英文字母和数字字符[2]

本题要求编写程序&#xff0c;输入N个字符&#xff0c;统计其中英文字母、数字字符和其他字符的个数。 输入格式: 输入在第一行中给出正整数N&#xff0c;第二行输入N个字符&#xff0c;最后一个回车表示输入结束&#xff0c;不算在内。 输出格式: 在一行内按照 letter 英…...

Elasticsearch:将 IT 智能和业务 KPI 与 AI 连接起来 - 房间里的大象

作者&#xff1a;Fermi Fang 大象寓言的智慧 在信息技术和商业领导力的交叉点&#xff0c;蒙眼人和大象的古老寓言提供了一个富有洞察力的类比。 这个故事起源于印度次大陆&#xff0c;讲述了六个蒙住眼睛的人第一次遇到大象的故事。 每个人触摸大象的不同部位 —— 侧面、象牙…...

记录一次线上问题排查:JDK序列化问题

在技术领域&#xff0c;我们常常被那些闪耀的、可见的成果所吸引。今天&#xff0c;这个焦点无疑是大语言模型技术。它们的流畅对话、惊人的创造力&#xff0c;让我们得以一窥未来的轮廓。然而&#xff0c;作为在企业一线构建、部署和维护复杂系统的实践者&#xff0c;我们深知…...

终极优化指南:NodeSource Node.js 二进制分发版的 Docker 镜像体积与启动速度革命

终极优化指南&#xff1a;NodeSource Node.js 二进制分发版的 Docker 镜像体积与启动速度革命 【免费下载链接】distributions NodeSource Node.js Binary Distributions 项目地址: https://gitcode.com/gh_mirrors/di/distributions NodeSource Node.js 二进制分发版为…...

如何在5分钟内搭建终端风格网站:LiveTerm自动化安装完整指南

如何在5分钟内搭建终端风格网站&#xff1a;LiveTerm自动化安装完整指南 【免费下载链接】LiveTerm &#x1f4bb; Build terminal styled websites in minutes! 项目地址: https://gitcode.com/gh_mirrors/li/LiveTerm LiveTerm是一款功能强大的开源工具&#xff0c;能…...

AI辅助游戏开发新体验:让快马平台的AI模型为你的Superpowers项目编写剧情与平衡技能

最近在尝试用Superpowers框架开发一款魔法题材的RPG游戏&#xff0c;发现InsCode(快马)平台的AI辅助功能特别适合快速原型开发。这里分享下如何用AI模型辅助完成游戏剧情脚本和技能平衡设计的实践过程。 剧情脚本生成 输入"魔法学校学徒发现古老卷轴"这个简单设定后&…...

OpenClaw+Qwen3.5-9B低成本方案:自建接口替代OpenAI API

OpenClawQwen3.5-9B低成本方案&#xff1a;自建接口替代OpenAI API 1. 为什么选择Qwen3.5-9B作为OpenClaw的本地大脑 去年冬天&#xff0c;当我第一次尝试用OpenClaw自动化处理周报时&#xff0c;被OpenAI API的账单吓了一跳——简单的文件整理和摘要生成&#xff0c;一周竟消…...

Cache 维护实战:深入理解 ARMv8-A 架构下的 Invalidate 与 Clean 操作

1. 为什么需要关注Cache维护&#xff1f; 在嵌入式开发中&#xff0c;Cache就像是你办公桌上的文件架。当你频繁访问某些数据时&#xff0c;CPU会把这些数据放在Cache里&#xff0c;就像把常用文件放在手边一样。但问题来了&#xff1a;如果文件内容更新了&#xff08;比如内存…...

避开高速接口时序坑:用IDELAY2和ODDR实战优化FPGA的input delay约束

高速接口时序优化实战&#xff1a;IDELAY2与ODDR的精细控制艺术 当FPGA设计遭遇GHz级高速接口时&#xff0c;传统的时序约束方法往往捉襟见肘。我曾在一个25Gbps背板项目中发现&#xff0c;即使精确计算了input delay约束&#xff0c;时序报告仍显示关键路径存在0.3ns的违例—…...

快速SEO排名服务需要多长时间见效_快速SEO排名服务有哪些常见的手段

快速SEO排名服务需要多长时间见效 在当今数字化时代&#xff0c;网站的在线可见度对于企业的成功至关重要。快速SEO排名服务应运而生&#xff0c;旨在帮助企业尽快在搜索引擎上获得更好的排名&#xff0c;从而提高流量和业务。但是&#xff0c;很多人都会疑惑&#xff0c;快速…...

Tomato-Novel-Downloader:高性能小说下载工具的技术实践与应用指南

Tomato-Novel-Downloader&#xff1a;高性能小说下载工具的技术实践与应用指南 【免费下载链接】Tomato-Novel-Downloader 番茄小说下载器不精简版 项目地址: https://gitcode.com/gh_mirrors/to/Tomato-Novel-Downloader 1 核心价值&#xff1a;重新定义小说下载体验 …...

Z-Image-GGUF文生图案例分享:看看AI能画出多美的图片

Z-Image-GGUF文生图案例分享&#xff1a;看看AI能画出多美的图片 1. 开篇&#xff1a;当文字遇见画笔 想象一下&#xff0c;你只需要输入一段描述&#xff0c;就能得到一张精美的图片。这不是科幻电影里的场景&#xff0c;而是Z-Image-GGUF带给我们的现实体验。作为阿里巴巴通…...