Java realizes the mail sending of multiple attachments

Posted by ldougherty on Thu, 03 Mar 2022 22:49:21 +0100

Narration: This paper mainly describes how to integrate and realize multi attachment e-mail sending in Springboot, and takes the QQ mailbox server as the e-mail server to send e-mail;

1. Preliminary preparation

What is the main need?

  • First, you should know the sending mail server provided by the server where the email account you choose to send mail is located (generally there will be a sending mail server and receiving mail server), and the QQ mailbox is;
  • Second, the port number of the sending mail server;
  • Third, you should set the authorization code for the mailbox that sends the email. This authorization code is the password that the third party needs to log in when using the mailbox for a series of operations;

The first and second information locations are as follows (QQ mailbox, other mailboxes are also similar, you can turn it if necessary):

Turn down and find the settings in the figure below. First start the service: IMAP/SMTP. Generally speaking, this service is an account authentication service setting used in the development process. After opening it, click step 4~

After clicking the connection in step 4, you can see the following page. Turn down and you will see the enclosed information in the figure~

Two thirds of the data we need will be found, leaving the third one. In fact, the third one is the operation of step 5 in the previous screenshot. Click the button link of step 5, as shown in the following figure:

Use the security phone in the figure above to send a message with the content of [configure email client] to the number [1069070069] in the box. After sending, click the [I have sent] button. If the server of QQ email receives your message, I will return you a 16 bit string as shown in the figure below (I stole the picture and I still remember my previous operation. Send it to me at will~ 🤣🤣🤣), Copy and save the string;

en~, the pre preparation work is OK. Let's start the code;

2. Code

There is no superfluous description. There are comments in the code. If you encounter trouble, you may be wordy~

2.1 pom file

<!-- javamail  -  mailbox jar -->
 <dependency>
     <groupId>javax.mail</groupId>
     <artifactId>mail</artifactId>
     <version>1.4.7</version>
 </dependency>

2.1. Controller layer

package com.java.product.module.controller;

import com.java.product.module.utils.MailSendUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.macrocloud.kernel.model.reqres.response.ResponseData;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("/mail")
@Api(value = "Mail sending", tags = "Send mail")
public class MailController {

    /**
     * Send mail with attachments
     *
     * @param sendMail        Sender mailbox
     * @param sendMailPwd     Sender password
     * @param sendMailName    Sender nickname (optional)
     * @param receiveMail     Recipient mailbox
     * @param receiveMailName Recipient nickname (optional)
     * @param sendSMTPHost    The SMTP server address of the sender's mailbox must be accurate. Different mail server addresses are different. The general (just general, by no means absolute) format is: SMTP xxx. com
     * @param title           Mail subject
     * @param content         Message body
     * @param files           Uploaded file collection
     * @param port            Mail server send mail port
     */
    @PostMapping("/sendFileMail")
    @ApiOperation(value = "File mail", notes = "sendMail(Sender mailbox),sendMailPwd(Sender password),sendMailName(Sender nickname-Optional), receiveMail(Recipient mailbox),receiveMailName(Recipient nickname-Optional), sendSMTPHost(Sender's mailbox SMTP server address),title(Mail subject),content(Message body)")
    public ResponseData sendFileMail(String sendMail, String sendMailPwd, String sendMailName, String[] receiveMail, String receiveMailName, String sendSMTPHost, String title, String content,
                                     MultipartFile[] files, String port) {
        try{
            MailSendUtil.sendFileMail(sendMail, sendMailPwd, sendMailName, receiveMail, receiveMailName, sendSMTPHost, title, content,
                    files, port);
        }catch (Exception e){
            return ResponseData.error(e.toString());
        }
        return ResponseData.success();
    }
}

Utils tool class

package com.java.product.module.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.*;
import javax.mail.util.ByteArrayDataSource;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Pattern;

/**
 * @description: Mail sending tool class
 * @author: limingxin
 * @time: 2020/7/21 0021 10:11
 */
@Slf4j
public class MailSendUtil {

    /**
     * Mailbox regular expression
     */
    static final Pattern pattern = Pattern.compile("^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$");

