使用SMTP javamail发送邮件

news2025/1/16 21:37:56

一、SMTP协议

        SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP协议属于TCP/IP协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。使用javamail编写发送程序发送邮件。

以QQ邮箱为例:

需要开启SMTP服务,设置授权码。授权码不是登录密码,授权码是QQ邮箱用于登录第三方客户端/服务的专用密码,适用于登录以下服务:POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV 服务。不同邮箱可能不一样。

还需要服务器地址,QQ 邮箱的服务器地址 (host) 是:

收信服务器 (POP3) : pop.qq.com

发信服务器 (SMTP) : smtp.qq.com

 二、代码编写

 1、配置文件

可以将邮件的账号密码等放入配置文件

#邮件配置,需要修改密码。username:账号,password:密码/授权码,serverUrl:服务器地址,serverPort:服务器端口,sendMail:邮箱
email:
  username: 1074004100@qq.com
  password:
  serverUrl: smtp.qq.com
  serverPort: 25
  sendMail: 1074004100@qq.com

配置对象:

package com.example.demo.config;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/**
 * @author zhanglei
 * @date : 2023/03/06 14:14
 * 邮箱配置
 */
@Component
@Configuration
@Data
public class EmailConfig {

    /**
     * 邮件账号
     */
    @Value("${email.username}")
    private String username;

    /**
     * 邮件密码/授权码
     */
    @Value("${email.password}")
    private String password;

    /**
     * 服务器地址
     */
    @Value("${email.serverUrl}")
    private String serverUrl;

    /**
     * 服务器端口
     */
    @Value("${email.serverPort}")
    private Integer serverPort;

    /**
     * 发送邮箱
     */
    @Value("${email.sendMail}")
    private String sendMail;


}

2、发送方法

参数对象:

package com.example.demo.entity;

import lombok.Data;

import java.util.List;

/**
 * 邮件内容
 * @author zhanglei
 */
@Data
public class MailContent {

    /**
     * 邮件标题
     */
    private String subject;

    /**
     * 邮件内容
     */
    private String text;

    /**
     * 附件名称
     */
    private List<String> attachmentNameList;


    /**
     * 附件地址
     */
    private List<String> attachmentUrlList;

    /**
     * 目标邮箱
     */
    private String toEmail;

    /**
     * 抄送邮箱
     */
    private String ccEmail;


}

发送方法:

package com.example.demo.util;

import com.example.demo.config.EmailConfig;
import com.example.demo.entity.MailContent;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;

import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * 自定义邮箱发送邮件
 *
 * @author zhanglei
 * @version 1.0
 * @date 2024-03-05 15:08
 */
@Component
public class MailSendSmtp {

    /**
     * 默认端口号
     */
    public static final Integer MAIL_DEFAULT_PORT = 25;

    @Autowired
    private EmailConfig emailConfig;


    /*{
        "attachmentNameList": [
        "附件名.pdf"
        ],
        "attachmentUrlList": [
        "https://invtest.nntest.cn/fp/BoRzE95ScXVqSZDehEhBZbz0YyYUFDwZ4Rr8oEuLzBfeM7rFoDSjYRKObeRPOHXyAnrfgbHtf4mz5r3-qvJRvQ.pdf"
        ],
        "ccEmail": "",
         "subject": "测试邮件",
         "text": "你好,这个测试邮件,请忽略",
         "toEmail": "1953623531.qq.com"
    }*/

