發送郵件
在日常工作和生活中經常會用到電子郵件。例如,當注冊一個新賬戶時,系統會自動給注冊郵箱發送一封激活郵件,通過郵件找回密碼,自動批量發送活動信息等。郵箱的使用基本包括這幾步:先打開瀏覽器并登錄郵箱,然后創建郵件再發送郵件。在這個過程中有大量的重復性工作且不能批量發送郵件,說明手動的方式效率太低。本節就介紹如何通過代碼完成發送郵件的功能。
SMTP與發送一封郵件的步驟
電子郵件在網絡中傳輸時需要遵從協議,常用的電子郵件協議包括SMTP、POP3、IMAP。其中,郵件的創建和發送只需要使用SMTP(Simple MailTransfer Protocol,簡單郵件傳輸協議)。
如果需要給客戶發送郵件,可以直接使用Java代碼發送。發送郵件的過程是先登錄指定的郵箱,然后再給用戶發送郵件,因此需要配置郵箱的權限或者SMTP。本小節以QQ郵箱作為收件人,介紹怎么配置163郵箱發送郵件。首先登錄163郵箱,選擇“設置”標簽,就會看到設置頁面如圖6.14所示。
必須開啟IMAP/SMTP服務和POP3/SMTP服務,開啟后可以看到服務器的地址,然后就可以使用Java配置163郵箱發送郵件了,這個很重要。
在網頁上創建并發送一封電子郵件的步驟如下:
(1)創建一個郵件對象(MimeMessage)。
(2)設置發件人、收件人,可以增加多個收件人、抄送人。
(3)設置郵件的主題(標題)。
(4)設置郵件的正文(內容)。
(5)設置郵件的發送時間。
(6)發送郵件。
同理,在Java中發送郵件的步驟和上面相似,完成上述步驟就能成功發送郵件,具體的代碼實現后面會詳細介紹。
實戰:使用Java Mail發送郵件
前面簡述了郵件的發送過程,下面使用Java的API完成郵件的發送。
(1)在pom.xml中添加E-mail的依賴坐標:
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
(2)編寫發送郵件的代碼:
package com.example.springextenddemo.email;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.Properties;
/**
* Java 發送郵件
*/
public class JavaSendMailDemo {
/**
* 郵箱賬戶
*/
public static String emailAddress = "changhe626@163.com";
/**
* 授權碼 */
public static String emailPassword = "OTLXYXXOELTJRMSO";
// 發件人郵箱的SMTP服務器地址
public static String smtpHost = "smtp.163.com";
public static void main(String[] args) throws Exception {
// 1. 創建參數配置,用于連接郵件服務器的參數配置
Properties props = new Properties();
// 使用的協議(JavaMail規范要求)
props.setProperty("mail.transport.protocol", "smtp");
// 發件人郵箱的SMTP服務器地址
props.setProperty("mail.smtp.host", smtpHost);
// 是否需要請求認證
props.setProperty("mail.smtp.auth", "true");
// 2. 根據配置創建會話對象,用于和郵件服務器進行交互
Session session = Session.getInstance(props);
// 設置為debug模式,觀察詳細的發送日志
session.setDebug(true);
// 3. 創建一封郵件
MimeMessage message = createMimeMessage(session,
emailAddress,"1507775353@qq.com");
// 4. 根據 Session 獲取郵件傳輸對象
Transport transport = session.getTransport();
//5. 輸入郵箱賬號和密碼連接郵件服務器,這里認證的郵箱必須與message中的發
件人郵箱一致,否則會報錯
transport.connect(emailAddress, emailPassword);
// 6.給所有的收件地址發送郵件,message.getAllRecipients() 獲取的是在
創建郵件對象時添加的所有收件人、抄送人、密送人
transport.sendMessage(message, message.getAllRecipients());
// 7. 關閉連接
transport.close();
System.out.println("完成郵件的發送");
}
/**
* 創建一封只包含文本的簡單郵件
* @param session 和服務器交互的會話
* @param sendMailAddress 發件人郵箱
* @param receiveMailAddress 收件人郵箱
* @return * @throws Exception
*/
public static MimeMessage createMimeMessage(Session session,
String sendMailAddress,
String receiveMailAddress) throws Exception {
// 1. 創建一封郵件
MimeMessage message = new MimeMessage(session);
// 2. From: 發件人
message.setFrom(new InternetAddress(sendMailAddress, "紫龍
神","UTF-8"));
// 3. To: 收件人(可以增加多個收件人、抄送和密送)
message.setRecipient(MimeMessage.RecipientType.TO, new
Internet Address(receiveMailAddress, "你好", "UTF-8"));
// 4. Subject: 郵件主題
message.setSubject("你好,請問你吃飯了沒有啊", "UTF-8");
// 5. Content: 郵件正文(可以使用HTML標簽)
message.setContent("你好,許久不見,想問問你吃飯了沒有啊",
"text/html; charset=UTF-8");
// 6. 設置發件時間
message.setSentDate(new Date());
// 7. 保存設置
message.saveChanges();
return message;
}
}
上述代碼演示了郵件從創建到發送的過程。運行代碼,控制臺上打印的發送郵件的日志如圖6.15所示,發件箱的發送記錄如圖6.16所示,收件箱的收件記錄如圖6.17所示。可以看到,已經成功發送郵件。
說明:在實際開發中,一般會把郵件發送封裝成一個工具類,然后再配置一個只發送郵件的郵箱,最后直接調用工具類完成郵件的發送。
實戰:Spring Boot集成郵件發送
Spring Boot為郵件發送功能提供了自動配置類,開發者只需要加入相關依賴,然后再配置郵箱的基本信息就可以發送郵件了,相較于郵件發送工具,類更加簡便。
下面介紹在Spring Boot項目中如何實現郵件發送的功能。
(1)在application.properties中添加E-mail配置文件,內容如下:
#email config
spring.mail.host=smtp.163.com
spring.mail.port=25
spring.mail.username=changhe626@163.com
spring.mail.password=OTLXYXXOELTJRMSO
spring.mail.default-encoding=UTF-8
spring.mail.properties.mail.debug=true
(2)編寫郵件發送的服務類和具體方法:
package com.example.springextenddemo.email;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import java.util.Date;
@Service
public class SpringEmailService {
@Autowired
private JavaMailSender javaMailSender;
/**
* 輸入發件人的郵箱地址
*/
@Value("${spring.mail.username}")
private String from;
public void sendSimpleMail() {
SimpleMailMessage message = new SimpleMailMessage();
message.setSubject("Spring 郵件發送");
message.setFrom(from);
message.setTo("1507775353@qq.com");
message.setSentDate(new Date());
message.setText("這是使用Spring發送郵件");
javaMailSender.send(message);
}
}
(3)新建一個郵件發送的Controller作為Web入口,其中包括發送郵件的方法:
package com.example.springextenddemo.controller;
import com.example.springextenddemo.email.SpringEmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EmailController {
@Autowired
private SpringEmailService springEmailService;
@GetMapping("/sendEamil")
public String sendEmail(){
springEmailService.sendSimpleMail();
return "send success";
}
}
(4)啟動當前項目,訪問localhost:8080/sendE mail,在控制臺能看到郵件發送成功的提示。查看控制臺打印的日志,如圖6.18所示,收件箱收到的郵件如圖6.19所示。
在Spring Boot中添加完E-mail的依賴和E-mail的配置文件后,SpringBoot會自動把E-mail的配置注入郵件的發送配置類中,不需要再手動配置。
使用的配置類是MailSender- AutoConfiguration,其中的部分源碼如下:
package org.springframework.boot.autoconfigure.mail;
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({MimeMessage.class, MimeType.class,
MailSender.class})
@ConditionalOnMissingBean({MailSender.class})
@Conditional({MailSenderAutoConfiguration.MailSenderCondition.class})
@EnableConfigurationProperties({MailProperties.class})
@Import({MailSenderJndiConfiguration.class, MailSenderProperties
Configuration.class})
public class MailSenderAutoConfiguration {
static class MailSenderCondition extends AnyNestedCondition {
MailSenderCondition() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
}
@ConditionalOnProperty(
prefix = "spring.mail",
name = {"jndi-name"}
)
static class JndiNameProperty {
JndiNameProperty() {
}
}
@ConditionalOnProperty(
prefix = "spring.mail",
name = {"host"}
)
static class HostProperty {
HostProperty() {
}
}
}
}
在
MailSenderAutoConfiguration類中可以看到還導入了另外一個配置類,即Mail-?SenderPropertiesConfiguration類,其部分源碼如下:
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnProperty(
prefix = "spring.mail",
name = {"host"}
)
MailSenderPropertiesConfiguration類獲取application.properties中E-mail的配置文件,把application.properties中E-mail的相關配置組裝成E-mail的配置對象,然后注入Spring容器中,這樣用戶就可以方便地發送Email,不需要再手動配置E-mail信息了。
擴展知識——郵件格式
電子郵件因為其傳播的廣泛性,所以必須具備公共認同的格式,以便于客戶端郵箱軟件識別、拆解相應的信息。
電子郵件本身是由ASCII字符構成,總體上分為郵件頭和郵件體兩部分,允許字符編碼、附件和壓縮等多樣化的格式。郵件體實際上是由一行行的字符構成的簡單序列,它和郵件頭是靠一個空行(該行只有一個回車換行符CRLF)來區分的。