1.使用javax.mail, spring的JavaMailSender,springboot发送邮件

xiaokantianse 2020-11-09 14:08:06
spring 使用 mail javax.mail javax


一、java发邮件

  1. 电子邮件服务器:这些邮件服务器就类似于邮局,它主要负责接收用户投递过来的邮件,并把邮件投递到邮件接收者的电子邮箱中,按功能划分有两种类型
    • SMTP邮件服务器:用户替用户发送邮件和接收外面发送给本地用户的邮件
    • POP3/IMAP邮件服务器:用户帮助用户读取SMTP邮件服务器接收进来的邮件
  2. 邮件传输协议:电子邮件需要在邮件客户端和邮件服务器之间,以及两个邮件服务器之间进行邮件传递,就需遵守一定的规则
    • SMTP协议:全称为 Simple Mail Transfer Protocol,简单邮件传输协议。它定义了邮件客户端软件和SMTP邮件服务器之间,以及两台SMTP邮件服务器之间的通信规则
    • POP3协议:全称为 Post Office Protocol,邮局协议。它定义了邮件客户端软件和POP3邮件服务器的通信规则
    • IMAP协议:全称为 Internet Message Access Protocol,Internet消息访问协议,它是对POP3协议的一种扩展,也是定义了邮件客户端软件和IMAP邮件服务器的通信规则
  3. 邮件格式:邮件内容的基本格式和具体细节分别是由 RFC822 文档和 MIME 协议定义的
    • RFC822文档中定义的文件格式包括两个部分:邮件头和邮件体
    • ME协议(Multipurpose Internet Mail Extensions )用于定义复杂邮件体的格式,使邮件的内容更加多样化
  4. 邮件发送与接收流程
      • 邮件客户端软件写好一封邮件,交到SMTP的QQ邮件服务器
      • QQ邮箱会解析用户发送的邮件,判断收件地址是否是自己的账户,如果收件也是QQ邮箱,会直接存放到自己的存储空间。如果不是QQ邮箱,而是163邮箱,那么QQ邮箱会将邮件转发到163邮箱服务器,转发协议也是SMTP
      • 163邮箱服务器接收到QQ邮箱转发过来的邮件,会判断收件地址是否是自己的,如果是自己的账户,就会将QQ邮箱转发过来的邮件存放到自己的内部存储空间
      • 用户A将邮件发送了之后,通知用户B去指定的邮箱收取邮件。用户B会通过邮件客户端软件先向163邮箱服务器请求,要求收取自己的邮件
      • 163邮箱服务器收到用户B的请求后,会从自己的存储空间中取出B未收取的邮件
      • 163邮箱服务器取出用户B未收取的邮件后,将邮件发给用户B,最后三步用户B收取邮件的过程,使用的协议是POP3

