You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复Java Mail在while循环中无法获取最新邮件的问题

嘿,我一眼就看出问题所在了!你现在的代码里,只在while循环启动前拉取了一次邮件列表,之后就一直在反复用这个旧列表——难怪拿不到新邮件啊!

POP3协议本身是“一次性下载”的逻辑,当你调用emailFolder.getMessages()的时候,它只会获取当下服务器上的邮件,之后不会自动同步新的进来。你的while循环根本没去服务器重新拉取,自然永远是第一次的那批邮件。

修复方案(适配POP3)

要解决这个问题,你得让每次循环都重新从服务器获取最新邮件。这里给你两种修改思路,其中第二种更稳定:

思路1:循环内刷新邮件列表(POP3支持有限)

如果你想保持长连接,可以尝试在循环内调用emailFolder.getMessageCount()触发刷新,再重新调用getMessages()。但POP3对这种操作的支持不太稳定,所以更推荐下面的方式。

思路2:每次循环重新连接服务器(稳定可靠)

直接把连接、获取邮件的逻辑放进while循环里,每次都重新从服务器拉取最新邮件。修改后的代码如下:

import java.util.Properties;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;

public class GetEmails {
    public static void on(){
        SSH on = new SSH();
        on.command = "python3 on.py";
        on.run();
    }
    public static void off(){
        SSH off = new SSH();
        off.command = "python3 off.py";
        off.run();
    }
    public static void check(String host, String storeType, String user, String password) {
        boolean power = true; // 把灯光状态移到循环外,保持连续状态
        try {
            while(true){
                // 每次循环重新建立连接
                Properties properties = new Properties();
                properties.put("mail.pop3.host", host);
                properties.put("mail.pop3.port", "995");
                properties.put("mail.pop3.starttls.enable", "true");
                Session emailSession = Session.getDefaultInstance(properties);
                
                Store store = emailSession.getStore("pop3s");
                store.connect(host, user, password);
                
                Folder emailFolder = store.getFolder("INBOX");
                emailFolder.open(Folder.READ_ONLY);
                
                // 重新获取最新邮件列表
                Message[] messages = emailFolder.getMessages();
                if(messages.length == 0){
                    System.out.println("暂无新邮件");
                    // 记得关闭资源
                    emailFolder.close(false);
                    store.close();
                    // 休眠5秒再查,别刷太频繁被服务器限流
                    Thread.sleep(5000);
                    continue;
                }
                
                // 取最新的那封邮件
                Message latestMessage = messages[messages.length - 1];
                String subject = latestMessage.getSubject();
                System.out.println("正在检查最新邮件主题:" + subject);
                
                // 执行灯光控制逻辑
                if(subject.equals("+myRoom") && !power){
                    on();
                    power = true;
                    System.out.println("灯光已打开");
                } else if (subject.equals("-myRoom") && power){
                    off();
                    power = false;
                    System.out.println("灯光已关闭");
                }
                
                // 必须关闭文件夹和连接,避免资源泄漏
                emailFolder.close(false);
                store.close();
                
                // 休眠5秒再进行下一次检查
                Thread.sleep(5000);
            }
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (MessagingException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        String host = "pop.gmail.com";// 按需修改
        String mailStoreType = "pop3";
        String username = "EMAIL@gmail.com";// 按需修改
        String password = "PASSWORD";// 按需修改
        check(host, mailStoreType, username, password);
    }
}

关键修改点:

  • 把power灯光状态变量移到循环外,确保循环过程中能记住当前灯光状态
  • 将邮件连接、获取逻辑全部放进while循环,每次都从服务器拉取最新邮件
  • 增加了Thread.sleep(5000),避免频繁请求邮件服务器导致被限流或封禁
  • 每次循环结束后主动关闭Folder和Store,防止资源泄漏
更优方案:改用IMAP协议

其实POP3本身就不适合这种需要实时监听邮件的场景,IMAP协议支持IDLE命令——服务器会主动推送新邮件通知,不需要你反复轮询。如果可以的话,建议换成IMAP,效率更高也更省心。

大致实现思路:

  1. 连接IMAP服务器(比如Gmail的imap.gmail.com,端口993)
  2. 打开INBOX文件夹
  3. 添加邮件数量监听器,当有新邮件时自动触发处理逻辑
  4. 调用Folder.idle()进入空闲监听状态,等待服务器推送

这种方式不用自己写轮询逻辑,服务器有新邮件会立刻通知你,完美适配你的灯光控制需求。


内容的提问来源于stack exchange,提问作者Salesperson1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 21:37:37