    /**
     * 发送邮件,自己发送,不使用消息中心
     *
     * @param mailContent 邮件内容
     * @throws Exception 异常
     */
    public boolean send(MailContent mailContent) {

        try {
            //抄送地址
            List<String> addresses = new ArrayList<>();
            addresses.add(mailContent.getToEmail());
            if (StringUtils.isNotBlank(mailContent.getCcEmail())) {
                String[] ccs = mailContent.getCcEmail().split(";");
                for (String addr : ccs) {
                    if (StringUtils.isNotBlank(addr)) {
                        addresses.add(addr);
                    }
                }
            }

            JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
            // 设置邮件内容格式
            javaMailSender.setDefaultEncoding("utf-8");
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
            javaMailSender.setHost(emailConfig.getServerUrl());
            // 设置默认端口,防止使用域名的时候,解析不正确
            Integer port = emailConfig.getServerPort() == null ? MAIL_DEFAULT_PORT : emailConfig.getServerPort();
            if (!MAIL_DEFAULT_PORT.equals(port)) {
                javaMailSender.setPort(port);
            }
            javaMailSender.setUsername(emailConfig.getUsername());
            javaMailSender.setPassword(emailConfig.getPassword());
            // 如果配置的发送邮箱为空,则使用邮件账号;否则使用发送邮箱
            helper.setFrom(StringUtils.isBlank(emailConfig.getSendMail()) ? emailConfig.getUsername() : emailConfig.getSendMail());
            //目标邮箱
            helper.setTo(mailContent.getToEmail());
            //邮件内容
            helper.setText(mailContent.getText(), true);
            //邮件标题
            helper.setSubject(mailContent.getSubject());
            // 增加抄送人
            if (StringUtils.isNotBlank(mailContent.getCcEmail())) {
                helper.setCc(addresses.toArray(new String[0]));
            }
            //附件,可以是多个,获取文件流
            if (CollectionUtils.isNotEmpty(mailContent.getAttachmentNameList())) {
                for (int i = 0; i < mailContent.getAttachmentNameList().size(); i++) {
                    String fileName = mailContent.getAttachmentNameList().get(i);
                    String url = mailContent.getAttachmentUrlList().get(i);
                    byte[] pdfBytes = HttpClientUtil.getRemoteResource(url, 5000);
                    if (pdfBytes != null) {
                        ByteArrayResource pdfResource = new ByteArrayResource(pdfBytes);
                        helper.addAttachment(MimeUtility.encodeText(fileName), pdfResource, "application/pdf");
                    }
                }
            }

            Properties props = new Properties();
            /*// 增加ssl配置
            if (mailInfoUtil.isEnableSsl()) {
                props.put("mail.smtp.auth", "true");
                props.put("mail.smtp.ssl.enable", "true");
            }
            // 增加tsl配置
            if (mailInfoUtil.isEnableTls()) {
                props.put("mail.smtp.starttls.enable", "true");
                props.put("mail.smtp.starttls.required", "true");
            }
            */
            if (!props.isEmpty()) {
                Session session = Session.getInstance(props, new javax.mail.Authenticator() {
                    @Override
                    protected javax.mail.PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(emailConfig.getUsername(), emailConfig.getPassword());
                    }
                });
                javaMailSender.setSession(session);
            }
            // 发送邮件
            javaMailSender.send(mimeMessage);
            return true;

        } catch (Exception e) {
            return false;
        }
    }
}

项目地址:https://gitee.com/itzhl/dynamic-data-source-demo.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1496734.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JavaEE】_Spring MVC 项目单个及多个参数传参

目录 1. 传递单个参数 1.1 关于参数名的问题 2. 传递多个参数 2.1 关于参数顺序的问题 2.2 关于基本类型与包装类的问题 1. 传递单个参数 现创建Spring MVC项目&#xff0c;.java文件内容如下&#xff1a; package com.example.demo.controller;import org.springframewo…

NCDA 大赛 App 设计获奖作品分享!

未来设计师全国高校数字艺术设计大赛简称“NCDA大赛”&#xff0c;是由工信部人才交流中心主办&#xff0c;直接对联合国接国际设计赛事的一个大学生竞赛&#xff0c;不仅由教育部中国高等教育学会认定&#xff0c;教育厅发文立项&#xff0c;还有来自我们都很熟悉的“学习强国…

vue3中指定组件名称:可以使用插件vite-plugin-vue-setup-extend

第一步&#xff1a;安装vite-plugin-vue-setup-extend插件 第二步&#xff1a;修改vite.config.ts文件配置

C#多线程(4)——任务并行库TPL

文章目录 1 什么是TPL2 创建与启动任务3 等待任务4 任务中的异常处理5 取消任务 1 什么是TPL T P L \textcolor{red}{TPL} TPL&#xff08;Task Parallel Library&#xff09;任务并行库&#xff0c;是从.NetFramwork4.0后引入的基于异步操作的一组API。TPL的底层是基于多线程实…

nginx: mac使用vscode本地调试nginx

vscode安装c语言插件 在extensions中搜索"c/c"&#xff0c; 将前3个插件都安装 在extensions中搜索"cmake"&#xff0c; 将前2个插件都安装 下载nginx源码 nginx 源码: https://github.com/nginx/nginx 编译运行Nginx 修改 /auto/cc/conf 文件&…

【论文阅读】单词级文本攻击TAAD2.2

TAAD2.2论文概览 0.前言1-101.Bridge the Gap Between CV and NLP! A Gradient-based Textual Adversarial Attack Frameworka. 背景b. 方法c. 结果d. 论文及代码 2.TextHacker: Learning based Hybrid Local Search Algorithm for Text Hard-label Adversarial Attacka. 背景b…

数据结构——lesson6二叉树基础

前言 hellohello~这里是土土数据结构学习笔记&#x1f973;&#x1f973; &#x1f4a5;个人主页&#xff1a;大耳朵土土垚的博客 &#x1f4a5; 所属专栏&#xff1a;数据结构学习笔记 &#x1f4a5;对于数据结构顺序表链表有疑问的都可以在上面数据结构的专栏进行学习哦~感…

