使用JavaMail实现收取和回复邮件

最近项目实现了一个使用javaMail来实现邮箱邮件的读取和邮件回复。本人查阅资料并汇总做个记录。

需要提前了解邮件协议

  1. 收取邮箱邮件的协议主要有两个,第一个是pop3,第二个是imap协议。两者协议唯一区别就是pop3不能识别邮箱邮件是否为已读需要自己去判断,而imap就很轻松做到这一点。我在这里选择imap协议
  2. 发送协议选择smtp协议

常见邮箱类型的协议

我们项目不能确定客户到底使用什么类型的邮箱,所以自己单独测试了各类型的邮箱做个汇总,省的再去翻阅资料查询。注意:以下邮箱密码如果是授权码,需要单独查询各类型邮箱获取授权码的方式!如果是密码则直接使用邮箱密码即可!

QQ邮箱

	imap服务器:imap.qq.com
	smtp服务器:smtp.qq.com
	smtp端口:587
	用户名:账号名称
	密码:授权码

企业邮箱

	imap服务器:imap.exmail.qq.com
	smtp服务器:smtp.exmail.qq.com
	smtp端口:25
	用户名:账号名称
	密码:密码

新浪邮箱

imap服务器:imap.sina.com
smtp服务器:smtp.sina.com
smtp端口:25
用户名:账号名称
密码:授权码

outlook邮箱

imap服务器:outlook.office365.com
smtp服务器:smtp-mail.outlook.com
smtp端口:587
用户名:账号名称
密码:密码

163邮箱

imap服务器:imap.163.com
smtp服务器:smtp.163.com
smtp端口:25
用户名:账号名称
密码:授权码

139邮箱

	139邮箱:
	imap服务器:imap.139.com
	smtp服务器:smtp.139.com
    smtp端口:25

** 阿里云邮箱 **

阿里云邮箱:
imap服务器:imap.aliyun.com
smtp服务器:smtp.aliyun.com
smtp端口:25
用户名:账号名称
密码:密码

接下来不多BB,直接上代码(代码里的带前后~~ ~~格式的需要自己去填写具体的协议、账号、密码 )

  1. 收取邮件
