springboot发邮件,javaxmail收邮件功能

简介: springboot发邮件,javaxmail收邮件功能


import com.sun.mail.imap.IMAPFolder;
import com.sun.mail.imap.protocol.IMAPProtocol;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.util.ObjectUtils;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class ReceivedIMAPMail {

public static String NORM_DATETIME_PATTERN = "yyyy-MM-dd hh:mm:ss";

private MimeMessage mimeMessage;
/**
 * 附件下载后的存放目录
 */
private String saveAttachPath = "";
/**
 * 存放邮件内容的StringBuffer对象
 */
private StringBuffer bodyText = new StringBuffer();

/**
 * 构造函数,初始化一个MimeMessage对象
 *
 * @param mimeMessage
 */
public ReceivedIMAPMail(MimeMessage mimeMessage) {
    this.mimeMessage = mimeMessage;
}

/**
 * 获得发件人的地址和姓名
 *
 * @return
 * @throws MessagingException
 */
public String getFrom() throws MessagingException {
    InternetAddress address[] = (InternetAddress[]) mimeMessage.getFrom();
    String from = address[0].getAddress();
    if (from == null) {
        from = "";
    }
    String personal = address[0].getPersonal();

    if (personal == null) {
        personal = "";
    }

    String fromAddr = null;
    if (personal != null || from != null) {
        fromAddr = personal + "<" + from + ">";
    }
    return fromAddr;
}

/**
 * 获得邮件的收件人,抄送,和密送的地址和姓名,根据所传递的参数的不同
 *
 * @param type "to"----收件人 "cc"---抄送人地址 "bcc"---密送人地址
 * @return
 * @throws MessagingException
 * @throws UnsupportedEncodingException
 */
public String getMailAddress(String type) throws MessagingException, UnsupportedEncodingException {
    if (ObjectUtils.isEmpty(type)) {
        return "";
    }

    String addType = type.toUpperCase();

    if (!addType.equals("TO") && !addType.equals("CC") && !addType.equals("BCC")) {
        return "";
    }
    InternetAddress[] address;

    if (addType.equals("TO")) {
        address = (InternetAddress[]) mimeMessage.getRecipients(Message.RecipientType.TO);
    } else if (addType.equals("CC")) {
        address = (InternetAddress[]) mimeMessage.getRecipients(Message.RecipientType.CC);
    } else {
        address = (InternetAddress[]) mimeMessage.getRecipients(Message.RecipientType.BCC);
    }

    if (ObjectUtils.isEmpty(address)) {
        return "";
    }
    StringBuilder mailAddr = new StringBuilder();
    String emailAddr;
    String personal;
    for (int i = 0; i < address.length; i++) {
        emailAddr = address[i].getAddress();
        if (emailAddr == null) {
            emailAddr = "";
        } else {
            emailAddr = MimeUtility.decodeText(emailAddr);
        }
        personal = address[i].getPersonal();
        if (personal == null) {
            personal = "";
        } else {
            personal = MimeUtility.decodeText(personal);
        }
        mailAddr.append(",").append(personal).append("<").append(emailAddr).append(">");
    }
    return mailAddr.toString().substring(1);
}

/**
 * 获得邮件主题
 *
 * @return
 * @throws MessagingException
 * @throws UnsupportedEncodingException
 */
public String getSubject() throws MessagingException, UnsupportedEncodingException {
    String subject = MimeUtility.decodeText(mimeMessage.getSubject());
    if (subject == null) {
        subject = "";
    }
    return subject;
}

/**
 * 获得邮件发送日期
 *
 * @return
 * @throws MessagingException
 */
public String getSentDate() throws MessagingException {
    Date sentDate = mimeMessage.getSentDate();
    SimpleDateFormat format = new SimpleDateFormat(NORM_DATETIME_PATTERN);
    return format.format(sentDate);
}

/**
 * 获得邮件正文内容
 *
 * @return
 */
public String getBodyText() {
    return bodyText.toString();
}

/**
 * 解析邮件,把得到的邮件内容保存到一个StringBuffer对象中,解析邮件 主要是根据MimeType类型的不同执行不同的操作,一步一步的解析
 * 
 * @param part
 * @throws MessagingException
 * @throws IOException
 */
public void getMailContent(Part part) throws MessagingException, IOException {

    String contentType = part.getContentType();

    int nameIndex = contentType.indexOf("name");

    boolean conName = false;

    if (nameIndex != -1) {
        conName = true;
    }

    if (part.isMimeType("text/plain") && conName == false) {
        bodyText.append((String) part.getContent());
    } else if (part.isMimeType("text/html") && conName == false) {
        bodyText.append((String) part.getContent());
    } else if (part.isMimeType("multipart/*")) {
        Multipart multipart = (Multipart) part.getContent();
        int counts = multipart.getCount();
        for (int i = 0; i < counts; i++) {
            this.getMailContent(multipart.getBodyPart(i));
        }
    } else if (part.isMimeType("message/rfc822")) {
        this.getMailContent((Part) part.getContent());
    }
}

/**
 * 判断此邮件是否需要回执,如果需要回执返回"true",否则返回"false"
 *
 * @return
 * @throws MessagingException
 */
public boolean getReplySign() throws MessagingException {

    boolean replySign = false;

    String needReply[] = mimeMessage.getHeader("Disposition-Notification-To");

    if (needReply != null) {
        replySign = true;
    }
    return replySign;
}

/**
 * 判断此邮件是否已读,如果未读返回false,反之返回true
 *
 * @return
 * @throws MessagingException
 */
public boolean isNew() throws MessagingException {
    boolean isNew = false;
    Flags flags = mimeMessage.getFlags();
    Flags.Flag[] flag = flags.getSystemFlags();
    for (int i = 0; i < flag.length; i++) {
        if (flag[i] == Flags.Flag.SEEN) {
            isNew = true;
        }
    }
    return isNew;
}

/**
 * 判断此邮件是否包含附件
 *
 * @param part
 * @return
 * @throws MessagingException
 * @throws IOException
 */
public boolean isContainAttach(Part part) throws MessagingException, IOException {
    boolean attachFlag = false;
    if (part.isMimeType("multipart/*")) {
        Multipart mp = (Multipart) part.getContent();
        BodyPart mPart;
        String conType;
        for (int i = 0; i < mp.getCount(); i++) {
            mPart = mp.getBodyPart(i);
            String disposition = mPart.getDisposition();
            if (Part.ATTACHMENT.equals(disposition) || Part.INLINE.equals(disposition)) {
                attachFlag = true;
            } else if (mPart.isMimeType("multipart/*")) {
                attachFlag = this.isContainAttach(mPart);
            } else {
                conType = mPart.getContentType();
                if (conType.toLowerCase().indexOf("application") != -1
                        || conType.toLowerCase().indexOf("name") != -1) {
                    attachFlag = true;
                }
            }
        }
    } else if (part.isMimeType("message/rfc822")) {
        attachFlag = isContainAttach((Part) part.getContent());
    }
    return attachFlag;
}

/**
 * 保存附件
 *
 * @param part
 * @throws MessagingException
 * @throws IOException
 */
public void saveAttachMent(Part part) throws MessagingException, IOException {
    String fileName;
    if (part.isMimeType("multipart/*")) {
        Multipart mp = (Multipart) part.getContent();
        BodyPart mPart;
        for (int i = 0; i < mp.getCount(); i++) {
            mPart = mp.getBodyPart(i);
            String disposition = mPart.getDisposition();
            if (Part.ATTACHMENT.equals(disposition) || Part.INLINE.equals(disposition)) {
                fileName = mPart.getFileName();
                if (null != fileName && fileName.toLowerCase().indexOf("gb2312") != -1) {
                    fileName = MimeUtility.decodeText(fileName);
                }
                fileName = fileName.replaceAll("\\?|=", "");
                this.saveFile(fileName, mPart.getInputStream());
            } else if (mPart.isMimeType("multipart/*")) {
                this.saveAttachMent(mPart);
            } else {
                fileName = mPart.getFileName();
                if ((fileName != null) && (fileName.toLowerCase().indexOf("GB2312") != -1)) {
                    fileName = MimeUtility.decodeText(fileName);
                    this.saveFile(fileName, mPart.getInputStream());
                }
            }
        }
    } else if (part.isMimeType("message/rfc822")) {
        this.saveAttachMent((Part) part.getContent());
    }
}

/**
 * 设置附件存放路径
 *
 * @param attachPath
 */
public void setAttachPath(String attachPath) {
    this.saveAttachPath = attachPath;
}

/**
 * 获得附件存放路径
 *
 * @return
 */
public String getAttachPath() {
    return saveAttachPath;
}

/**
 * 真正的保存附件到指定目录里
 *
 * @param fileName
 * @param in
 * @throws IOException
 */
private void saveFile(String fileName, InputStream in) throws IOException {
    String osName = System.getProperty("os.name");
    String storeDir = this.getAttachPath();
    if (null == osName) {
        osName = "";
    }
    if (osName.toLowerCase().indexOf("win") != -1) {
        if (ObjectUtils.isEmpty(storeDir))
            storeDir = "C:\\tmp";
    } else {
        storeDir = "/tmp";
    }
    FileOutputStream fos = new FileOutputStream(new File(storeDir + File.separator + fileName));
    IOUtils.copy(in, fos);
    IOUtils.closeQuietly(fos);
    IOUtils.closeQuietly(in);
}

/**
 * 获取阿里云邮箱信息
 *
 * @param host     邮件服务器
 * @param username 邮箱名
 * @param password 密码
 * @param protocol 协议
 * @return
 * @throws MessagingException
 */
public static Message[] getALiYunMessage(String host, String username, String password, String protocol)
        throws MessagingException {
    Properties props = new Properties();
    Session session = Session.getDefaultInstance(props, null);

    Store store = session.getStore(protocol);
    store.connect(host, username, password);

    Folder folder = store.getFolder("INBOX");
    folder.open(Folder.READ_ONLY);
    return folder.getMessages();
}

/**
 * 获取163邮箱信息
 *
 * @param host
 * @param username
 * @param password
 * @param protocol
 * @return
 * @throws MessagingException
 */
public static Message[] getWEMessage(String host, String username, String password, String protocol)
        throws MessagingException {
    Properties props = System.getProperties();
    props.setProperty("mail.store.protocol", protocol);
    Session session = Session.getDefaultInstance(props, null);
    Store store = session.getStore(protocol);
    store.connect(host, username, password);
    Folder folder = store.getFolder("INBOX");

    if (folder instanceof IMAPFolder) {
        IMAPFolder imapFolder = (IMAPFolder) folder;
        // javamail中使用id命令有校验checkOpened, 所以要去掉id方法中的checkOpened();
        imapFolder.doCommand(new IMAPFolder.ProtocolCommand() {
            public Object doCommand(IMAPProtocol p) throws com.sun.mail.iap.ProtocolException {
                Map<String, String> gmap = new HashMap<>();
                gmap.put("GUID", "FUTONG");
                // p.id("FUTONG");
                p.id(gmap);
                return null;
            }
        });
    }

    if (folder != null) {
        folder.open(Folder.READ_WRITE);
    }

    return folder.getMessages();
}

/**
 * 过滤邮箱信息
 *
 * @param messages
 * @param fromMail  只读取该邮箱发来的邮件,如果为空则不过滤
 * @param startDate 只读取该日期以后的邮件,如果为空则不过滤
 * @return
 * @throws MessagingException
 */
public static List<Message> filterMessage(Message[] messages, String fromMail, String startDate)
        throws MessagingException, ParseException {
    List<Message> messageList = new ArrayList<>();
    if (ObjectUtils.isEmpty(messages)) {
        return messageList;
    }
    boolean isEnptyFromMail = ObjectUtils.isEmpty(fromMail);
    boolean isEnptyStartDate = ObjectUtils.isEmpty(startDate);
    if (isEnptyFromMail && isEnptyStartDate) {
        return Arrays.asList(messages);
    }

    String from;
    for (Message message : messages) {
        from = (message.getFrom()[0]).toString();
        if (isEnptyFromMail) {
            if (new SimpleDateFormat(NORM_DATETIME_PATTERN).parse(startDate).getTime() > message.getSentDate()
                    .getTime()) {
                continue;
            }
        } else if (null != from && from.contains(fromMail)) {
            if (!isEnptyStartDate && new SimpleDateFormat(NORM_DATETIME_PATTERN).parse(startDate)
                    .getTime() > message.getSentDate().getTime()) {
                continue;
            }
        } else {
            continue;
        }
        messageList.add(message);
    }
    return messageList;
}

/**
 * 打印邮件
 *
 * @param messageList
 * @throws IOException
 * @throws MessagingException
 */
public static void printMailMessage(List<Message> messageList) throws IOException, MessagingException {
    System.out.println("邮件数量:" + messageList.size());
    ReceivedIMAPMail re;
    Message message;
    for (int i = 0, leng = messageList.size(); i < leng; i++) {
        message = messageList.get(i);
        re = new ReceivedIMAPMail((MimeMessage) message);
        System.out.println("邮件【" + i + "】主题:" + re.getSubject());
        System.out.println("邮件【" + i + "】发送时间:" + re.getSentDate());
        System.out.println("邮件【" + i + "】是否需要回复:" + re.getReplySign());
        System.out.println("邮件【" + i + "】是否已读:" + re.isNew());
        System.out.println("邮件【" + i + "】是否包含附件:" + re.isContainAttach(message));
        System.out.println("邮件【" + i + "】发送人地址:" + re.getFrom());
        System.out.println("邮件【" + i + "】收信人地址:" + re.getMailAddress("to"));
        System.out.println("邮件【" + i + "】抄送:" + re.getMailAddress("cc"));
        System.out.println("邮件【" + i + "】暗抄:" + re.getMailAddress("bcc"));
        System.out.println("邮件【" + i + "】发送时间:" + re.getSentDate());
        System.out.println("邮件【" + i + "】邮件ID:" + ((MimeMessage) message).getMessageID());
        re.getMailContent(message);
        // System.out.println("邮件【" + i + "】正文内容:\r\n" + re.getBodyText());
        if(re.isContainAttach(message)) {
            System.out.println("邮件包含附件,开始下载到D:\\xl下面");
            re.setAttachPath("D:\\xl\\mail\\");
            re.saveAttachMent(message);
        }
    }
}

public static void main(String[] args) throws MessagingException, IOException, ParseException {
    // 阿里云登录信息

// String host = "pop3.mxhichina.com";
// String username = "liwei@xiaostudy.com";
// String password = "密码";
// String protocol = "pop3";
// String fromMail = "XXX@163.com";
// String startDate = "2020-2-24 23:35:40";
// List messageList = filterMessage(getALiYunMessage(host, username, password, protocol), fromMail, startDate);

    // 163登录信息
    String host = "imap.163.com";
    String username = "*****@163.com";
    String password = "客户端授权码";
    String protocol = "imaps";
    String fromMail = "";// "****@163.com";
    String startDate = "";// "2020-2-24 23:35:40";
    List<Message> messageList = filterMessage(getWEMessage(host, username, password, protocol), fromMail,
            startDate);

    printMailMessage(messageList);
}

}

