邮箱功能简介

  • 要在网络上实现邮件功能,必须要有专门的邮件服务器。直接百度即可,如qq邮箱的smtp服务器为smtp.qq.com
  • image.png

    协议

  • SMTP协议 发送邮件的协议

    • 通常把处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。
    • 常用smtp端口一般是465/587/25 具体看邮箱服务商的规定
  • POP3协议 接收邮件的协议
    • 通常把处理用户pop3请求(邮件接收请求)的服务器称之为POP3服务器(邮件接收服务器)。
  • IMAP:接收,它使用标准端口143和加密端口993。IMAP和POP3的主要区别是,IMAP协议在本地的所有操作都会自动同步到服务器上,并且,IMAP可以允许用户在邮件服务器的收件箱中创建文件夹。

    准备

  • 第三方代理收发邮件功能需要在邮箱服务中开启smtppop3功能,并取得授权码

    导入依赖

    1. <dependency>
    2. <groupId>javax.mail</groupId>
    3. <artifactId>javax.mail-api</artifactId>
    4. <version>1.6.2</version>
    5. </dependency>
    6. <dependency>
    7. <groupId>com.sun.mail</groupId>
    8. <artifactId>javax.mail</artifactId>
    9. <version>1.6.2</version>
    10. </dependency>

    发邮件

    ```java package com.boot.service;

import javax.mail.*; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import java.util.Properties;

public class EmailService { public static void main(String[] args) throws MessagingException { String smtp = “smtp.qq.com”; // 登录用户名(邮箱账号): String username = “1743430691@qq.com”; // 登录口令(第三方收发功能授权码): String password = “vqhjbasxvzsxccgg”; // 连接到SMTP服务器587端口: Properties props = new Properties(); //配置信息类,存储配置 props.put(“mail.smtp.host”, smtp); // SMTP主机名 props.put(“mail.smtp.port”, “587”); // 主机端口号 props.put(“mail.smtp.auth”, “true”); // 是否需要用户认证 props.put(“mail.smtp.starttls.enable”, “true”); // 启用TLS加密 // 获取Session实例: Session session = Session.getInstance(props, new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(username, password); } }); // 设置debug模式便于调试: session.setDebug(true);

  1. MimeMessage message = new MimeMessage(session);
  2. // 设置发送方地址:
  3. message.setFrom(new InternetAddress("1743430691@qq.com"));
  4. // 设置接收方地址:
  5. message.setRecipient(Message.RecipientType.TO, new InternetAddress("768854737@qq.com"));
  6. // 设置邮件主题(标题):
  7. message.setSubject("Hello", "UTF-8");
  8. // 设置邮件正文:
  9. message.setText("Hi Xiaoming...", "UTF-8");
  10. // 发送:
  11. Transport.send(message);

} }

<a name="tRihw"></a>
## 发送HTML邮件

- 把:`message.setText(body, "UTF-8");`  改为:`message.setText(body, "UTF-8", "html");`,body传入`html`代码字符串即可
   - 不一定要传入完整的html源码,只传入部分就能识别,如传`<h1>Hello</h1><p>Hi, xxx</p>`  无需<html>这些即可
<a name="MZDfD"></a>
## 发送附件邮件

- 取消原本的`message.setText()`,改为构造Multipart对象,将内容,附件等信息传入Multipart中,然后`message.setContent(multipart)`
   - 一个Multipart对象可以添加若干个BodyPart,其中第一个BodyPart是文本,即邮件正文,后面的BodyPart是附件
   - 如果添加文本,用`setContent("...", "text/plain;charset=utf-8")`添加纯文本,或者用`setContent("...", "text/html;charset=utf-8")`添加HTML文本。
   - 如果添加附件,需要设置文件名(不一定和真实文件名一致),并且添加一个`DataHandler()`,传入文件的MIME类型。二进制文件可以用`application/octet-stream`,Word文档则是`application/msword`。
```java
 String body = "这是一封附件邮件...";
        Multipart multipart = new MimeMultipart();
        InputStream input=new FileInputStream("C:\\Users\\Lw\\Desktop\\sdfaf.txt");