/**
 1. 读取邮件
*/
public void readEmail() {
        Properties props = new Properties();
        props.put("mail.imap.host", "~~imapHost~~ ");
        props.put("mail.imap.auth", "true");
        props.setProperty("mail.store.protocol", "imap");
        props.put("mail.imap.starttls.enable", "true");
        Session session = Session.getInstance(props);
        try {
            Store store = session.getStore();
            store.connect("~~imapHost~~ ","~~userName~~ ", "~~passWord~~ ");
            Folder folder = store.getFolder("Inbox");
            //javamail中使用id命令有校验checkOpened, 所以要去掉id方法中的checkOpened();(这里针对163邮箱无法收发票做的逻辑代码)
                IMAPFolder imapFolder = (IMAPFolder)folder;
                imapFolder.doCommand(p -> { p.id("FUTONG");
                    return null;
                });
            //邮箱打开方式
            folder.open(Folder.READ_WRITE);
            //收取未读邮件
            Message[] messages = folder.getMessages(folder.getMessageCount() - folder.getUnreadMessageCount() + 1, folder.getMessageCount());
            //解析邮件
            if (messages.length != 0) {
                parseMessage(messages);
            }
            //设置邮件为已读
            folder.setFlags(messages, new Flags(Flags.Flag.SEEN), true);
            folder.close(true);
            store.close();
        } catch (MessagingException e) {
            e.printStackTrace();
        }
    }
    
	/**
     * 解析邮件
     */
    public void parseMessage(Message[] messages) {
        for (Message message : messages) {
            try {
                //获取未读邮件
                if (!message.getFlags().contains(Flags.Flag.SEEN)) {
                    MimeMessage mimeMsg = (MimeMessage) message;
                    //判断邮件是否包含附件
                    boolean containAttachment = this.containAttachment(mimeMsg);
                    // 解析邮件发件人
                    EmailInfo emailInfo = this.processEmailInfo(mimeMsg);
                    log.debug("-----> 发件人信息:{}, 包含附件:{}", emailInfo, containAttachment);
                    if (containAttachment) {
                        // 邮箱附件解析
                        List<BodyPart> mimeFileList = this.getMimeFile(mimeMsg);
                        // 附件操作(遍历可以拿到每个文件的名称和流)
                        saveEmailAttach(mimeFileList);
                    }
                }
            } catch (MessagingException e) {
                e.printStackTrace();
            }
        }
    }
    
    /**
     * 邮件是否包含附件
     */
     public static boolean containAttachment(MimeMessage mimeMsg) {
        try {
            if (mimeMsg.isMimeType(MULTIPART_MIME_TYPE)) {
                Multipart mp = (Multipart) mimeMsg.getContent();
                for (int i = 0; i < mp.getCount(); i++) {
                    BodyPart bp = mp.getBodyPart(i);
                    // 如果该BodyPart对象包含附件
                    if (bp.getDisposition() != null) {
                        return true;
                    }
                }
            }
        } catch (MessagingException | IOException e) {
            log.error("-----> {}", LogUtil.stackTraceInfo(e));
        }
        return false;
    }
    
    /**
     * 解析邮件发件信息
     */
    public static EmailInfo processEmailInfo(MimeMessage mimeMsg) {
        EmailInfo emailInfo = new EmailInfo();
        try {
            String from = ((InternetAddress) (mimeMsg.getFrom()[0])).getAddress();
            String subject = mimeMsg.getSubject();
            Date sentDate = mimeMsg.getSentDate();
            emailInfo.setFrom(from)
                    .setSubject(subject)
                    .setSendDate(sentDate)
                    .setSendDateStr(DateUtil.format(sentDate, DatePattern.NORM_DATETIME_PATTERN));
        } catch (MessagingException e) {
            log.error("-----> {}", LogUtil.stackTraceInfo(e));
        }
        return emailInfo;
    }
    
    /**
     * 解析邮件附件
     *
     * @param part 邮件中多个组合体中的其中一个组合体
     */
    public static List<BodyPart> getMimeFile(Part part) {

        List<BodyPart> files = new ArrayList<>();
        try {
            if (part.isMimeType(MULTIPART_MIME_TYPE)) {
                //复杂体邮件
                Multipart multipart = (Multipart) part.getContent();
                //复杂体邮件包含多个邮件体
                int partCount = multipart.getCount();
                for (int i = 0; i < partCount; i++) {
                    //获得复杂体邮件中其中一个邮件体
                    BodyPart bodyPart = multipart.getBodyPart(i);
                    //某一个邮件体也有可能是由多个邮件体组成的复杂体
                    String disp = bodyPart.getDisposition();
                    if (disp != null && (disp.equalsIgnoreCase(Part.ATTACHMENT) || disp.equalsIgnoreCase(Part.INLINE))) {
                        files.add(bodyPart);
                    } else if (bodyPart.isMimeType(MULTIPART_MIME_TYPE)) {
                        getFile(bodyPart);
                    } else {
                        String contentType = bodyPart.getContentType();
                        if (contentType.contains("name") || contentType.contains("application")) {
                            files.add(bodyPart);
                        }
                    }
                }
            } else if (part.isMimeType(RFC822_MIME_TYPE)) {
                getMimeFile((BodyPart) part.getContent());
            }
        } catch (IOException | MessagingException e) {
            log.error("-----> {}", LogUtil.stackTraceInfo(e));
        }
        return files;
    }
    /**
     * 保存附件
     */
     public void saveEmailAttach(List<BodyPart> bodyPartList) {
        ArrayList<Attach> attachList = new ArrayList<>();
        try {
            for (BodyPart file : bodyPartList) {
                String fileNameSuffix = file.getFileName();
                fileNameSuffix = MimeUtility.decodeText(fileNameSuffix);
                String suffix = fileNameSuffix.substring(fileNameSuffix.lastIndexOf(".") + 1);
                suffix = MimeUtility.decodeText(suffix);
                //判断附件类型是否为PDF(看具体情况具体处理)
                if (!suffix.equalsIgnoreCase("PDF")) {
                    continue;
                }
                //获取输入流
                InputStream inputStream = file.getInputStream();
                //TODO
            }
        } catch (MessagingException | IOException e) {
            throw new CommonException(e);
        }
    }

    /**
     * 发件人信息
     */
    public class EmailInfo {
    /** 发件人 */
    private String from;
    /** 主题 */
    private String subject;
    /** 发件时间 */
    private Date sendDate;
    /** 发件时间字符串 */
    private String sendDateStr;
    }
  

 2. 回复邮件
 

