• springboot(java)使用javamail实现邮件的接收、转发、发送、清除


    前言

    最近在弄邮件相关的功能,被搞的头大,很多找的方法根本不知道该怎么往下走,就目前为止,
    经过各种的碰壁和失败,就整理出来如何使用javamail实现邮件的接收、转发、发送、清除
    不单单是分享,也为我后续查找更方便做一个记录

    邮件相关概念

    在正式发送邮件之前,我们应该对邮件有一个概念

    第一点:
    我觉得也是最重要的,接收和发送的主机host端口port不一样的;我一开始的时候,并不懂;直接就不管是发送还是接收都用的一个主机host端口port

    第二点:
    接收邮件和发送邮件的协议不一样
    发送邮件用的是SMTP,SMTP 即简单邮件传输协议,用于邮件发送。SMTP 认证,简单地说就是要求必须提供账户名和密码之后才可以登录 SMTP 服务器。
    接收邮件用的是POP3,
    POP3协议允许电子邮件客户端下载服务器上的邮件,但是这个下载不会影响服务器本身的邮件

    至于另外还有一个是IMAP 的协议,因为我这边并没有用到就不多说,感兴趣百度即可

    导入依赖

    用的是javamail,因此是需要导入javamail的maven依赖

    
            <dependency>
                <groupId>javax.mailgroupId>
                <artifactId>javax.mail-apiartifactId>
                <version>1.5.5version>
            dependency>
            <dependency>
                <groupId>com.sun.mailgroupId>
                <artifactId>javax.mailartifactId>
                <version>1.5.5version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    邮件发送

        public void sendMail(String toEmail, String ccEmail, String bccEmail, String subject, String text, List<File> files) {
            try {
                System.setProperty("mail.mime.splitlongparameters", "false");
                final JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
                javaMailSender.setUsername(username);
                javaMailSender.setPassword(password);
                javaMailSender.setHost(host);
                javaMailSender.setPort(port);
                javaMailSender.setProtocol(protocol);
                javaMailSender.setDefaultEncoding(defaultEncoding);
                final Properties mailProperties = new Properties();
                mailProperties.put("mail.smtp.auth", true);
                mailProperties.put("mail.smtp.starttls.enable", true);
                javaMailSender.setJavaMailProperties(mailProperties);
                final MimeMessage mimeMessage = getMimeMessage(toEmail, ccEmail, bccEmail, subject, text, javaMailSender, files,senderName);
                javaMailSender.send(mimeMessage);
            } catch (MessagingException e) {
                System.out.println("发送邮件失败:"+e.getMessage());
            }
        }
    
    
    
    
    
        private MimeMessage getMimeMessage(String toEmail, String ccEmail, String bccEmail, String subject, String text,
                                           JavaMailSenderImpl javaMailSender, List<File> files,String senderName) throws javax.mail.MessagingException {
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
            mimeMessageHelper.setFrom(senderName);
            mimeMessageHelper.setTo(toEmail.split(","));
            if (!Strings.isNullOrEmpty(ccEmail)) {
                mimeMessageHelper.setCc(ccEmail.split(","));
            }
            if (!Strings.isNullOrEmpty(bccEmail)) {
                mimeMessageHelper.setBcc(bccEmail.split(","));
            }
            mimeMessageHelper.setSubject(subject);
            mimeMessageHelper.setText(text, true);
            try {
                if (!CollectionUtils.isEmpty(files)) {
                    for (File file : files) {
                        mimeMessageHelper.addAttachment(MimeUtility.encodeText(file.getName(), "GBK", "B"), file);
                    }
                }
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
            return mimeMessage;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    sendMail方法
    我们在使用的时候直接调用sendMail方法即可
    其中,各个参数含义如下:
    toEmail: 发送到对应的邮箱
    ccEmail:抄送到对应的邮箱
    bccEmail:秘密抄送到对应邮箱
    subject:邮件主题
    text: 字符文本,可以是html元素文本
    files:附件
    在这个基础上,其实我们还是有额外的参数需要设置的,可以定义成全局
    username: 用于发送邮件的邮箱账号
    password: 用于发送邮件的邮箱密码
    host:发送邮件的主机
    port:发送邮件的端口
    protocol:发送邮件的协议,默认值是:smtp
    defaultEncoding:发送邮件的字符集,默认使用UTF-8

    在这里,host和port是根据你需要连的邮箱进行设置的,比如连qq邮箱,网易邮箱。
    百度能知道他们具体的协议和主机、端口

    getMimeMessage方法
    该方法其实主要就是将接收到的参数进行赋值发送邮箱,不需要多余讲解

    邮件接收

        public static Message[] receiveMail(String receiveHost,String receivePort,String receiveProtocol,String username,String password) throws Exception {
            Properties props = new Properties();
            props.put("mail.pop3.host", receiveHost);
            props.put("mail.pop3.port", receivePort);
            Session session = Session.getInstance(props, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });
            store =  session.getStore(receiveProtocol);
    //        storeLocal.set(store);
            store.connect();
            folder = store.getFolder("INBOX");
    //        folderLocal.set(folder);
            folder.open(Folder.READ_WRITE);
            Calendar calendar = Calendar.getInstance();
            // 搜索1天前到今天收到的的所有邮件,根据时间筛选邮件
            calendar.add(Calendar.DAY_OF_MONTH, -1);
            // 创建ReceivedDateTerm对象,ComparisonTerm.GE(大于等于),Date类型的时间 new Date(calendar.getTimeInMillis())----(表示1天前)
            SentDateTerm term = new SentDateTerm(ComparisonTerm.GE, new Date(calendar.getTimeInMillis()));
            Message[] messages = folder.search(term);
            return messages;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    receiveMail方法
    以下为各个参数说明
    receiveHost:接收邮件的主机
    receivePort:接收邮件的端口
    receiveProtocol:接收邮件的协议,默认值:pop3
    username: 需要接收邮件的账号
    password:需要接收邮件的密码
    这里也是需要账号密码的,区别在于你需要查找接收对应邮箱有收到什么邮件,你就需要对应账号和密码才能接收到

    其中,注释已经标注接收什么时间范围内的邮件

    邮件转发

    转发就有点意思,我找这个找遍了都没有对应的方法能够实现,现在我来说一下我是怎么样的一个思路
    要想转发,第一步,你就得先接收邮件
    但是接收完邮件,你不能把FolderStore关闭掉
    否则你是没有办法转发的
    那什么是Folder和Store?

    接收邮件和发送邮件很类似的都有用到Session,但是获取到Session后,我们需要从Session获取到特定类型的Store,然后连接到Store。

    这里的Store代表了存储邮件的邮件服务器,在连接Store的过程中,我们是既有可能需要用到用户名和密码或者Authenticator,也就是验证的。

    在连接到Store后,一个Folder对象,也叫目录对象,会通过Store的getFolder方法获取到邮件,也就能够从中读取到邮件。

    这也是我们为什么想转发不能关闭他们的原因。
    第二步,开始接收到需要转发的邮件,然后将对应邮件转发。
    第三步,在转发完成之后我们才能够将其完成转发
    也就是,我们必须接收邮件和转发邮件是同一个方法内进行的,没办法通过保存一个邮件类型的对象,额外做操作对其进行转发。

    我也是卡死在了这一步上。

    于是转发的方法如下:

    
      public void forwardMail(String receiveHost,String receivePort,String username,String password,String sendHost,String sendPort,String SendFrom,String SendTo) {
        //设置接收邮件
        final Properties receiveProps = new Properties();
        receiveProps.put("mail.pop3.host", receiveHost);
        receiveProps.put("mail.pop3.port", receivePort);
        final Session receiveSession = Session.getInstance(receiveProps, new Authenticator() {
          @Override
          protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(username, password);
          }
        });
        final ThreadLocal<Store> storeLocal = new ThreadLocal<>();
        final Store store = receiveSession.getStore("pop3");
        storeLocal.set(store);
        store.connect();
        final ThreadLocal<Folder> folderLocal = new ThreadLocal<>();
        final Folder folder = store.getFolder("INBOX");
        folderLocal.set(folder);
        folder.open(Folder.READ_WRITE);
        final Calendar calendar = Calendar.getInstance();
        // 搜索所有邮件,根据时间筛选
        calendar.add(Calendar.DAY_OF_MONTH, -10);//n天之内
        // 创建ReceivedDateTerm对象,ComparisonTerm.GE(大于等于)
        final SentDateTerm term = new SentDateTerm(ComparisonTerm.GE, new Date(calendar.getTimeInMillis()));
        final Message[] messages = folder.search(term);
        for (Message mail : messages) {
          //String header = ((MimeMessage)mail).getHeader("SUBJECT")[0];
          //log.info("Header:{}", header);
          System.out.println("收到邮件的主题:", mail.getSubject());
          if (mail.isMimeType("multipart/related")) {
            final MimeMultipart mimeMultipart = (MimeMultipart) mail.getContent();
            for (int i = 0; i < mimeMultipart.getCount(); i++) {
              System.out.println("收到邮件的正文:", mimeMultipart.getBodyPart(i).getContent().toString().length());
            }
          }
    
    
          System.out.println("--------------------------------分割线----------------------------------------");
    
    
          //设置转发邮件
          final Properties forwardProps = new Properties();
          forwardProps.put("mail.smtp.host", sendHost);
          forwardProps.put("mail.smtp.port", sendPort);
          final Session forwardSession = Session.getInstance(forwardProps, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
              return new PasswordAuthentication(username, password);
            }
          });
          // 创建转发邮件信息
          final Message forwardMail = new MimeMessage(forwardSession);
          // 设置主题
          forwardMail.setSubject("转发: " + mail.getSubject());
          forwardMail.setFrom(new InternetAddress(SendFrom));
          forwardMail.addRecipient(Message.RecipientType.TO, new InternetAddress(SendTo));
          //创建Multipart的容器
          final Multipart multipart = new MimeMultipart();
          //被转发的邮件体部分
          final BodyPart messageBodyPart = new MimeBodyPart();
          messageBodyPart.setDataHandler(mail.getDataHandler());
          //添加到Multipart容器
          multipart.addBodyPart(messageBodyPart);
          forwardMail.setContent(multipart);
          //发送
          Transport.send(forwardMail);
        }
    
    
        folder.close(false);//false标识不删除读取的邮件
        store.close();
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    receiveMail方法
    以下为参数说明
    receiveHost:接收邮件的主机
    receivePort:接收邮件的端口
    username:接收邮件的账号
    password:接收邮件的密码
    这里可以看到,我接收和转发用的都是一个username和password,表示我从接收的邮件的这个账号,用这个账号转发给别的邮箱
    sendHost:发送邮件的主机
    sendPort:发送邮件的端口
    SendFrom:从哪个邮箱进行转发
    SendTo:将邮件转发给该邮箱

    清除邮箱

    以时间为限制,删除一定时间内的邮件

        public static void clearMail(String receiveHost,String receivePort,String receiveProtocol,String username,String password) throws Exception {
            Properties props = new Properties();
            props.put("mail.pop3.host", receiveHost);
            props.put("mail.pop3.port", receivePort);
            Session session = Session.getInstance(props, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });
            Store store = session.getStore(receiveProtocol);
    //        removeStoreLocal.set(store);
            store.connect();
            Folder folder = store.getFolder("INBOX");
    //        removeFolderLocal.set(folder);
            folder.open(Folder.READ_WRITE);
            Calendar calendar = Calendar.getInstance();
            // 搜索7天前收到的的所有邮件,根据时间筛选邮件
            calendar.add(Calendar.DAY_OF_MONTH, -7);
            SentDateTerm term = new SentDateTerm(ComparisonTerm.LE, new Date(calendar.getTimeInMillis()));
            Message[] messages = folder.search(term);
            for (int i = 0; i < messages.length; i++) {
    //            if(!messages[i].getFolder().isOpen()) //判断是否open
    //                messages[i].getFolder().open(Folder.READ_WRITE);
                messages[i].setFlag(Flags.Flag.DELETED, true);
            }
            folder.close(false);
            store.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    clearMail方法
    以下为对应参数说明
    receiveHost:接收邮件的主机
    receivePort:接收邮件的端口
    receiveProtocol:接收邮件的协议
    username:接收该邮箱的邮件的账号
    password:接收该邮箱的邮件的密码

    结语

    以上,就是我通过springboot(java)使用javamail实现邮件的接收、转发、发送的具体过程,如后续有新内容将在本文章更新

  • 相关阅读:
    zabbix监控方式
    【C语言】字符串、字符数组
    uni-app:showModal中实现弹窗中文本框输入
    数据结构六:线性表之顺序栈的设计
    【TES720D】青翼科技基于复旦微的FMQL20S400全国产化ARM核心模块
    【AI视野·今日NLP 自然语言处理论文速览 第三十七期】Wed, 20 Sep 2023
    推荐系统方法梳理
    HTML5中的document.visibilityState
    C++中多态的原理【精华】
    声明式事务概念
  • 原文地址:https://blog.csdn.net/xc9711/article/details/127787964