ping多个IP的工具

Ping Tool 项目地址 python开发的IP搜索小工具 ping一个网段所有IP&#xff0c;显示结果查看某个ip地址开放监听的端口配置可保存

查询IP地址保障电商平台安全

随着电子商务的快速发展&#xff0c;网购已经成为人们日常生活中不可或缺的一部分。然而&#xff0c;网络交易安全一直是人们关注的焦点之一&#xff0c;尤其是在面对日益频发的网络诈骗和欺诈行为时。为了提高网购平台交易的安全性&#xff0c;一种有效的方法是通过查询IP地址…

Java红黑树实现Map简单示例

红黑树&#xff08;Red-Black Tree&#xff09;是一种自平衡的二叉搜索树&#xff0c;它是由 Rudolf Bayer 在 1972 年提出的&#xff0c;后来由 Leo J. Guibas 和 Robert Sedgewick 在 1978 年发表的论文中形式化定义。 红黑树具有以下特性&#xff1a; 1.节点颜色&#xff1…

java数据结构与算法刷题-----LeetCode653. 两数之和 IV - 输入二叉搜索树

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 1. 前序遍历加hash2. 中序遍历双指针 1. 前序遍历加hash 解题思…

(上海电力展)2024上海国际智慧电力与电气设备展览会

2024上海国际智慧电力与电气设备展览会 2024 Shanghai International Intelligent Power and Electrical Equipment Exhibition 时 间&#xff1a;2024年7月13-15日 地 点&#xff1a;上海新国际博览中心 展会简介Introduction 随着全球进入互联网和数字经济时…

逻辑分析仪分析硬件spi

一&#xff0c;cubemx配置好后&#xff0c;使用spi接口发送数据&#xff1b; 发送5个字节&#xff1a;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff1b; 第1个字节&#xff1a;1&#xff1b; 第2个字节&#xff1a;2&#xff1b; 第3个字节&#xff1a;3&am…

【趣玩一下】StreamDiffusion一秒100张!实时生成二次元老婆照!

源代码 https://github.com/cumulo-autumn/StreamDiffusion 基础原理 首先Stream Batch&#xff0c;是将原来顺序的去噪步骤改为批量化处理。允许在一个批处理中&#xff0c;每幅图像处于去噪流程的不同阶段。 如此一来&#xff0c;可以大大减少UNet推理次数&#xff0c;显著…

基于单片机的医院输液系统设计

目 录 摘 要 Ⅰ Abstract Ⅱ 引 言 1 1系统方案设计与论证 3 1.1系统硬件结构总体设计方案 3 1.2点滴速度测量电路方案的选择与论证 3 1.3液面检测电路方案的选择与论证 4 1.4通过电机控制滴速电路的方案与论证 4 1.5显示器接口电路方案选择与论证 5 1.6键盘接口电路方案选择与…

十:套接字和标准I/O,以及分离I/O流

1 标准I/O函数的优点 C语言标准IO整理 1.1 标准I/O函数的两个优点 标准I/O函数具有良好的移植性。 标准I/O函数可以利用缓冲提高性能 从图中可以看出&#xff0c;使用标准I/O函数传输数据时&#xff0c;经过两个缓冲。例如&#xff0c;使用fputs函数传输字符串 “Hello” 时…

数据分析-Pandas数据的画图设置

数据分析-Pandas数据的画图设置 数据分析和处理中&#xff0c;难免会遇到各种数据&#xff0c;那么数据呈现怎样的规律呢&#xff1f;不管金融数据&#xff0c;风控数据&#xff0c;营销数据等等&#xff0c;莫不如此。如何通过图示展示数据的规律&#xff1f; 数据表&#x…

TypeScript(四)枚举类型(Enum Types),类型别名(Type),运算符

一、枚举类型 使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。 TypeScript支持数字的和基于字符串的枚举。 枚举类型的特点 可以给一组数值取上一个更好理解的名字&#xff1b;一个枚举中只会存在几个固定的值&#xff0c;并不会…

C语言第三十六弹---文件操作(中)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 文件操作 1、文件的顺序读写 1.1、顺序读写函数介绍 1.1.1、fgetc 与 fputc 1.1.2、fgets 与 fputs 1.1.3、fscanf 与 fprintf 1.1.4、fread 与 fwrite 1.…

【vue3之组合式API及其新特性】

组合式API及其新特性 一、setup1.写法2.如何访问3.语法糖4.同步返回对象 二、reactive()和ref()1.reactive()2.ref() 三、computed四、watch函数1.侦听单个数据2.侦听多个数据3. immediate4. deep5.精确侦听对象的某个属性 五、生命周期函数六、组件通信1.父传子2. 子传父 七、…