相关文章
|
4天前
|
消息中间件 缓存 Java
手写模拟Spring Boot启动过程功能
【11月更文挑战第19天】Spring Boot自推出以来,因其简化了Spring应用的初始搭建和开发过程,迅速成为Java企业级应用开发的首选框架之一。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,帮助读者深入理解其工作机制。
21 3
|
4天前
|
Java 开发者 微服务
手写模拟Spring Boot自动配置功能
【11月更文挑战第19天】随着微服务架构的兴起,Spring Boot作为一种快速开发框架,因其简化了Spring应用的初始搭建和开发过程,受到了广大开发者的青睐。自动配置作为Spring Boot的核心特性之一,大大减少了手动配置的工作量,提高了开发效率。
19 0
|
1月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
42 4
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
143 1
|
28天前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
35 0
|
17天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
95 62
|
14天前
|
前端开发 Java easyexcel
SpringBoot操作Excel实现单文件上传、多文件上传、下载、读取内容等功能
SpringBoot操作Excel实现单文件上传、多文件上传、下载、读取内容等功能
54 8
|
15天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
34 2
|
19天前
|
JSON Java API
springboot集成ElasticSearch使用completion实现补全功能
springboot集成ElasticSearch使用completion实现补全功能
23 1
|
23天前
|
存储 Java 数据管理
强大!用 @Audited 注解增强 Spring Boot 应用,打造健壮的数据审计功能
本文深入介绍了如何在Spring Boot应用中使用`@Audited`注解和`spring-data-envers`实现数据审计功能,涵盖从添加依赖、配置实体类到查询审计数据的具体步骤,助力开发人员构建更加透明、合规的应用系统。