/**
 * @param smtpHost  邮箱服务器地址
 * @param smtpPort  邮箱服务器端口
 * @param userName  邮箱用户名
 * @param password  邮箱密码
 * @param sendAddr  发送地址(多个收件人以逗号分割)
 * @param subject   邮件主题
 * @param message   邮件内容
 * @param attr_path 附件(文件地址)
 */
private void sendMsg(String smtpHost, String smtpPort, String userName, String password, String sendAddr, String subject, String message, String attr_path) {
    try {
        Properties props = new Properties();
        // 开启debug调试
        props.setProperty(EmailConstant.MAIL_DEBUG, EmailConstant.FALSE);
        // 发送服务器需要身份验证
        props.setProperty(EmailConstant.MAIL_SMTP_AUTH, EmailConstant.TRUE);
        // 设置邮件服务器主机名
        log.info("----->回复邮件邮箱的服务器配置" + smtpHost);
        props.setProperty(EmailConstant.MAIL_HOST, smtpHost);
        // 发送邮件协议名称
        props.setProperty(EmailConstant.MAIL_TRANSPORT_PROTOCOL, EmailConstant.SMTP);
        log.info("----->回复邮件的服务器端口配置" + smtpPort);
        props.setProperty(EmailConstant.MAIL_SMTP_PORT, smtpPort);
        props.put(EmailConstant.MAIL_SMTP_STARTTLS_ENABLE, EmailConstant.TRUE);
        props.put(EmailConstant.MAIL_SMTP_SSL_TRUST, smtpHost);
        props.put(EmailConstant.MAIL_SMTP_CONNECT_TIMEOUT, EmailConstant.MAIL_IMAP_TIMEOUT_VALUE);
        props.put(EmailConstant.MAIL_SMTP_TIMEOUT, EmailConstant.MAIL_IMAP_TIMEOUT_VALUE);
        props.put(EmailConstant.MAIL_SMTP_WRITE_TIMEOUT, EmailConstant.MAIL_IMAP_TIMEOUT_VALUE);
        // 设置环境信息
        Session session = Session.getInstance(props);
        // 创建邮件对象
        MimeMessage msg = new MimeMessage(session);
        // 设置发件人
        msg.setFrom(new InternetAddress(userName));
        // 设置收件人
        String[] result = sendAddr.split(",");
        InternetAddress[] sendTo = new InternetAddress[result.length];
        for (int i = 0; i < result.length; i++) {
            log.info("----->需发送到邮箱{}:" + result[i]);
            sendTo[i] = new InternetAddress(result[i]);
        }
        msg.addRecipients(Message.RecipientType.TO, sendTo);

        // 设置邮件主题
        msg.setSubject(subject);
        //新建一个存放信件内容的BodyPart对象
        BodyPart mdp = new MimeBodyPart();
        //给BodyPart对象设置内容和格式/编码方式
        mdp.setContent(message, EmailConstant.MESSAGE);
        //新建一个MimeMultipart对象用来存放BodyPart对象(事实上可以存放多个)
        Multipart mm = new MimeMultipart();
        //将BodyPart加入到MimeMultipart对象中(可以加入多个BodyPart)
        mm.addBodyPart(mdp);
        if (StrUtil.isNotEmpty(attr_path)) {
            DataSource attr_ds = new FileDataSource(new File(attr_path));
            DataHandler attr_handler = new DataHandler(attr_ds);
            BodyPart attachmentBodyPart = new MimeBodyPart();
            attachmentBodyPart.setDataHandler(attr_handler);
            attachmentBodyPart.setFileName(MimeUtility.encodeWord(attr_path.substring(attr_path.lastIndexOf("/") + 1)));
            mm.addBodyPart(attachmentBodyPart);
        }
        //把mm作为消息对象的内容
        msg.setContent(mm);
        Transport transport = session.getTransport();
        // 连接邮件服务器
        log.info("----->连接收票邮箱" + userName);
        transport.connect(userName, password);
        // 发送邮件
        log.info("----->发送回复邮件");
        transport.sendMessage(msg, sendTo);
        // 关闭连接
        transport.close();
    } catch (Exception e) {
        log.error("----->回复邮件异常{}", LogUtil.stackTraceInfo(e));
    }

}
public class EmailConstant {