二、使用javax.mail发送邮件(简单,带图片,带附件,带图片和附件)

  • 使用之前应该申请qq邮箱的授权码(第三方的使用时,替代密码)

  • qq邮箱邮件服务器地址和端口(smtp.qq.com 端口465或587)

  • 导入依赖

  • <!--发送邮件的jar 1.4 版本会出现javamail.providers 文件找不见 与其他jar包中文件冲突-->
    <dependency>
    <groupId>javax.mail</groupId>
    <artifactId>mail</artifactId>
    <version>1.4.4</version>
    </dependency>
    
  1. 邮件的基本信息类

    @Data
    public class JavaMailInfo {
    /**
    * 使用java mail 发送邮件 邮件的协议有SMTP POP IMAP MIME 等 协议具体内容可自行百度 SMTP 为简单邮件传输协议 比较常用
    */
    // 邮件服务器地址
    private String mailSeverHost;
    // 邮件服务器端口
    private String mailServerPort;
    // 邮件发送者
    private String fromAddress;
    // 发送者用户名
    private String userName;
    // 发送者密码
    private String password;
    // 收件人地址
    private String toAddress;
    // 邮件主题
    private String subject;
    // 邮件内容
    private String content;
    // 图片地址集合
    private List<String> photoUrlList;
    // 附件地址集合
    private List<String> attachList;
    /**
    * 获取邮件会话属性 ,对邮件Session进行设置 此部分的内容可以通过加载配置文件的方式进行设置
    * @return
    */
    public Properties getProperties() {
    Properties properties = new Properties();
    properties.put("mail.transport.protocol", "smtp");// 连接协议
    properties.put("mail.smtp.host", this.mailSeverHost);// 主机名
    properties.put("mail.smtp.port", this.mailServerPort);// 端口号
    properties.put("mail.smtp.auth", "true");//设置smtp是否需要认证
    properties.put("mail.smtp.ssl.enable", "true");// 设置是否使用ssl安全连接 ---一般都使用
    properties.put("mail.debug", "true");// 设置是否显示debug信息 true 会在控制台显示相关信息
    properties.put("mail.smtp.timeout", 20000);// 超时时间
    return properties;
    }
    }
    
  2. 权限认证类

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class MyJavaMailAuthenticator extends Authenticator {
    private String userName = null;
    private String password = null;
    /**
    * 此类用于储存授权时使用的用户名和密码 用于构建邮件Session对象 便于需要认证时邮件Session知道需要使用哪个类验证
    * 以用户名、密码的方式访问那些受到保护的资源,在这里“资源”就是指邮件服务器
    * 自定义的类需要继承Authenticator类 重写getPasswordAuthentication() 方法 注意导包 需要使用javax.mail包下的相关类
    */
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication(this.userName, this.password);
    }
    }
    
  3. 发送邮件工具类

    public class JavaMailSendUtils {
    /**
    * 实际使用
    * @param args
    */
    public static void main(String[] args) {
    JavaMailInfo javaMailInfo = new JavaMailInfo();
    javaMailInfo.setMailSeverHost("smtp.qq.com");
    javaMailInfo.setMailServerPort("465");// 465或587(使用ssl)
    javaMailInfo.setFromAddress("发件人");
    javaMailInfo.setUserName("您邮箱用户名");
    javaMailInfo.setPassword("您邮箱授权码");// 密码需要使用对应邮箱的授权码授权码
    javaMailInfo.setToAddress("收件人");
    javaMailInfo.setSubject("邮件主题");
    javaMailInfo.setContent("邮件内容");
    List<String> photoUrlList = new ArrayList<>();
    photoUrlList.add("图片1");
    photoUrlList.add("图片2");
    javaMailInfo.setPhotoUrlList(photoUrlList);
    List<String> attachList = new ArrayList<>();
    attachList.add("附件1");
    attachList.add("附件2");
    javaMailInfo.setAttachList(attachList);
    sendJavaMail(javaMailInfo);
    }
    /**
    * 此工具类可根据邮件基本信息进行邮件的发送
    */
    /**
    * 发送邮件方法
    * @param javaMailInfo
    * @return
    */
    public static boolean sendJavaMail(JavaMailInfo javaMailInfo) {
    // 获取邮件session的相关配置参数
    Properties properties = javaMailInfo.getProperties();
    // 创建授权验证类
    MyJavaMailAuthenticator myJavaMailAuthenticator = new MyJavaMailAuthenticator();
    myJavaMailAuthenticator.setUserName(javaMailInfo.getUserName());
    myJavaMailAuthenticator.setPassword(javaMailInfo.getPassword());
    // 构建邮件Session会话对象 带不带default均可 查看源码可知 带default的是获取该类的属性 不带获取的是新创建的
    Session mailSession = Session.getDefaultInstance(properties, myJavaMailAuthenticator);
    // 开启debug properties中设置了此处就无须设置
    // mailSession.setDebug(true);
    // 邮差对象 也可使用静态方法进行发送
    Transport transport = null;
    try {
    // 获取消息 也就是发送的内容
    // Message message = createSimpleMail(mailSession, javaMailInfo);
    // Message message = createImageMail(mailSession, javaMailInfo);
    // Message message = createAttachMail(mailSession, javaMailInfo);
    Message message = createPhotoAndAttachMail(mailSession, javaMailInfo);
    // 设置规范 具体是什么规范呢? 固定写法
    MailcapCommandMap defaultCommandMap = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
    defaultCommandMap.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
    defaultCommandMap.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
    defaultCommandMap.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
    defaultCommandMap.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
    defaultCommandMap.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
    CommandMap.setDefaultCommandMap(defaultCommandMap);
    // 发送邮件 Transport.send(message); 或者获取Transport对象发送
    transport = mailSession.getTransport();
    transport.connect(javaMailInfo.getUserName(), javaMailInfo.getUserName());
    transport.sendMessage(message, message.getAllRecipients());
    System.out.println("邮件发送成功");
    return true;
    } catch (MessagingException e) {
    e.printStackTrace();
    System.out.println("邮件发送失败");
    return false;
    } finally {
    if (null != transport) {
    try {
    transport.close();
    } catch (MessagingException e) {
    e.printStackTrace();
    }
    }
    }
    }
    /**
    * 根据邮件Session和邮件信息创建邮件内容(文本类 html)
    * @param mailSession
    * @param javaMailInfo
    * @return
    */
    private static Message createSimpleMail(Session mailSession, JavaMailInfo javaMailInfo) throws MessagingException {
    /**
    * Message是一 个抽象类,我们使用MimeMessage这个子类, 该类是使用MIME类型、MIME信息头的 邮箱信息
    * 信息头只能使用US-ASCII字符,而非ASCII字符将通过编码转换为ASCII的方式使用
    */
    // 根据邮件session创建消息对象
    MimeMessage mimeMessage = new MimeMessage(mailSession);
    // 设置发件人 setFrom 和 setReplyTo 均可 有多个发件人使用 addFroms(Address[] addresses)
    mimeMessage.setFrom(new InternetAddress(javaMailInfo.getFromAddress()));
    // 设置收件人 收件人类型 Message.RecipientType.TO(接受者) Message.RecipientType.CC(抄送着) Message.RecipientType.BCC(密送者)
    // setRecipients(Message.RecipientType var1, Address[] var2) 设置多个收件人
    mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(javaMailInfo.getToAddress()));
    // 设置标题
    mimeMessage.setSubject(javaMailInfo.getSubject(), "text/plain;charset=utf-8");
    // 设置内容 是文本可直接使用setText()
    mimeMessage.setContent(javaMailInfo.getContent(), "text/html;charset=utf-8");
    // 设置发送时间
    mimeMessage.setSentDate(new Date());
    mimeMessage.saveChanges();
    return mimeMessage;
    }
    /**
    * 根据邮件Session和邮件信息创建邮件内容(图片类 可多个图片)
    * @param mailSession
    * @param javaMailInfo
    * @return
    */
    private static Message createImageMail(Session mailSession, JavaMailInfo javaMailInfo) throws MessagingException {
    /**
    * Message表示一个邮件,messgaes.getContent()返回一个Multipart对象。一个Multipart对象包含一个或多个BodyPart对象,来组成邮件的正文部分(包括附件)
    * Multipart的content-type
    * 总体来说,MIME消息由消息头和消息体两大部分组成。现在我们关注的是MIME邮件,因此在以下的讨论中姑且称“消息”为“邮件”。
    * 邮件头包含了发件人、收件人、主题、时间、MIME版本、邮件内容的类型等重要信息。每条信息称为一个域,由域名后加“: ”和信息内容构成,可以是一行,较长的也可以占用多行。
    * 域的首行必须“顶头”写,即左边不能有空白字符(空格和制表符);续行则必须以空白字符打头,且第一个空白字符不是信息本身固有的,解码时要过滤掉。
    * 邮件体包含邮件的内容,它的类型由邮件头的“Content-Type”域指出。常见的简单类型有text/plain(纯文本)和text/html(超文本)。有时也会出现的multipart类型,是MIME邮件的精髓。
    * 邮件体被分为多个段,每个段又包含段头和段体两部分,这两部分之间也以空行分隔。常见的multipart类型有三种:multipart/mixed, multipart/related和multipart/alternative。
    * multipart/mixed:附件。
    * multipart/related:内嵌资源。
    * multipart/alternative:纯文本与超文本共存。
    */
    MimeMessage mimeMessage = new MimeMessage(mailSession);
    mimeMessage.setFrom(new InternetAddress(javaMailInfo.getFromAddress()));
    mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(javaMailInfo.getToAddress()));
    mimeMessage.setSubject(javaMailInfo.getSubject(), "text/plain;charset=utf-8");
    List<String> photoUrlList = javaMailInfo.getPhotoUrlList();
    // 创建消息体 以下方式每个图片都有一个标题
    MimeMultipart mimeMultipart = new MimeMultipart();
    if (!CollectionUtils.isEmpty(photoUrlList)) {
    for (String photoUrl : photoUrlList) {
    MimeBodyPart text = new MimeBodyPart();
    // 设置图片标题 注意img标签的引用位置 用cid:开头
    String cid = UUID.randomUUID().toString();
    text.setContent(javaMailInfo.getContent() +"<br/><img src='cid:"+ cid +".jpg'>", "text/html;charset=utf-8");
    // 使用数据处理器处理图片
    MimeBodyPart image = new MimeBodyPart();
    image.setDataHandler(new DataHandler(new FileDataSource(photoUrl)));
    image.setContentID(cid);
    // 描述正文和图片的关系
    MimeMultipart photo = new MimeMultipart();
    photo.addBodyPart(text);
    photo.addBodyPart(image);
    photo.setSubType("related");
    MimeBodyPart mimeBodyPart = new MimeBodyPart();
    mimeBodyPart.setContent(photo);
    // 将图片放入body中
    mimeMultipart.addBodyPart(mimeBodyPart);
    }
    }
    /*// 以下方式所有图片公用一个标题
    MimeMultipart photo = new MimeMultipart();
    MimeBodyPart text = new MimeBodyPart();
    photo.addBodyPart(text);
    StringBuilder textContent = new StringBuilder(javaMailInfo.getContent());
    if (!CollectionUtils.isEmpty(photoUrlList)) {
    for (String photoUrl : photoUrlList) {
    // 设置图片标题 注意img标签的引用位置 用cid:开头
    String cid = UUID.randomUUID().toString();
    textContent.append("<br/><img src='cid:"+ cid +".jpg'>");
    // 使用数据处理器处理图片
    MimeBodyPart image = new MimeBodyPart();
    image.setDataHandler(new DataHandler(new FileDataSource(photoUrl)));
    image.setContentID(cid);
    // 描述正文和图片的关系
    photo.addBodyPart(image);
    }
    photo.setSubType("related");
    }
    text.setContent(textContent.toString(), "text/html;charset=utf-8");*/
    // 设置消息体
    mimeMessage.setContent(mimeMultipart);
    // mimeMessage.setContent(photo);
    mimeMessage.setSentDate(new Date());
    mimeMessage.saveChanges();
    return mimeMessage;
    }
    /**
    * 根据邮件Session和邮件信息创建邮件内容(附件类 可多个附件)
    * @param mailSession
    * @param javaMailInfo
    * @return
    */
    private static Message createAttachMail(Session mailSession, JavaMailInfo javaMailInfo) throws MessagingException {
    MimeMessage mimeMessage = new MimeMessage(mailSession);
    mimeMessage.setFrom(new InternetAddress(javaMailInfo.getFromAddress()));
    mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(javaMailInfo.getToAddress()));
    mimeMessage.setSubject(javaMailInfo.getSubject(), "text/plain;charset=utf-8");
    List<String> attachList = javaMailInfo.getAttachList();
    // 创建消息体
    MimeMultipart mimeMultipart = new MimeMultipart();
    MimeBodyPart text = new MimeBodyPart();
    text.setContent(javaMailInfo.getSubject(), "text/html;charset=utf-8");
    mimeMultipart.addBodyPart(text);
    if (!CollectionUtils.isEmpty(attachList)) {
    for (String attach : attachList) {
    // 创建附件
    MimeBodyPart mimeBodyPart = new MimeBodyPart();
    DataHandler dataHandler = new DataHandler(new FileDataSource(attach));
    mimeBodyPart.setDataHandler(dataHandler);
    mimeBodyPart.setFileName(dataHandler.getName());
    // 加入最外面的容器
    mimeMultipart.addBodyPart(mimeBodyPart);
    }
    // 描述关系
    mimeMultipart.setSubType("mixed");
    }
    mimeMessage.setContent(mimeMultipart);
    mimeMessage.setSentDate(new Date());
    mimeMessage.saveChanges();
    return mimeMessage;
    }
    /**
    * 根据邮件Session和邮件信息创建邮件内容(多图片 多附件)
    * @param mailSession
    * @param javaMailInfo
    * @return
    */
    private static Message createPhotoAndAttachMail(Session mailSession, JavaMailInfo javaMailInfo) throws MessagingException {
    MimeMessage mimeMessage = new MimeMessage(mailSession);
    mimeMessage.setFrom(new InternetAddress(javaMailInfo.getFromAddress()));
    mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(javaMailInfo.getToAddress()));
    List<String> photoUrlList = javaMailInfo.getPhotoUrlList();
    // 获取所有的图片 公用一个主题
    MimeMultipart photo = new MimeMultipart();
    MimeBodyPart text = new MimeBodyPart();
    photo.addBodyPart(text);
    StringBuilder textContent = new StringBuilder(javaMailInfo.getContent());
    if (!CollectionUtils.isEmpty(photoUrlList)) {
    for (String photoUrl : photoUrlList) {
    // 设置图片标题 注意img标签的引用位置 用cid:开头
    String cid = UUID.randomUUID().toString();
    textContent.append("<br/><img src='cid:"+ cid +".jpg'>");
    // 使用数据处理器处理图片
    MimeBodyPart image = new MimeBodyPart();
    image.setDataHandler(new DataHandler(new FileDataSource(photoUrl)));
    image.setContentID(cid);
    // 描述正文和图片的关系
    photo.addBodyPart(image);
    }
    photo.setSubType("related");
    }
    text.setContent(textContent.toString(), "text/html;charset=utf-8");
    // 将图片包裹成一个body 作为 其内容
    MimeBodyPart content = new MimeBodyPart();
    content.setContent(photo);
    // 获取所有的附件
    List<String> attachList = javaMailInfo.getAttachList();
    MimeMultipart attach = new MimeMultipart();
    if (!CollectionUtils.isEmpty(attachList)) {
    for (String attachUrl : attachList) {
    // 创建附件
    MimeBodyPart mimeBodyPart = new MimeBodyPart();
    DataHandler dataHandler = new DataHandler(new FileDataSource(attachUrl));
    mimeBodyPart.setDataHandler(dataHandler);
    mimeBodyPart.setFileName(dataHandler.getName());
    // 加入最外面的容器
    attach.addBodyPart(mimeBodyPart);
    }
    }
    // 将图片body 和 附件组合
    attach.addBodyPart(content);
    attach.setSubType("mixed");
    mimeMessage.setContent(attach);
    mimeMessage.setSentDate(new Date());
    mimeMessage.saveChanges();
    return mimeMessage;
    }
    }
    