// 添加内容:
        BodyPart textpart = new MimeBodyPart();
        textpart.setContent(body, "text/html;charset=utf-8");
        multipart.addBodyPart(textpart);
// 添加附件:
        BodyPart imagepart = new MimeBodyPart();
        imagepart.setFileName("附件1.txt");
        imagepart.setDataHandler(new DataHandler(new ByteArrayDataSource(input, "application/octet-stream")));
        multipart.addBodyPart(imagepart);
// 设置邮件内容为multipart:
        message.setContent(multipart);
        // 发送:
        Transport.send(message);

HTML邮件内嵌图片

  • 一般情况下<img>引入的外部图片链接通常会被邮件客户端过滤,并提示用户显示图片并不安全。只有内嵌的图片才能正常在邮件中显示。

    • 在HTML邮件中引用图片时,需要设定一个ID,用类似Email - 图2引用
    • 在添加图片作为BodyPart时,除了要正确设置MIME类型(根据图片类型使用image/jpegimage/png),还需要设置一个Header:imagepart.setHeader("Content-ID", "<img01>");
      Multipart multipart = new MimeMultipart();
      // 添加text:
      BodyPart textpart = new MimeBodyPart();
      textpart.setContent("<h1>Hello</h1><p><img src=\"cid:img01\"></p>", "text/html;charset=utf-8");
      multipart.addBodyPart(textpart);
      // 添加image:
      BodyPart imagepart = new MimeBodyPart();
      imagepart.setFileName(fileName);
      imagepart.setDataHandler(new DataHandler(new ByteArrayDataSource(input, "image/jpeg")));
      // 与HTML的<img src="cid:img01">关联:
      imagepart.setHeader("Content-ID", "<img01>");
      multipart.addBodyPart(imagepart);
      

      常见问题

      常见问题

  • 如果用户名或口令错误,会导致535登录失败:

DEBUG SMTP: AUTH LOGIN failed Exception **in** thread "main" javax.mail.AuthenticationFailedException: 535 5.7.3 Authentication unsuccessful [HK0PR03CA0105.apcprd03.prod.outlook.com]

  • 如果登录用户和发件人不一致,会导致554拒绝发送错误:

DEBUG SMTP: MessagingException **while** sending, **THROW**: com.sun.mail.smtp.SMTPSendFailedException: 554 5.2.0 STOREDRV.Submission.**Exception**:SendAsDeniedException.MapiExceptionSendAsDenied;

  • 有些时候,如果邮件主题和正文过于简单,会导致554被识别为垃圾邮件的错误:

DEBUG SMTP: MessagingException **while** sending, THROW: com.sun.mail.smtp.SMTPSendFailedException: 554 DT:SPM

收邮件

  • 很少需要用到这种功能,自己看:链接

    springboot中发送Email

    配置

    spring:
    mail:
      host: smtp.qq.com
      port: 465   #587和465是qq邮箱smtp的2个端口,一个不行时换一个试试
      username: 1743430691@qq.com
      password: nzsqldzfmuwnfbda   
      protocol: smtp     #协议
      test-connection: true
      default-encoding: UTF-8
      properties:
        mail.smtp.auth: true
        mail.smtp.starttls.enable: true
        mail.smtp.starttls.required: true
        mail.smtp.ssl.enable: true   //qq邮箱需要开启ssl,别的不清楚
        mail.display.sendmail: spring-boot-demo
    

    依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
      </dependency>
      <!-- 模板引擎利于动态添加数据到html中-->
         <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
      </dependency>
    

    使用

  • 不同类型的邮件有不同类,不过有一些通用方法

    • setFrom(from);//发送者
    • setTo(to);//接收者
    • setSubject(title);//标题
    • setText(txt);//内容 内容即便是html等,也是通过api传入html路径或者名称就会得到渲染后的源码字符串
    • send(邮件对象);
  • 见springboot-demo