    public static String MAIL_IMAP_HOST = "mail.imap.host";

    public static String MAIL_IMAP_AUTH = "mail.imap.auth";

    public static String MAIL_STORE_PROTOCOL = "mail.store.protocol";

    public static String MAIL_IMAP_STARTTLS_ENABLE = "mail.imap.starttls.enable";

    public static String MAIL_IMAP_CONNECT_TIMEOUT = "mail.imap.connectiontimeout";

    public static String MAIL_IMAP_TIMEOUT = "mail.imap.timeout";

    public static String MAIL_IMAP_WRITE_TIMEOUT = "mail.imap.writetimeout";

    public static String MAIL_SMTP_CONNECT_TIMEOUT = "mail.smtp.connectiontimeout";

    public static String MAIL_SMTP_TIMEOUT = "mail.smtp.timeout";

    public static String MAIL_SMTP_WRITE_TIMEOUT = "mail.smtp.writetimeout";

    public static String MAIL_DEBUG = "mail.debug";

    public static String MAIL_SMTP_AUTH = "mail.smtp.auth";

    public static String MAIL_HOST = "mail.host";

    public static String MAIL_TRANSPORT_PROTOCOL = "mail.transport.protocol";

    public static String MAIL_SMTP_PORT = "mail.smtp.port";

    public static String MAIL_SMTP_STARTTLS_ENABLE = "mail.smtp.starttls.enable";

    public static String MAIL_SMTP_SSL_TRUST = "mail.smtp.ssl.trust";

    public static String MESSAGE = "text/html;charset=UTF-8";

    public static int MAIL_IMAP_TIMEOUT_VALUE = 5000;

    public static String MAIL_SPECIAL = "@163.com";

    public static String MAIL_IMAP_SSL_TRUST = "mail.imap.ssl.trust";

    public static String MAIL_IMAP_SSL_SOCKETFACTORY = "mail.imap.ssl.socketFactory";

    public static String IMAP = "imap";

    public static String SMTP = "smtp";

    public static String TRUE = "true";

    public static String FALSE = "false";

    public static String EMAIL_PROCESS = "emailProcess";

    public static String INVOICE_CODE = "invoiceCode";

    public static String INVOICE_NUMBER = "invoiceNumber";

}

补充(导包贴图)
在这里插入图片描述
在这里插入图片描述

**全部代码都在这里,我在里面删除了自己好多项目具体自己处理的逻辑,有不对的地方可以指出,我再进行修改。**

  

		

	
 


评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值