@Override public ListenableFuture<List<MessageStatus>> listUidThin( Folder folder, List<Sequence> sequences) { Preconditions.checkState( mailClientHandler.isLoggedIn(), "Can't execute command because client is not logged in"); Preconditions.checkState( !mailClientHandler.idleRequested.get(), "Can't execute command while idling (are you watching a folder?)"); checkCurrentFolder(folder); SettableFuture<List<MessageStatus>> valueFuture = SettableFuture.create(); // -ve end range means get everything (*). String extensions = config.useGmailExtensions() ? " X-GM-MSGID X-GM-THRID X-GM-LABELS UID" : ""; StringBuilder argsBuilder = new StringBuilder(); // Emit ranges. for (int i = 0, sequencesSize = sequences.size(); i < sequencesSize; i++) { Sequence seq = sequences.get(i); argsBuilder.append(toUpperBound(seq.start)); if (seq.end != 0) argsBuilder.append(':').append(toUpperBound(seq.end)); if (i < sequencesSize - 1) argsBuilder.append(','); } argsBuilder.append(" (FLAGS" + extensions + ")"); send(Command.FETCH_THIN_HEADERS_UID, argsBuilder.toString(), valueFuture); return valueFuture; }
@Override public ListenableFuture<List<MessageStatus>> list(Folder folder, int start, int end) { Preconditions.checkState( mailClientHandler.isLoggedIn(), "Can't execute command because client is not logged in"); Preconditions.checkState( !mailClientHandler.idleRequested.get(), "Can't execute command while idling (are you watching a folder?)"); checkCurrentFolder(folder); checkRange(start, end); Preconditions.checkArgument( start > 0, "Start must be greater than zero (IMAP uses 1-based " + "indexing)"); SettableFuture<List<MessageStatus>> valueFuture = SettableFuture.create(); // -ve end range means get everything (*). String extensions = config.useGmailExtensions() ? " X-GM-MSGID X-GM-THRID X-GM-LABELS UID" : ""; String args = start + ":" + toUpperBound(end) + " (RFC822.SIZE INTERNALDATE FLAGS ENVELOPE" + extensions + ")"; send(Command.FETCH_HEADERS, args, valueFuture); return valueFuture; }
@Override // @Stateless public ListenableFuture<FolderStatus> statusOf(String folder) { Preconditions.checkState( mailClientHandler.isLoggedIn(), "Can't execute command because client is not logged in"); SettableFuture<FolderStatus> valueFuture = SettableFuture.create(); String args = '"' + folder + "\" (UIDNEXT RECENT MESSAGES UNSEEN)"; send(Command.FOLDER_STATUS, args, valueFuture); return valueFuture; }
@Override public synchronized void watch(Folder folder, FolderObserver observer) { Preconditions.checkState( mailClientHandler.isLoggedIn(), "Can't execute command because client is not logged in"); checkCurrentFolder(folder); Preconditions.checkState( mailClientHandler.idleRequested.compareAndSet(false, true), "Already idling..."); // This MUST happen in the following order, otherwise send() may trigger a new mail event // before we've registered the folder observer. mailClientHandler.observe(observer); channel.write(sequence.incrementAndGet() + " idle\r\n"); }
@Override public ListenableFuture<Boolean> copy(Folder folder, int imapUid, String toFolder) { Preconditions.checkState( mailClientHandler.isLoggedIn(), "Can't execute command because client is not logged in"); Preconditions.checkState( !mailClientHandler.idleRequested.get(), "Can't execute command while idling (are you watching a folder?)"); checkCurrentFolder(folder); SettableFuture<Boolean> valueFuture = SettableFuture.create(); String args = imapUid + " " + toFolder; send(Command.COPY, args, valueFuture); return valueFuture; }
@Override public ListenableFuture<Set<Flag>> addOrRemoveFlags( Folder folder, int imapUid, Set<Flag> flags, boolean add) { Preconditions.checkState( mailClientHandler.isLoggedIn(), "Can't execute command because client is not logged in"); Preconditions.checkState( !mailClientHandler.idleRequested.get(), "Can't execute command while idling (are you watching a folder?)"); checkCurrentFolder(folder); SettableFuture<Set<Flag>> valueFuture = SettableFuture.create(); String args = imapUid + " " + (add ? "+" : "-") + Flag.toImap(flags); send(Command.STORE_FLAGS, args, valueFuture); return valueFuture; }
@Override // @Stateless public ListenableFuture<List<String>> listFolders() { Preconditions.checkState( mailClientHandler.isLoggedIn(), "Can't execute command because client is not logged in"); Preconditions.checkState( !mailClientHandler.idleRequested.get(), "Can't execute command while idling (are you watching a folder?)"); SettableFuture<List<String>> valueFuture = SettableFuture.create(); send(Command.LIST_FOLDERS, "\"\" \"*\"", valueFuture); return valueFuture; }
@Override public ListenableFuture<Message> fetchUid(Folder folder, int uid) { Preconditions.checkState( mailClientHandler.isLoggedIn(), "Can't execute command because client is not logged in"); Preconditions.checkState( !mailClientHandler.idleRequested.get(), "Can't execute command while idling (are you watching a folder?)"); checkCurrentFolder(folder); Preconditions.checkArgument(uid > 0, "UID must be greater than zero"); SettableFuture<Message> valueFuture = SettableFuture.create(); String args = uid + " (uid body[])"; send(Command.FETCH_BODY_UID, args, valueFuture); return valueFuture; }
@Override public ListenableFuture<List<Message>> fetch(Folder folder, int start, int end) { Preconditions.checkState( mailClientHandler.isLoggedIn(), "Can't execute command because client is not logged in"); Preconditions.checkState( !mailClientHandler.idleRequested.get(), "Can't execute command while idling (are you watching a folder?)"); checkCurrentFolder(folder); checkRange(start, end); Preconditions.checkArgument( start > 0, "Start must be greater than zero (IMAP uses 1-based " + "indexing)"); SettableFuture<List<Message>> valueFuture = SettableFuture.create(); String args = start + ":" + toUpperBound(end) + " (uid body[])"; send(Command.FETCH_BODY, args, valueFuture); return valueFuture; }
@Override public ListenableFuture<Set<String>> setGmailLabels( Folder folder, int imapUid, Set<String> labels) { Preconditions.checkState( mailClientHandler.isLoggedIn(), "Can't execute command because client is not logged in"); Preconditions.checkState( !mailClientHandler.idleRequested.get(), "Can't execute command while idling (are you watching a folder?)"); checkCurrentFolder(folder); SettableFuture<Set<String>> valueFuture = SettableFuture.create(); StringBuilder args = new StringBuilder(); args.append(imapUid); args.append(" X-GM-LABELS ("); Iterator<String> it = labels.iterator(); while (it.hasNext()) { args.append(it.next()); if (it.hasNext()) args.append(" "); else args.append(")"); } send(Command.STORE_LABELS, args.toString(), valueFuture); return valueFuture; }
@Override public ListenableFuture<List<Integer>> searchUid(Folder folder, String query, Date since) { Preconditions.checkState( mailClientHandler.isLoggedIn(), "Can't execute command because client is not logged in"); Preconditions.checkState( !mailClientHandler.idleRequested.get(), "Can't execute command while idling (are you watching a folder?)"); checkCurrentFolder(folder); SettableFuture<List<Integer>> valueFuture = SettableFuture.create(); StringBuilder argsBuilder = new StringBuilder(); if (config.useGmailExtensions()) { argsBuilder.append("X-GM-RAW \"").append(query).append('"'); } else argsBuilder.append(query); if (since != null) argsBuilder.append(" since ").append(SINCE_FORMAT.format(since)); send(Command.SEARCH_RAW_UID, argsBuilder.toString(), valueFuture); return valueFuture; }
@Override // @Stateless public ListenableFuture<Folder> open(String folder, boolean readWrite) { Preconditions.checkState( mailClientHandler.isLoggedIn(), "Can't execute command because client is not logged in"); Preconditions.checkState( !mailClientHandler.idleRequested.get(), "Can't execute command while idling (are you watching a folder?)"); final SettableFuture<Folder> valueFuture = SettableFuture.create(); final SettableFuture<Folder> externalFuture = SettableFuture.create(); valueFuture.addListener( new Runnable() { @Override public void run() { try { // We do this to enforce a happens-before ordering between the time a folder is // saved to currentFolder and a listener registered by the user may fire in a parallel // executor service. currentFolder = valueFuture.get(); externalFuture.set(currentFolder); } catch (InterruptedException e) { log.error("Interrupted while attempting to open a folder", e); } catch (ExecutionException e) { log.error("Execution exception while attempting to open a folder", e); externalFuture.setException(e); } } }, workerPool); String args = '"' + folder + "\""; send(readWrite ? Command.FOLDER_OPEN : Command.FOLDER_EXAMINE, args, valueFuture); return externalFuture; }
@Override public ListenableFuture<List<Integer>> exists(Folder folder, Collection<Integer> uids) { Preconditions.checkState( mailClientHandler.isLoggedIn(), "Can't execute command because client is not logged in"); Preconditions.checkState( !mailClientHandler.idleRequested.get(), "Can't execute command while idling (are you watching a folder?)"); checkCurrentFolder(folder); SettableFuture<List<Integer>> valueFuture = SettableFuture.create(); StringBuilder argsBuilder = new StringBuilder("uid "); Iterator<Integer> iterator = uids.iterator(); for (int i = 0, uidsSize = uids.size(); i < uidsSize; i++) { argsBuilder.append(iterator.next()); if (i < uidsSize - 1) argsBuilder.append(","); } send(Command.SEARCH_UID_ONLY, argsBuilder.toString(), valueFuture); return valueFuture; }
public boolean isConnected() { return channel != null && channel.isConnected() && channel.isOpen() && mailClientHandler.isLoggedIn(); }