Email should be one of the must-have extensions to your website, sign up for verification, forget your password, or send marketing messages to users.
I. Mail protocol
In the process of sending and receiving emails, you need to comply with the following protocols:
- Protocol for sending E-mail:
SMTP
; - Protocol for receiving E-mail:
POP3
andIMAP
.
1.1 what isSMTP
?
SMTP is the Simple Mail Transfer Protocol (SMTP). It is a set of specifications for transferring mails from source addresses to destination addresses to control the Transfer mode of mails. SMTP authentication requires users to provide an account and password to log in to the server, which is designed to prevent users from being invaded by spam.
1.2 what isIMAP
?
The Internet Message Access Protocol (IMAP) allows users to obtain and download mail information from mail servers. IMAP, like POP, is a mail retrieval protocol.
1.3 what isPOP3
?
POP3 is short for Post Office Protocol 3 (Post Office Protocol 3). POP3 allows clients to remotely manage emails on servers. POP3 is often used for offline mail processing, which allows clients to download server messages and then the messages on the server will be deleted. At present, many POP3 mail servers only provide the function of downloading mail, the server itself does not delete mail, this is an improved version of the POP3 protocol.
1.4 IMAP
andPOP3
What’s the difference in the protocol?
The biggest difference between the two is that IMAP allows bidirectional communication. That is, operations performed on the client side are reported back to the server. For example, operations such as receiving emails or marking read on the client side are synchronized by the server. Although POP protocol also allows the client to download server mail, but the operations on the client side will not be synchronized to the server above, such as receiving or marking read mail on the client side, the server will not synchronize these operations.
2. Initial configuration
2.1 Enabling the Mail Service
This article only takes QQ mailbox and 163 mailbox as examples.
QQ
Mailbox Open the mail service document163
Mailbox Open the mail service document
2.2 pom.xml
Normally we would use JavaMail apis to write code for sending emails, but Spring Boot now provides a package that is much easier to use.
spring-boot-starter-mail
:Spring Boot
Mail service;spring-boot-starter-thymeleaf
Use:Thymeleaf
Create email templates.
<! - the test package -- -- >
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<! --mail -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<! Create a mail template with Thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<! -- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>1.8.4</scope>
</dependency>
Copy the code
2.3 application.yml
The spring-boot-starter-mail configuration is provided by the MailProperties configuration class.
The configuration is slightly different for different mailboxes. The following is the configuration of QQ mailbox and 163 mailbox.
server: port: 8081 #spring: # mail: # # # QQ email https://service.mail.qq.com/cgi-bin/help?subtype=1&&no=1001256&&id=28 host: Smtp.qq.com # # email account # username: [email protected] # # email authorization code (not password) # password: password # default-encoding: UTF-8 # properties: # mail: # smtp: # auth: true # starttls: # enable: true # required: true spring: mail: # 163 mailbox http://help.mail.163.com/faqDetail.do?code=d7a5dc8471cd0c0e8b4b8f4f8e49998b374173cfe9171305fa1ce630d7f67ac2cda80145a1742 516 host: smtp.163.com # email account username: [email protected] # email authorization code password: password default-encoding: UTF-8 properties: mail: smtp: auth: true starttls: enable: true required: trueCopy the code
2.4 Mail Information
To save the message subject, message content and other information when sending a message
@Data
public class Mail {
/** * Email id */
private String id;
/** * Email sender */
private String sender;
/** * Email recipients (multiple email addresses are separated by commas (",") */
private String receiver;
/** * Email subject */
private String subject;
/** * Email content */
private String text;
/** * Attachment/file address */
private String filePath;
/** * Attachment/file name */
private String fileName;
/** * Whether there is an attachment (default no) */
private Boolean isTemplate = false;
/** * Template name */
private String emailTemplateName;
/** * Template content */
private Context emailTemplateContext;
}
Copy the code
Three, the realization of sending emails
3.1 Checking the entered Mail configuration
Verify email recipient, email subject, and email content
private void checkMail(Mail mail) {
if (StringUtils.isEmpty(mail.getReceiver())) {
throw new RuntimeException("Mail addressee cannot be empty.");
}
if (StringUtils.isEmpty(mail.getSubject())) {
throw new RuntimeException("Email subject cannot be empty");
}
if (StringUtils.isEmpty(mail.getText()) && null == mail.getEmailTemplateContext()) {
throw new RuntimeException("Email content cannot be empty."); }}Copy the code
3.2 Saving Emails to the database
After the mail is sent, the mail is saved to the database for collecting statistics and tracing mail problems.
private Mail saveMail(Mail mail) {
// ToDO send success/failure synchronize mail information to database
return mail;
}
Copy the code
3.3 Sending Emails
- Send plain text messages
public void sendSimpleMail(Mail mail){
checkMail(mail);
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setFrom(sender);
mailMessage.setTo(mail.getReceiver());
mailMessage.setSubject(mail.getSubject());
mailMessage.setText(mail.getText());
mailSender.send(mailMessage);
saveMail(mail);
}
Copy the code
- Send mail and carry attachments
public void sendAttachmentsMail(Mail mail) throws MessagingException {
checkMail(mail);
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(sender);
helper.setTo(mail.getReceiver());
helper.setSubject(mail.getSubject());
helper.setText(mail.getText());
File file = new File(mail.getFilePath());
helper.addAttachment(file.getName(), file);
mailSender.send(mimeMessage);
saveMail(mail);
}
Copy the code
- Send template email
public void sendTemplateMail(Mail mail) throws MessagingException {
checkMail(mail);
// templateEngine replaces dynamic parameters to produce the final HTML
String emailContent = templateEngine.process(mail.getEmailTemplateName(), mail.getEmailTemplateContext());
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(sender);
helper.setTo(mail.getReceiver());
helper.setSubject(mail.getSubject());
helper.setText(emailContent, true);
mailSender.send(mimeMessage);
saveMail(mail);
}
Copy the code
4. Test and optimization
4.1 Unit Test
- When testing attachment mail, the attachment is placed
static
Under the folder; - When testing the template email, the template is placed in
file
Under the folder.
@RunWith(SpringRunner.class)
@SpringBootTest
public class MailServiceTest {
@Resource
MailService mailService;
/** * Send plain text message */
@Test
public void sendSimpleMail(a) {
Mail mail = new Mail();
// mail.setReceiver("[email protected]");
mail.setReceiver("[email protected]");
mail.setSubject("Test simple mail");
mail.setText("Test simple content");
mailService.sendSimpleMail(mail);
}
/** ** Send mail and bring attachments */
@Test
public void sendAttachmentsMail(a) throws MessagingException {
Mail mail = new Mail();
// mail.setReceiver("[email protected]");
mail.setReceiver("[email protected]");
mail.setSubject("Test attachment mail");
mail.setText("Contents of the Attached Mail");
mail.setFilePath("file/dusty_blog.jpg");
mailService.sendAttachmentsMail(mail);
}
/** * Test template email */
@Test
public void sendTemplateMail(a) throws MessagingException {
Mail mail = new Mail();
// mail.setReceiver("[email protected]");
mail.setReceiver("[email protected]");
mail.setSubject("Test Template Email");
// Create template body
Context context = new Context();
// Set the template parameters to be replaced
context.setVariable("verifyCode"."6666");
mail.setEmailTemplateContext(context);
// Template name (templates are in the templates directory)
mail.setEmailTemplateName("emailTemplate"); mailService.sendTemplateMail(mail); }}Copy the code
4.2 optimization
Since there are cc/BCC requirements for sending mail, we encapsulate an entity and utility class to make it easy to call the mail service directly.
- Mail message class
@Data
public class MailDomain {
/** * Email id */
private String id;
/** * Email sender */
private String sender;
/** * Email recipients (multiple email addresses are separated by commas (",") */
private String receiver;
/** * Email subject */
private String subject;
/** * Email content */
private String text;
/** * cc (multiple mailboxes are separated by commas ",") */
private String cc;
/** * encryption (multiple mailboxes are separated by commas (,") */
private String bcc;
/** * Attachment/file address */
private String filePath;
/** * Attachment/file name */
private String fileName;
/** * Whether there is an attachment (default no) */
private Boolean isTemplate = false;
/** * Template name */
private String emailTemplateName;
/** * Template content */
private Context emailTemplateContext;
/** * Send time (future send time can be specified) */
private Date sentDate;
}
Copy the code
- Mail tool class
@Component
public class EmailUtil {
@Resource
private JavaMailSender mailSender;
@Resource
TemplateEngine templateEngine;
@Value("${spring.mail.username}")
private String sender;
/** * Build the complex mail message class *@param mail
* @throws MessagingException
*/
public void sendMail(MailDomain mail) throws MessagingException {
//true: complex types are supported
MimeMessageHelper messageHelper = new MimeMessageHelper(mailSender.createMimeMessage(), true);
// The mail sender reads from the configuration item
mail.setSender(sender);
// The sender of the email
messageHelper.setFrom(mail.getSender());
// The recipient of the email
messageHelper.setTo(mail.getReceiver().split(","));
// The subject of the message
messageHelper.setSubject(mail.getSubject());
// The content of the email
if (mail.getIsTemplate()) {
// templateEngine replaces dynamic parameters to produce the final HTML
String emailContent = templateEngine.process(mail.getEmailTemplateName(), mail.getEmailTemplateContext());
messageHelper.setText(emailContent, true);
}else {
messageHelper.setText(mail.getText());
}
/ / cc
if(! StringUtils.isEmpty(mail.getCc())) { messageHelper.setCc(mail.getCc().split(","));
}
/ / send
if(! StringUtils.isEmpty(mail.getBcc())) { messageHelper.setCc(mail.getBcc().split(","));
}
// Add mail attachments
if(mail.getFilePath() ! =null) {
File file = new File(mail.getFilePath());
messageHelper.addAttachment(file.getName(), file);
}
// Send time
if (StringUtils.isEmpty(mail.getSentDate())) {
messageHelper.setSentDate(mail.getSentDate());
}
// Officially send the email
mailSender.send(messageHelper.getMimeMessage());
}
/** * Detect mail messages *@param mail
*/
private void checkMail(MailDomain mail) {
if (StringUtils.isEmpty(mail.getReceiver())) {
throw new RuntimeException("Mail addressee cannot be empty.");
}
if (StringUtils.isEmpty(mail.getSubject())) {
throw new RuntimeException("Email subject cannot be empty");
}
if (StringUtils.isEmpty(mail.getText()) && null == mail.getEmailTemplateContext()) {
throw new RuntimeException("Email content cannot be empty."); }}/** * Save the message to the database *@param mail
* @return* /
private MailDomain saveMail(MailDomain mail) {
// ToDO send success/failure synchronize mail information to database
returnmail; }}Copy the code
See the Github sample code for details, which I won’t post here.
Five, summary and extension
5.1 Asynchronous Sending
Most of the time, mail delivery is not an outcome that our main business must care about, such as notification class, notification class business can allow delay or failure. At this time, asynchronous mail can be sent to speed up the execution of the main transaction. In the actual project, MQ mail sending parameters can be used to monitor the message queue and start sending mail.
5.2 Sending Failure
There are always mail sending failures due to various reasons, such as too frequent mail sending and network exceptions. In this case, we generally consider sending the email again, which can be divided into the following steps to achieve:
- After receiving the request to send mail, first record the request and put it into the database;
- Call the mail sending interface to send mail, and record the sending result into the database;
- During the period when periodic system scanning is started, the system fails to send messages and the number of retries is smaller than the number of retries
3
To send the message again.
5.3 Other Questions
Mail port problems and attachment size problems.
5.4 Sample code address
-
Github sample code
-
Spring Boot series articles, welcome to pay attention to the dust blog!
5.5 Technical Exchange
- Over the blog
- Dust blog – Gold digging
- Travelogue Blog – Blog Garden
- Github
- The public,