Можно ли использовать условия запроса IMAP в Javamail с GMail? - PullRequest
2 голосов
/ 27 января 2011

Я пытаюсь программно получить сообщения журнала вызовов, которые резервируются с моего телефона Android, с помощью небольшого приложения под названием SMSBackup (настоятельно рекомендуется).

Что я хочу сделать, так это иметь возможность получать журналы вызовов за определенный день. Я пробовал следующую программу, используя JavaMail:

public List<CallLogEntry> getCallLog(String username, String password, Date date, TimeZone tz) {
    Store store = null;

    try {
        store = MailUtils.getGmailImapStore(username, password);
        Folder folder = store.getDefaultFolder();
        if (folder == null)
            throw new Exception("No default folder");
        Folder inboxfolder = folder.getFolder("Call log");
        if (inboxfolder == null)
            throw new Exception("No INBOX");
        inboxfolder.open(Folder.READ_ONLY);

        Date fromMidnight = new Date(TimeUtils.fromMidnight(date.getTime(), tz));
        Date toMidnight = new Date(TimeUtils.toMidnight(date.getTime(), 0, tz));

        SentDateTerm fromTerm = new SentDateTerm(SentDateTerm.GT, fromMidnight);
        SentDateTerm toTerm = new SentDateTerm(SentDateTerm.LT, toMidnight);

        AndTerm searchTerms = new AndTerm(fromTerm, toTerm);
        Message[] msgs = inboxfolder.search(searchTerms);

        FetchProfile fp = new FetchProfile();
        fp.add("Subject");
        fp.add("Content");
        fp.add("From");
        fp.add("SentDate");
        inboxfolder.fetch(msgs, fp);

        List<CallLogEntry> callLog = new ArrayList<CallLogEntry>();
        for (Message message : msgs) {
            CallLogEntry entry = new CallLogEntry();
            entry.subject = message.getSubject();
            entry.body = (String) message.getContent();
            callLog.add(entry);
        }

        inboxfolder.close(false);
        store.close();

        return callLog;
    } catch (NoSuchProviderException ex) {
        ex.printStackTrace();
    } catch (MessagingException ex) {
        ex.printStackTrace();
    } catch (Exception ex) {
        ex.printStackTrace();
    } finally {
        try {
            if (store != null)
                store.close();
        } catch (MessagingException ex) {
            ex.printStackTrace();
        }
    }
    return null;
}

Мои два служебных метода (с середины ночи / до ночи):

public static final long fromMidnight(long time, TimeZone tz) {
    Calendar c = Calendar.getInstance(tz);
    c.setTimeInMillis(time);
    c.set(Calendar.HOUR_OF_DAY, 0);
    c.set(Calendar.MINUTE, 0);
    c.set(Calendar.SECOND, 0);
    c.set(Calendar.MILLISECOND, 1);
    return c.getTimeInMillis();
}

public static final long toMidnight(long time, int nDays, TimeZone tz) {
    Calendar c = Calendar.getInstance(tz);
    c.setTimeInMillis(time + nDays*MILLIS_IN_DAY);
    c.set(Calendar.HOUR_OF_DAY, 23);
    c.set(Calendar.MINUTE, 59);
    c.set(Calendar.SECOND, 59);
    c.set(Calendar.MILLISECOND, 999);
    return c.getTimeInMillis();
}

Однако по какой-то причине:

  1. во время выполнения, требуется около 3 минут для завершения
  2. Я получаю обратно весь журнал звонков, то есть весь контент папки «Журнал звонков» в моем почтовом ящике

Чего мне не хватает?

1 Ответ

5 голосов
/ 28 января 2011

Главное, что вам не хватает, это то, что базовый синтаксис IMAP SEARCH поддерживает только даты, а не дату-время . Таким образом, ваш запрос приведет к тому, что JavaMail выдаст команду:

A001 SEARCH SENTBEFORE 16-JAN-2011 SENTSINCE 16-JAN-2011 ALL

(Поставьте точку останова в IMAPProtocol.issueSearch(), чтобы увидеть это.)

Похоже, GMail сходит с ума по этому запросу, который логически не может соответствовать ни одному сообщению. Попробуйте переключить вашу логику на один термин, используя SentDateTerm.EQ (который соответствует SENTON), и он должен работать:

    SentDateTerm term = new SentDateTerm(SentDateTerm.EQ, date.getTime());
    Message[] msgs = inboxfolder.search(term);
...