Java Mail - 检查来自特定发件人的带有附件的新邮件

标签 java jakarta-mail imap

我编写了代码,每小时检查是否有来自特定发件人的带有附件的新电子邮件。预计每小时都会收到来自特定用户的带有附件的电子邮件(因此不使用空闲功能)。

检测到新电子邮件时,来自该用户的所有新电子邮件都会保存到数组中,并检查最新电子邮件中的 csv 附件、进行操作并保存到磁盘。

检查新电子邮件的代码看起来非常冗长,我想知道是否可以进行任何改进。

具体来说,(1) 如果用户登录并阅读和发送电子邮件,则比较调用之间的未读消息计数将会失败。

(2) 新电子邮件数组仅查看最新电子邮件 (length()-1)。

public class Mail implements Runnable {
private static final long KEEP_ALIVE_FREQ = 3000; // time between mail checks

@Override
public void run() {

    String host = "imap.gmail.com";
    String username = "user@gmail.com";
    String password = "passwd";
    Properties props = new Properties();
    props.setProperty("mail.imap.ssl.enable", "true");
    Folder inbox;
    int messageCount;
    Store store = null;
    Session session = Session.getInstance(props);

    try {
        store = session.getStore("imap");
        store.connect(host,username,password);
        inbox = store.getFolder("inbox");
        inbox.open(Folder.READ_WRITE);
        messageCount = inbox.getUnreadMessageCount();
        inbox.close(true);

        while (!Thread.interrupted()) {
            inbox.open(Folder.READ_WRITE);
            try {
                if (inbox.getUnreadMessageCount() > messageCount) {
                    System.out.println("New mail has arrived");
                    // Construct array of unseen messages from specified user
                    FlagTerm unseenFlagTerm = new FlagTerm(new Flags(Flags.Flag.SEEN), false);
                    FromTerm senderFlagTerm = new FromTerm(new InternetAddress("specifieduser@gmail.com"));
                    SearchTerm searchTerm = new AndTerm(unseenFlagTerm, senderFlagTerm);
                    Message messages[] = inbox.search(searchTerm);
                    // check that messages array contains at least one message from senderFlag
                    if (messages.length>0) {
                        Message msg = messages[messages.length - 1]; // get most recent message from sender
                        if (hasAttachments(msg)) {
                            System.out.println("Message has an attachment - processing");
                            String csv = attachmentToString(msg);
                            String cleanCsv = cleanCsv(csv);
                            FileUtils.writeStringToFile(new File("C:\\tmp\\somefile.csv"), cleanCsv, StandardCharsets.UTF_8, false);
                            // delete message
                            msg.setFlag(Flags.Flag.DELETED, true);
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            // reset unread message count
            messageCount = inbox.getUnreadMessageCount();
            // close inbox
            inbox.close(true);
            System.out.println("About to sleep");
            Thread.sleep(KEEP_ALIVE_FREQ);
        }

    } catch (NoSuchProviderException e) {
        e.printStackTrace();
    } catch (MessagingException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

public String attachmentToString(Message message) throws IOException, MessagingException {
    Multipart multipart = (Multipart) message.getContent();
    String theString = null;
    for (int i = 0; i < multipart.getCount(); i++) {
        BodyPart bodyPart = multipart.getBodyPart(i);
        if (!Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) &&
                StringUtils.isBlank(bodyPart.getFileName())) {
            continue; // dealing with attachments only
        }
        InputStream inputStream = bodyPart.getInputStream();
        StringWriter writer = new StringWriter();
        IOUtils.copy(inputStream, writer, "UTF-8");
        theString = writer.toString();
    }
    return theString;
}

public String cleanCsv(String csv) {
    csv = csv.replaceAll("\"", "");
    csv = csv.replaceAll("\\s*,", ",");
    return csv;
}

boolean hasAttachments(Message msg) throws MessagingException, IOException {
    if (msg.isMimeType("multipart/mixed")) {
        Multipart mp = (Multipart)msg.getContent();
        if (mp.getCount() > 1)
            return true;
    }
    return false;
    }
}

因为我知道电子邮件总是在整点+/-一分钟左右到达 - 安排邮件检查的代码会更简单并且更可靠吗?

最佳答案

正如 @arnt 所说,跟踪最后处理的消息的 UID,然后搜索符合您条件的新消息:

FromTerm senderFromTerm = new FromTerm(new InternetAddress("specifieduser@gmail.com")); 
// first, find all the new messages since we last looked
Message messages[] = ((UIDFolder)inbox).getMessagesByUID(lastProcessedUID, UIDFolder.LASTUID);
// now search within the new messages for those from our user
messages = inbox.search(senderFromTerm, messages);

关于Java Mail - 检查来自特定发件人的带有附件的新邮件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51346197/

相关文章:

java - 如何在java-8中查找流类型

java - Flickr auth 与 scribe-java 提供回调 url

osgi - 将 JavaMail 1.5 与 XPage 结合使用

php - imap_open 使用来自数据库的加密密码

java - 找不到符号抛出 IndexOutOfBoundException

java - 如何将 Maven 多项目构建中的离线 JaCoCo 执行文件集成到 SonarQube 中

java - "No MimeMessage content"发送SimpleMailMessage 异常

javax.mail 无法在 Marshmallow 或更高版本的系统上运行

PHP imap_reopen 没有返回错误

c# - SslHandshakeException : An error occurred while attempting to establish an SSL or TLS connection