三、使用spring的JavaMailSender发送邮件(简单,带图片,带附件,带图片和附件,freemarker模板)

  • spring提供的JavaMailSender是对原始的javax.mail进行了简化

  • 再其使用过程中可以注册到spring容器中,也可不用注册

  • 导入依赖

  • javax.mail的依赖包
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    </dependency>
    
  1. 邮件的基本信息类

    @Data
    public class JavaMailSenderInfo {
    // 收件人地址
    private String toAddress;
    // 邮件主题
    private String subject;
    // 邮件内容
    private String content;
    // 是否是html 注意字段boolean类型 不要用is开头 idea会生成get,set方法会进行优化 isHtml -> isHtml(),getHtml() -- html -> isHtml(),getHtml()
    private boolean html = false;
    // 图片地址集合
    private List<String> photoList;
    // 附件地址集合
    private List<String> attachList;
    }
    
  2. 准备mail.propertise配置文件(也就是设置会话的属性),文件放在resource目录下

    #传输协议
    mail.transport.protocol=smtp
    #服务器主机名
    mail.smtp.host=smtp.qq.com
    #服务器端口号 465或587(使用ssl)
    mail.smtp.port=465
    #是否进行用户名密码校验 配置了否 就不能配置 用户名和密码 否则会去获取用户名密码进行验证
    mail.smtp.auth=true
    #设置是否使用ssl安全连接 ---一般都使用
    mail.smtp.ssl.enable=true
    #设置是否显示debug信息 true 会在控制台显示相关信息
    mail.debug=true
    #设置超时时间
    mail.smtp.timeout=20000
    #编码格式
    mail.smtp.defaultEncoding=utf-8
    #你的邮箱地址
    mail.smtp.username=xxxxxx@qq.com
    #你的授权码(第三方使用时代替密码)
    mail.smtp.password=xxxxxx
    
  3. 加载配置文件,初始化JavaMailSender

    public class InitJavaMailSender {
    /**
    * 此类的作用是加载配置文件来创建JavaMailSender对象 JavaMailSenderImpl是该接口的实现类
    * 因此我们需要对JavaMailSenderImpl进行配置 在spring的环境下 我们可以使用加载配置文件的方式 或者
    * 在spring配置文件中直接配置该bean(由spring托管)使用时@Autowired直接注入即可
    * <bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    * <property name="host" value="${mail.smtp.host}" />
    * <property name="username" value="${mail.smtp.username}" />
    * <property name="password" value="${mail.smtp.password}" />
    * <property name="defaultEncoding" value="${mail.smtp.defaultEncoding}" />
    * <property name="javaMailProperties">
    * <props>
    * <prop key="mail.smtp.auth">${mail.smtp.auth}</prop>
    * <prop key="mail.smtp.timeout">${mail.smtp.timeout}</prop>
    * ...
    * </props>
    * </property>
    * </bean>
    * 本次采用加载配置文件的方式
    * 由spring提供 其底层使用的仍然是javax.mail进行邮件的发送
    * JavaMailSenderImpl 依赖javax.mail 和 spring-context-support包
    */
    // 传输协议
    private static String protocol;
    // 服务器主机名
    private static String host;
    // 服务器端口号
    private static String port;
    // 是否进行用户名密码校验
    private static String auth;
    // 设置是否使用ssl安全连接
    private static String enableSSL;
    // 设置是否显示debug信息
    private static String debug;
    // 超时时间
    private static String timeout;
    // 编码格式
    private static String defaultEncoding;
    // 邮箱地址
    public static String username;
    // 授权码
    private static String password;
    private static JavaMailSenderImpl javaMailSenderImpl;
    static {
    init();
    }
    private static void init() {
    // 加载配置文件
    Properties properties = new Properties();
    InputStream resourceAsStream = JavaMailSender.class.getClassLoader().getResourceAsStream("mail.properties");
    try {
    properties.load(resourceAsStream);
    protocol = properties.getProperty("mail.transport.protocol");
    host = properties.getProperty("mail.smtp.host");
    port = properties.getProperty("mail.smtp.port");
    auth = properties.getProperty("mail.smtp.auth");
    enableSSL = properties.getProperty("mail.smtp.ssl.enable");
    debug = properties.getProperty("mail.debug");
    timeout = properties.getProperty("mail.smtp.timeout");
    defaultEncoding = properties.getProperty("mail.smtp.defaultEncoding");
    username = properties.getProperty("mail.smtp.username");
    password = properties.getProperty("mail.smtp.password");
    System.out.println("mail.properties加载成功");
    } catch (IOException e) {
    e.printStackTrace();
    System.out.println("mail.properties加载失败");
    } finally {
    if (null != resourceAsStream) {
    try {
    resourceAsStream.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    /**
    * 使用单例获取JavaMailSender 双重检查既保证的线程安全 又保证了效率 又能起到延迟加载的作用
    * @return
    */
    public static JavaMailSender getJavaMailSender() {
    if (null == javaMailSenderImpl) {
    synchronized (InitJavaMailSender.class) {
    if (null == javaMailSenderImpl) {
    javaMailSenderImpl = new JavaMailSenderImpl();
    javaMailSenderImpl.setProtocol(protocol);
    javaMailSenderImpl.setHost(host);
    javaMailSenderImpl.setPort(Integer.parseInt(port));
    javaMailSenderImpl.setDefaultEncoding(defaultEncoding);
    javaMailSenderImpl.setUsername(username);
    javaMailSenderImpl.setPassword(password);
    Properties properties = new Properties();
    properties.setProperty("mail.smtp.auth", auth);
    properties.setProperty("mail.smtp.ssl.enable", enableSSL);
    properties.setProperty("mail.debug", debug);
    properties.setProperty("mail.smtp.timeout", timeout);
    javaMailSenderImpl.setJavaMailProperties(properties);
    }
    }
    }
    return javaMailSenderImpl;
    }
    }
    
  4. 邮件发送工具类

    public class JavaMailSenderUtils {
    /**
    * 测试发送邮件 实际中可以在service中使用(若使用的spring配置的方式创建JavaMailSender,则需注入使用)
    * 此处为方便使用main方法
    * @param args
    */
    public static void main(String[] args) {
    JavaMailSenderInfo javaMailSenderInfo = new JavaMailSenderInfo();
    javaMailSenderInfo.setToAddress("发件人");
    javaMailSenderInfo.setSubject("邮件主题");
    javaMailSenderInfo.setContent("邮件内容");
    javaMailSenderInfo.setHtml(true);
    List<String> list = new ArrayList<>();
    list.add("图片1");
    // list.add("图片2");
    // list.add("图片3");
    // list.add("图片4");
    javaMailSenderInfo.setPhotoList(list);
    javaMailSenderInfo.setAttachList(list);
    // JavaMailSenderUtils.sendSimpleMail(javaMailSenderInfo);
    JavaMailSenderUtils.sendPhotoMail(javaMailSenderInfo);
    // JavaMailSenderUtils.sendAttacheMail(javaMailSenderInfo);
    // JavaMailSenderUtils.sendPhotoAndAttacheMail(javaMailSenderInfo);
    }
    private static final JavaMailSender javaMailSender = InitJavaMailSender.getJavaMailSender();
    private static final String htmlStartStr = "<html><body>";
    private static final String htmlEndStr = "</body></html>";
    /**
    * 发送简单邮件 文本 html
    * @param javaMailSenderInfo
    * @return
    */
    public static boolean sendSimpleMail(JavaMailSenderInfo javaMailSenderInfo) {
    // 创建邮件消息 简单邮件可直接使用SimpleMailMessage
    MimeMessage mimeMessage = javaMailSender.createMimeMessage();
    MimeMessageHelper mimeMessageHelper = null;
    try {
    // 创建消息辅助器 参数二 为true时为多组件 html 等
    mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "utf-8");
    // 设置公共字段
    setMailCommonField(mimeMessageHelper, javaMailSenderInfo);
    // 文本内容 可指定是否是html
    mimeMessageHelper.setText(javaMailSenderInfo.getContent(), javaMailSenderInfo.isHtml());
    javaMailSender.send(mimeMessage);
    System.out.println("简单邮件发送成功");
    return true;
    } catch (MessagingException e) {
    e.printStackTrace();
    System.out.println("简单邮件发送失败");
    return false;
    }
    }
    /**
    * 发送带图片的邮件
    * @param javaMailSenderInfo
    * @return
    */
    public static boolean sendPhotoMail(JavaMailSenderInfo javaMailSenderInfo) {
    // 创建邮件消息 简单邮件可直接使用SimpleMailMessage
    MimeMessage mimeMessage = javaMailSender.createMimeMessage();
    MimeMessageHelper mimeMessageHelper = null;
    try {
    mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "utf-8");
    setMailCommonField(mimeMessageHelper, javaMailSenderInfo);
    List<String> photoList = javaMailSenderInfo.getPhotoList();
    // html内容
    StringBuilder text = new StringBuilder(htmlStartStr);
    text.append(javaMailSenderInfo.getContent());
    if (!CollectionUtils.isEmpty(photoList)) {
    for (String photo : photoList) {
    // 每个图片创建一个标题吧 每个图片关联一个cid
    String cid = UUID.randomUUID().toString();
    text.append("<br/><h1>"+ javaMailSenderInfo.getSubject() +"</h1><br/><img src='cid:"+ cid +"'/>");
    mimeMessageHelper.addInline(cid, new File(photo));
    }
    }
    // 为什么会有最后一个图片图裂不显示的问题(求大佬指点)
    // String cid = UUID.randomUUID().toString();
    // mimeMessageHelper.addInline(cid, new File(""));
    text.append(htmlEndStr);
    mimeMessageHelper.setText(text.toString(),true);
    javaMailSender.send(mimeMessage);
    System.out.println("带图片的邮件发送成功");
    return true;
    } catch (MessagingException e) {
    e.printStackTrace();
    System.out.println("带图片的邮件发送失败");
    return false;
    }
    }
    /**
    * 发送带附件的邮件
    * @param javaMailSenderInfo
    * @return
    */
    public static boolean sendAttacheMail(JavaMailSenderInfo javaMailSenderInfo) {
    // 创建邮件消息 简单邮件可直接使用SimpleMailMessage
    MimeMessage mimeMessage = javaMailSender.createMimeMessage();
    MimeMessageHelper mimeMessageHelper = null;
    try {
    mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "utf-8");
    setMailCommonField(mimeMessageHelper, javaMailSenderInfo);
    List<String> attachList = javaMailSenderInfo.getAttachList();
    // 邮件文本
    mimeMessageHelper.setText(javaMailSenderInfo.getContent(), javaMailSenderInfo.isHtml());
    if (!CollectionUtils.isEmpty(attachList)) {
    for (String attach : attachList) {
    // 添加附件(最后一个附件是图片也存在图裂的问题,但可下载使用,求大佬指点)
    FileSystemResource fileSystemResource = new FileSystemResource(attach);
    // 参数一为附件名称
    mimeMessageHelper.addAttachment(fileSystemResource.getFilename(), fileSystemResource);
    }
    }
    javaMailSender.send(mimeMessage);
    System.out.println("带附件的邮件发送成功");
    return true;
    } catch (MessagingException e) {
    e.printStackTrace();
    System.out.println("带附件的邮件发送失败");
    return false;
    }
    }
    /**
    * 发送带图片和附件的邮件
    * @param javaMailSenderInfo
    * @return
    */
    public static boolean sendPhotoAndAttacheMail(JavaMailSenderInfo javaMailSenderInfo) {
    // 创建邮件消息 简单邮件可直接使用SimpleMailMessage
    MimeMessage mimeMessage = javaMailSender.createMimeMessage();
    MimeMessageHelper mimeMessageHelper = null;
    try {
    mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "utf-8");
    setMailCommonField(mimeMessageHelper, javaMailSenderInfo);
    List<String> photoList = javaMailSenderInfo.getPhotoList();
    // 放入图片和内容
    StringBuilder text = new StringBuilder(htmlStartStr + javaMailSenderInfo.getContent());
    if (!CollectionUtils.isEmpty(photoList)) {
    for (String photo : photoList) {
    String cid = UUID.randomUUID().toString();
    text.append("<br/><img src='cid:"+ cid +"'>");
    mimeMessageHelper.addInline(cid, new File(photo));
    }
    }
    text.append(htmlEndStr);
    mimeMessageHelper.setText(text.toString(),true);
    // 放入附件
    List<String> attachList = javaMailSenderInfo.getAttachList();
    if (!CollectionUtils.isEmpty(attachList)) {
    for (String attach : attachList) {
    // 添加附件
    FileSystemResource fileSystemResource = new FileSystemResource(attach);
    // 参数一为附件名称
    mimeMessageHelper.addAttachment(fileSystemResource.getFilename(), fileSystemResource);
    }
    }
    javaMailSender.send(mimeMessage);
    System.out.println("带图片和附件的邮件发送成功");
    return true;
    } catch (MessagingException e) {
    e.printStackTrace();
    System.out.println("带图片和附件邮件发送失败");
    return false;
    }
    }
    /**
    * 发送由freemarker模板技术生成的邮件
    * @param javaMailSenderInfo
    * @return
    */
    public static boolean sendFreemarkerMail(JavaMailSenderInfo javaMailSenderInfo) {
    // 创建邮件消息 简单邮件可直接使用SimpleMailMessage
    MimeMessage mimeMessage = javaMailSender.createMimeMessage();
    MimeMessageHelper mimeMessageHelper = null;
    try {
    mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "utf-8");
    setMailCommonField(mimeMessageHelper, javaMailSenderInfo);
    /**
    * 此处没有实现采用模板技术(可自行探索)
    * 封装模板所需要的数据
    * 读取freemarker的模板文件 xxx.ftl 进行静态化,生成html形式的字符串
    * 将生成好的html字符串设置到邮件的正文中
    */
    javaMailSender.send(mimeMessage);
    System.out.println("freemarker模板技术生成的邮件发送成功");
    return true;
    } catch (MessagingException e) {
    e.printStackTrace();
    System.out.println("freemarker模板技术生成的邮件发送失败");
    return false;
    }
    }
    /**
    * 设置邮件的公共字段
    * @param mimeMessageHelper
    * @param javaMailSenderInfo
    * @throws MessagingException
    */
    private static void setMailCommonField(MimeMessageHelper mimeMessageHelper, JavaMailSenderInfo javaMailSenderInfo) throws MessagingException {
    // 发件人
    mimeMessageHelper.setFrom(InitJavaMailSender.username);
    // 收件人 多人用数组
    mimeMessageHelper.setTo(javaMailSenderInfo.getToAddress());
    // 主题
    mimeMessageHelper.setSubject(javaMailSenderInfo.getSubject());
    // 日期
    mimeMessageHelper.setSentDate(new Date());
    }
    }
    

四、使用springboot发送邮件

  • 使用springboot发送邮件和使用spring提供的JavaMailSender发送邮件的方式一样

  • 在yml配置文件中配置相关的会话信息后

  • 在service层中直接注入使用即可

  • 导入依赖

  • <!--springboot整合mail-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
    
  1. 修改配置

    # 邮件的设置 导入mail启动包 使用时注入直接JavaMailSender即可
    spring:
    mail:
    protocol: smtp
    host: smtp.qq.com
    port: 465
    default-encoding: utf-8
    username: 邮箱用户名
    password: 邮箱授权码
    test-connection: true
    properties:
    mail:
    debug: true
    smtp:
    auth: true
    timeout: 20000
    ssl:
    enable: true
    
  2. 直接在service层中使用即可

    public MailServiceImpl {
    @Autowired
    private JavaMailSender javaMailSender;
    // 以下代码使用即可
    ...
    }
    
版权声明
本文为[xiaokantianse]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/xiaokantianse/p/13948245.html

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云