Java实现收发邮件

154 阅读2分钟

前言

谈到邮箱的发送与接收,就不得不提到两个应用层的协议,SMTP协议和IMAP协议。两者都是基于TCP的协议。

SMTP协议是一种用于发送电子邮件的协议,只负责邮件的发送。如果要接收邮件,就需要用到IMAP协议,与POP3协议类似,但功能更强大,可以访问邮件服务器上的多个邮件文件夹,并支持邮件的同步和搜索。

下文我们基于Java依次使用两种协议来实现收发邮件。

SMTP发送邮件

配置SmtpProperties

@Data
@Component
public class SmtpProperties {

    public final static String PROTOCOL = "smtp";

    @Value("${smtp.host}")
    private String host;
    @Value("${smtp.port}")
    private Integer port;
    @Value("${mail.username}")
    private String username;
    //授权码
    @Value("${mail.secretKey}")
    private String secretKey;

    public Properties generateSmtp() {
        Properties properties = new Properties();
        properties.put("mail.smtp.host", host); // SMTP主机名
        properties.put("mail.smtp.port", port);
        properties.put("mail.smtp.auth", "true"); // 是否需要用户认证
        properties.put("mail.smtp.starttls.enable", "true"); // 启用TLS加密
        properties.put("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");
        properties.put("mail.smtp.socketFactory.port", port);
        return properties;
    }
}

在nacos配置文件中配置域名、端口、用户名、密钥等

创建Session对象

session = Session.getInstance(prop.generateSmtp(), new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(prop.getUsername(), prop.getSecretKey());
    }
});

创建MimeMessage对象包装邮件并发送

try {
    // 创建默认的 MimeMessage 对象
    MimeMessage message = new MimeMessage(session);

    // 设置 From: 邮件发送方
    message.setFrom(new InternetAddress(from));

    // 设置 To: 邮件接收方
    message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));

    // 设置 Subject: 邮件主题
    message.setSubject("邮件主题");

    // 设置邮件正文
    Multipart multipart = new MimeMultipart();
    
    // 正文part:
    BodyPart textPart = new MimeBodyPart();
    textPart.setContent(send.getContext(), CONTEXT_TYPE);
    multipart.addBodyPart(textPart);
    
    //附件part
    BodyPart filePart = new MimeBodyPart();
    filePart.setFileName("文件名称");
    FileDataSource fileDataSource = new FileDataSource("文件路径");
    filePart.setDataHandler(new DataHandler(fileDataSource));
    multipart.addBodyPart(filePart);

    message.setContent(multipart);

    // 发送消息
    Transport.send(message);
    System.out.println("Sent message successfully....");
} catch (MessagingException mex) {
    mex.printStackTrace();
}

IMAP 接受邮件

配置ImapProperties

@Data
@Component
public class ImapProperties {

    public final static String PROTOCOL = "imap";

    @Value("${imap.host}")
    private String host;
    @Value("${imap.port}")
    private Integer port;
    @Value("${mail.username}")
    private String username;
    //授权码
    @Value("${mail.secretKey}")
    private String secretKey;
    //收件附件保存路径
    @Value("${mail.attachment.savePath}")
    private String savePath;

    public Properties generateProp() throws GeneralSecurityException {
        Properties properties = new Properties();
        properties.put("mail.store.protocol", PROTOCOL);
        properties.put("mail.imap.host", host);
        properties.put("mail.imap.port", port);
        properties.put("mail.imap.socketFactory.class","javax.net.ssl.SSLSocketFactory");
        return properties;
    }
}

连接邮箱,获取邮件

session = Session.getInstance(properties.generateProp());

// 创建IMAP store对象并连接到邮件服务器
store = (IMAPStore) session.getStore(ImapProperties.PROTOCOL);
store.connect(properties.getUsername(), properties.getSecretKey());

// 获取inbox文件夹 
Folder emailFolder = store.getFolder("INBOX"); 
emailFolder.open(Folder.READ_ONLY); 

// 从邮件文件夹中获取消息 
Message[] messages = emailFolder.getMessages(); 

// 逐一处理每封邮件
for (int i = 0; i < messages.length; i++) {
    Message message = messages[i];
    System.out.println("---------------------------------");
    System.out.println("Email Number " + (i + 1));
    System.out.println("Subject: " + message.getSubject());
    System.out.println("From: " + message.getFrom()[0]);

    // 检查邮件是否包含附件
    if (message.isMimeType("multipart/*")) {
        Multipart multipart = (Multipart) message.getContent();
        for (int j = 0; j < multipart.getCount(); j++) {
            BodyPart bodyPart = multipart.getBodyPart(j);
            // 检查是否是附件
            if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {
                // 保存附件到文件
                String fileName = bodyPart.getFileName();
                if (fileName != null) {
                    String filePath = "path/to/save/attachments/" + fileName;
                    saveFile(bodyPart.getInputStream(), filePath);
                    System.out.println("Attachment saved: " + fileName);
                }
            }
        }
    }
}