如何确保在使用JavaMail API的情况下,多服务器环境中的服务器之一只能读取一封电子邮件

时间:2019-05-05 09:17:52

标签: java javamail imap multiserver

我有一个要求,我要从Outlook中读取传入的电子邮件,然后进行一些处理。我正在使用JavaMail API和IMAP协议来实现此目的。事件。

在单服务器环境中,使用以下代码可以很好地工作,但是当我将其部署到拥有2台服务器的生产环境中时,由于在两台服务器上都部署了相同的代码,所以我最终两次处理每封电子邮件,因此都尝试读取电子邮件一旦收到邮箱中的邮件。

以下是我用来连接到邮箱并阅读电子邮件的代码段:

 try {
    Properties props = System.getProperties();
    // Get a Session object
    Session session = Session.getInstance(props, null);
    // session.setDebug(true);

    // Get a Store object
    Store store = session.getStore("imap");

    // Connect
    store.connect(argv[0], argv[1], argv[2]);

    // Open a Folder
    Folder folder = store.getFolder(argv[3]);
    if (folder == null || !folder.exists()) {
    System.out.println("Invalid folder");
    System.exit(1);
    }

    folder.open(Folder.READ_WRITE);

    // Add messageCountListener to listen for new messages
    folder.addMessageCountListener(new MessageCountAdapter() {
    public void messagesAdded(MessageCountEvent ev) {
        Message[] msgs = ev.getMessages();
        System.out.println("Got " + msgs.length + " new messages");
        // Process incoming mail.

} catch (Exception ex) {
    ex.printStackTrace();
}

关于如何限制在多服务器环境中仅处理一次电子邮件的任何建议?

1 个答案:

答案 0 :(得分:0)

也许最简单的解决方法是使用分布式锁。有很好的库。但是,如果要在javamail中回答,则有两种方法。

首先,您可以使用Flag并调用message.isSet()来检查另一台服务器是否设置了该标志,然后调用message.setFlags()进行锁定。不幸的是那场比赛。可以通过涉及一些另外两个标志或Java邮件显然不支持的an IMAP extension called condstore的一些不道德的黑客来解决此问题-setFlags()仅在以下情况下需要使用新的long参数来设置标志自客户上次注意到以来,这些标记没有改变。

第二,您可以使用一系列邮箱,并通过它移动邮件。您需要四个邮箱,即收件箱和另外三个邮箱,分别称为“ processing-a”,“ processing-b”和“ processed”。服务器A处理“处理a”中的所有消息,然后将每个消息移至“已处理”,B处理“处理b”。当每个服务器都完成其“ processing- foo ”处理后,它将在收件箱中查找新消息,并调用moveMessages()将一个或几个消息原子地移动到其自己的邮箱中。 moveMessages()使用an IMAP extension called move原子地移动消息,大多数服务器都支持,但不是全部。