    /**
     * Send mail with attachments
     *
     * @param sendMail        Sender mailbox
     * @param sendMailPwd     Sender password
     * @param sendMailName    Sender nickname (optional)
     * @param receiveMail     Recipient mailbox
     * @param receiveMailName Recipient nickname (optional)
     * @param sendSMTPHost    The SMTP server address of the sender's mailbox must be accurate. Different mail server addresses are different. The general (just general, by no means absolute) format is: SMTP xxx. com
     * @param title           Mail subject
     * @param content         Message body
     * @param port            Mail server send mail port
     *
     */
    public static void sendFileMail(String sendMail, String sendMailPwd, String sendMailName, String[] receiveMail, String receiveMailName,
                                    String sendSMTPHost, String title, String content, MultipartFile[] files, String port) {

        Session session = createSSLSession(sendSMTPHost, port, sendMailName, sendMailPwd);
        // 3. Create an email
        MimeMessage message;
        try {
            message = createMimeMessage(session, sendMail, sendMailName, receiveMail, receiveMailName, title, content);
            // 5. Content: email body (html tag can be used) (the content is suspected of advertising, so as to avoid being mistaken by the email server for indiscriminate advertising and return failure. Please modify the sending content)
            MimeMultipart mm = new MimeMultipart();
            MimeBodyPart text = new MimeBodyPart();
            text.setContent(content, "text/html;charset=UTF-8");
            mm.addBodyPart(text);
            if (files.length > 0) {
                for (MultipartFile f : files) {
                    // Convert MultipartFile to InputStream
                    byte [] byteArr=f.getBytes();
                    InputStream inputStream = new ByteArrayInputStream(byteArr);
                    MimeBodyPart attachment = new MimeBodyPart();
                    DataSource source = new ByteArrayDataSource(inputStream, "application/msexcel");
                    attachment.setDataHandler(new DataHandler(source));
                    // Set the file name of the attachment (encoding required)
                    attachment.setFileName(MimeUtility.encodeText(f.getOriginalFilename()));
                    // 10. Set the relationship between text and attachment (synthesize a large hybrid "node" / Multipart)
                    // If there are multiple attachments, you can create multiple attachments and add them multiple times
                    mm.addBodyPart(attachment);
                }
            }
            message.setContent(mm);
            message.saveChanges();
            // 4. Get the mail transmission object according to the Session
            Transport transport = session.getTransport("smtp");
            transport.connect(sendSMTPHost, sendMail, sendMailPwd);
            // 6. Send mail to all receiving addresses, message Getallrecipients() gets all the recipients, CC and BCC added when creating the mail object
            transport.sendMessage(message, message.getAllRecipients());
            // 7. Close the connection
        } catch (Exception e) {
            log.error("", e);
        }

    }

    /**
     * Create session
     */
    private static Session createSSLSession(String sendSMTPHost, String port, String userName, String pwd) {
        // 1. Create parameter configuration, which is used to connect to the parameter configuration of the mail server
        Properties props = new Properties(); // Parameter configuration

        props.setProperty("mail.smtp.user", userName);
        props.setProperty("mail.smtp.password", pwd);
        props.setProperty("mail.smtp.host", sendSMTPHost);
        props.setProperty("mail.smtp.port", port);
        props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.setProperty("mail.smtp.socketFactory.fallback", "false");
        props.setProperty("mail.smtp.socketFactory.port", port);
        props.put("mail.smtp.auth", "true");

        // 2. Create a session object according to the configuration to interact with the mail server
        Session session = Session.getDefaultInstance(props, new Authenticator() {
            //identity authentication 
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(userName, pwd);
            }
        });
        session.setDebug(true); // Set the debug mode to view the detailed sending log
        return session;
    }

}

3. Test interface

Here's an explanation. I didn't use swagger to debug my interface. Many people may wonder why I configured swagger but didn't use it? Because in swagger, only one book with the same collection name can exist, that is to say, I can't measure the effect of multiple files uploading at the same time. Well, I can only use postMan like this!


The returned data result says that the request is successful. Then I log in to my recipient account to see if the data exists normally~

The first one is at least successful. It depends on the attachments inside;

OK, the file is normal! Everything is normal~

4. Upload file control

In addition, there is a problem. Since file upload is involved, a file upload control is required. The following code is added to the configuration file [application.yml]:

spring:
  # Enable file upload control
  servlet:
    multipart:
      enabled: true
      # Threshold for writing files to disk
      file-size-threshold: 1KB
      # Maximum file size
      max-file-size: 10MB
      # Maximum request size
      max-request-size: 200MB

pass: if you don't understand anything in the article, you are welcome to ask questions, work together and make progress together!