Search in sources :

Example 1 with MessageRetrievalListener

use of com.fsck.k9.mail.MessageRetrievalListener in project k-9 by k9mail.

the class ImapFolder method fetchPart.

@Override
public void fetchPart(Message message, Part part, MessageRetrievalListener<Message> listener) throws MessagingException {
    checkOpen();
    String partId = part.getServerExtra();
    String fetch;
    if ("TEXT".equalsIgnoreCase(partId)) {
        int maximumAutoDownloadMessageSize = store.getStoreConfig().getMaximumAutoDownloadMessageSize();
        fetch = String.format(Locale.US, "BODY.PEEK[TEXT]<0.%d>", maximumAutoDownloadMessageSize);
    } else {
        fetch = String.format("BODY.PEEK[%s]", partId);
    }
    try {
        String command = String.format("UID FETCH %s (UID %s)", message.getUid(), fetch);
        connection.sendCommand(command, false);
        ImapResponse response;
        int messageNumber = 0;
        ImapResponseCallback callback = new FetchPartCallback(part);
        do {
            response = connection.readResponse(callback);
            if (response.getTag() == null && ImapResponseParser.equalsIgnoreCase(response.get(1), "FETCH")) {
                ImapList fetchList = (ImapList) response.getKeyedValue("FETCH");
                String uid = fetchList.getKeyedString("UID");
                if (!message.getUid().equals(uid)) {
                    if (K9MailLib.isDebug()) {
                        Log.d(LOG_TAG, "Did not ask for UID " + uid + " for " + getLogId());
                    }
                    handleUntaggedResponse(response);
                    continue;
                }
                if (listener != null) {
                    listener.messageStarted(uid, messageNumber++, 1);
                }
                ImapMessage imapMessage = (ImapMessage) message;
                Object literal = handleFetchResponse(imapMessage, fetchList);
                if (literal != null) {
                    if (literal instanceof Body) {
                        // Most of the work was done in FetchAttchmentCallback.foundLiteral()
                        MimeMessageHelper.setBody(part, (Body) literal);
                    } else if (literal instanceof String) {
                        String bodyString = (String) literal;
                        InputStream bodyStream = new ByteArrayInputStream(bodyString.getBytes());
                        String contentTransferEncoding = part.getHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING)[0];
                        String contentType = part.getHeader(MimeHeader.HEADER_CONTENT_TYPE)[0];
                        MimeMessageHelper.setBody(part, MimeUtility.createBody(bodyStream, contentTransferEncoding, contentType));
                    } else {
                        // This shouldn't happen
                        throw new MessagingException("Got FETCH response with bogus parameters");
                    }
                }
                if (listener != null) {
                    listener.messageFinished(message, messageNumber, 1);
                }
            } else {
                handleUntaggedResponse(response);
            }
        } while (response.getTag() == null);
    } catch (IOException ioe) {
        throw ioExceptionHandler(connection, ioe);
    }
}
Also used : MessagingException(com.fsck.k9.mail.MessagingException) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException) ByteArrayInputStream(java.io.ByteArrayInputStream) Body(com.fsck.k9.mail.Body)

Example 2 with MessageRetrievalListener

use of com.fsck.k9.mail.MessageRetrievalListener in project k-9 by k9mail.

the class MessagingController method searchLocalMessagesSynchronous.

@VisibleForTesting
void searchLocalMessagesSynchronous(final LocalSearch search, final MessagingListener listener) {
    List<Account> searchAccounts = getAccountsFromLocalSearch(search, preferences);
    for (final Account account : searchAccounts) {
        // Collecting statistics of the search result
        MessageRetrievalListener<LocalMessage> retrievalListener = new MessageRetrievalListener<LocalMessage>() {

            @Override
            public void messageStarted(String message, int number, int ofTotal) {
            }

            @Override
            public void messagesFinished(int number) {
            }

            @Override
            public void messageFinished(LocalMessage message, int number, int ofTotal) {
                if (!isMessageSuppressed(message)) {
                    List<LocalMessage> messages = new ArrayList<>();
                    messages.add(message);
                    if (listener != null) {
                        listener.listLocalMessagesAddMessages(account, null, messages);
                    }
                }
            }
        };
        // build and do the query in the localstore
        try {
            LocalStore localStore = localStoreProvider.getInstance(account);
            localStore.searchForMessages(retrievalListener, search);
        } catch (Exception e) {
            Timber.e(e);
        }
    }
    if (listener != null) {
        listener.listLocalMessagesFinished();
    }
}
Also used : SearchAccount(com.fsck.k9.search.SearchAccount) Account(com.fsck.k9.Account) LocalMessage(com.fsck.k9.mailstore.LocalMessage) ArrayList(java.util.ArrayList) LocalStore(com.fsck.k9.mailstore.LocalStore) CertificateValidationException(com.fsck.k9.mail.CertificateValidationException) MessagingException(com.fsck.k9.mail.MessagingException) AuthenticationFailedException(com.fsck.k9.mail.AuthenticationFailedException) MessageRetrievalListener(com.fsck.k9.mail.MessageRetrievalListener) VisibleForTesting(androidx.annotation.VisibleForTesting)

Example 3 with MessageRetrievalListener

use of com.fsck.k9.mail.MessageRetrievalListener in project k-9 by k9mail.

the class WebDavFolder method fetchMessages.

/**
 * Fetches the full messages or up to {@param lines} lines and passes them to the message parser.
 */
private void fetchMessages(List<WebDavMessage> messages, MessageRetrievalListener<WebDavMessage> listener, int lines) throws MessagingException {
    WebDavHttpClient httpclient;
    httpclient = store.getHttpClient();
    /**
     * We can't hand off to processRequest() since we need the stream to parse.
     */
    for (int i = 0, count = messages.size(); i < count; i++) {
        WebDavMessage wdMessage = messages.get(i);
        int statusCode = 0;
        if (listener != null) {
            listener.messageStarted(wdMessage.getUid(), i, count);
        }
        /**
         * If fetch is called outside of the initial list (ie, a locally stored message), it may not have a URL
         * associated. Verify and fix that
         */
        if (wdMessage.getUrl().equals("")) {
            wdMessage.setUrl(getMessageUrls(new String[] { wdMessage.getUid() }).get(wdMessage.getUid()));
            Timber.i("Fetching messages with UID = '%s', URL = '%s'", wdMessage.getUid(), wdMessage.getUrl());
            if (wdMessage.getUrl().equals("")) {
                throw new MessagingException("Unable to get URL for message");
            }
        }
        try {
            Timber.i("Fetching message with UID = '%s', URL = '%s'", wdMessage.getUid(), wdMessage.getUrl());
            HttpGet httpget = new HttpGet(new URI(wdMessage.getUrl()));
            HttpResponse response;
            HttpEntity entity;
            httpget.setHeader("translate", "f");
            if (store.getAuthentication() == WebDavConstants.AUTH_TYPE_BASIC) {
                httpget.setHeader("Authorization", store.getAuthString());
            }
            response = httpclient.executeOverride(httpget, store.getHttpContext());
            statusCode = response.getStatusLine().getStatusCode();
            entity = response.getEntity();
            if (statusCode < 200 || statusCode > 300) {
                throw new IOException("Error during with code " + statusCode + " during fetch: " + response.getStatusLine().toString());
            }
            if (entity != null) {
                InputStream istream = null;
                StringBuilder buffer = new StringBuilder();
                String tempText;
                String resultText;
                BufferedReader reader = null;
                int currentLines = 0;
                try {
                    istream = WebDavHttpClient.getUngzippedContent(entity);
                    if (lines != -1) {
                        // Convert the ungzipped input stream into a StringBuilder
                        // containing the given line count
                        reader = new BufferedReader(new InputStreamReader(istream), 8192);
                        while ((tempText = reader.readLine()) != null && (currentLines < lines)) {
                            buffer.append(tempText).append("\r\n");
                            currentLines++;
                        }
                        IOUtils.closeQuietly(istream);
                        resultText = buffer.toString();
                        istream = new ByteArrayInputStream(resultText.getBytes("UTF-8"));
                    }
                    // Parse either the entire message stream, or a stream of the given lines
                    wdMessage.parse(istream);
                } catch (IOException ioe) {
                    Timber.e(ioe, "IOException during message parsing");
                    throw new MessagingException("I/O Error", ioe);
                } finally {
                    IOUtils.closeQuietly(reader);
                    IOUtils.closeQuietly(istream);
                }
            } else {
                Timber.v("Empty response");
            }
        } catch (IllegalArgumentException iae) {
            Timber.e(iae, "IllegalArgumentException caught");
            throw new MessagingException("IllegalArgumentException caught", iae);
        } catch (URISyntaxException use) {
            Timber.e(use, "URISyntaxException caught");
            throw new MessagingException("URISyntaxException caught", use);
        } catch (IOException ioe) {
            Timber.e(ioe, "Non-success response code loading message, response code was %d, URL: %s", statusCode, wdMessage.getUrl());
            throw new MessagingException("Failure code " + statusCode, ioe);
        }
        if (listener != null) {
            listener.messageFinished(wdMessage, i, count);
        }
    }
}
Also used : HttpEntity(org.apache.http.HttpEntity) InputStreamReader(java.io.InputStreamReader) MessagingException(com.fsck.k9.mail.MessagingException) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) HttpGet(org.apache.http.client.methods.HttpGet) HttpResponse(org.apache.http.HttpResponse) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) URI(java.net.URI) ByteArrayInputStream(java.io.ByteArrayInputStream) BufferedReader(java.io.BufferedReader)

Example 4 with MessageRetrievalListener

use of com.fsck.k9.mail.MessageRetrievalListener in project k-9 by k9mail.

the class Pop3Folder method getMessages.

public List<Pop3Message> getMessages(int start, int end, MessageRetrievalListener<Pop3Message> listener) throws MessagingException {
    if (start < 1 || end < 1 || end < start) {
        throw new MessagingException(String.format(Locale.US, "Invalid message set %d %d", start, end));
    }
    try {
        indexMsgNums(start, end);
    } catch (IOException ioe) {
        throw new MessagingException("getMessages", ioe);
    }
    List<Pop3Message> messages = new ArrayList<>();
    int i = 0;
    for (int msgNum = start; msgNum <= end; msgNum++) {
        Pop3Message message = msgNumToMsgMap.get(msgNum);
        if (message == null) {
            /*
                 * There could be gaps in the message numbers or malformed
                 * responses which lead to "gaps" in msgNumToMsgMap.
                 *
                 * See issue 2252
                 */
            continue;
        }
        if (listener != null) {
            listener.messageStarted(message.getUid(), i++, (end - start) + 1);
        }
        messages.add(message);
        if (listener != null) {
            listener.messageFinished(message, i++, (end - start) + 1);
        }
    }
    return messages;
}
Also used : MessagingException(com.fsck.k9.mail.MessagingException) ArrayList(java.util.ArrayList) IOException(java.io.IOException) SuppressLint(android.annotation.SuppressLint)

Example 5 with MessageRetrievalListener

use of com.fsck.k9.mail.MessageRetrievalListener in project k-9 by k9mail.

the class ImapFolder method fetch.

@Override
public void fetch(List<ImapMessage> messages, FetchProfile fetchProfile, MessageRetrievalListener<ImapMessage> listener) throws MessagingException {
    if (messages == null || messages.isEmpty()) {
        return;
    }
    checkOpen();
    List<String> uids = new ArrayList<>(messages.size());
    HashMap<String, Message> messageMap = new HashMap<>();
    for (Message message : messages) {
        String uid = message.getUid();
        uids.add(uid);
        messageMap.put(uid, message);
    }
    Set<String> fetchFields = new LinkedHashSet<>();
    fetchFields.add("UID");
    if (fetchProfile.contains(FetchProfile.Item.FLAGS)) {
        fetchFields.add("FLAGS");
    }
    if (fetchProfile.contains(FetchProfile.Item.ENVELOPE)) {
        fetchFields.add("INTERNALDATE");
        fetchFields.add("RFC822.SIZE");
        fetchFields.add("BODY.PEEK[HEADER.FIELDS (date subject from content-type to cc " + "reply-to message-id references in-reply-to " + K9MailLib.IDENTITY_HEADER + ")]");
    }
    if (fetchProfile.contains(FetchProfile.Item.STRUCTURE)) {
        fetchFields.add("BODYSTRUCTURE");
    }
    if (fetchProfile.contains(FetchProfile.Item.BODY_SANE)) {
        int maximumAutoDownloadMessageSize = store.getStoreConfig().getMaximumAutoDownloadMessageSize();
        if (maximumAutoDownloadMessageSize > 0) {
            fetchFields.add(String.format(Locale.US, "BODY.PEEK[]<0.%d>", maximumAutoDownloadMessageSize));
        } else {
            fetchFields.add("BODY.PEEK[]");
        }
    }
    if (fetchProfile.contains(FetchProfile.Item.BODY)) {
        fetchFields.add("BODY.PEEK[]");
    }
    String spaceSeparatedFetchFields = combine(fetchFields.toArray(new String[fetchFields.size()]), ' ');
    for (int windowStart = 0; windowStart < messages.size(); windowStart += (FETCH_WINDOW_SIZE)) {
        int windowEnd = Math.min(windowStart + FETCH_WINDOW_SIZE, messages.size());
        List<String> uidWindow = uids.subList(windowStart, windowEnd);
        try {
            String commaSeparatedUids = combine(uidWindow.toArray(new String[uidWindow.size()]), ',');
            String command = String.format("UID FETCH %s (%s)", commaSeparatedUids, spaceSeparatedFetchFields);
            connection.sendCommand(command, false);
            ImapResponse response;
            int messageNumber = 0;
            ImapResponseCallback callback = null;
            if (fetchProfile.contains(FetchProfile.Item.BODY) || fetchProfile.contains(FetchProfile.Item.BODY_SANE)) {
                callback = new FetchBodyCallback(messageMap);
            }
            do {
                response = connection.readResponse(callback);
                if (response.getTag() == null && ImapResponseParser.equalsIgnoreCase(response.get(1), "FETCH")) {
                    ImapList fetchList = (ImapList) response.getKeyedValue("FETCH");
                    String uid = fetchList.getKeyedString("UID");
                    long msgSeq = response.getLong(0);
                    if (uid != null) {
                        try {
                            msgSeqUidMap.put(msgSeq, uid);
                            if (K9MailLib.isDebug()) {
                                Log.v(LOG_TAG, "Stored uid '" + uid + "' for msgSeq " + msgSeq + " into map");
                            }
                        } catch (Exception e) {
                            Log.e(LOG_TAG, "Unable to store uid '" + uid + "' for msgSeq " + msgSeq);
                        }
                    }
                    Message message = messageMap.get(uid);
                    if (message == null) {
                        if (K9MailLib.isDebug()) {
                            Log.d(LOG_TAG, "Do not have message in messageMap for UID " + uid + " for " + getLogId());
                        }
                        handleUntaggedResponse(response);
                        continue;
                    }
                    if (listener != null) {
                        listener.messageStarted(uid, messageNumber++, messageMap.size());
                    }
                    ImapMessage imapMessage = (ImapMessage) message;
                    Object literal = handleFetchResponse(imapMessage, fetchList);
                    if (literal != null) {
                        if (literal instanceof String) {
                            String bodyString = (String) literal;
                            InputStream bodyStream = new ByteArrayInputStream(bodyString.getBytes());
                            imapMessage.parse(bodyStream);
                        } else if (literal instanceof Integer) {
                        // All the work was done in FetchBodyCallback.foundLiteral()
                        } else {
                            // This shouldn't happen
                            throw new MessagingException("Got FETCH response with bogus parameters");
                        }
                    }
                    if (listener != null) {
                        listener.messageFinished(imapMessage, messageNumber, messageMap.size());
                    }
                } else {
                    handleUntaggedResponse(response);
                }
            } while (response.getTag() == null);
        } catch (IOException ioe) {
            throw ioExceptionHandler(connection, ioe);
        }
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Message(com.fsck.k9.mail.Message) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) MessagingException(com.fsck.k9.mail.MessagingException) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) ArrayList(java.util.ArrayList) IOException(java.io.IOException) IOException(java.io.IOException) MessagingException(com.fsck.k9.mail.MessagingException) ByteArrayInputStream(java.io.ByteArrayInputStream)

Aggregations

MessagingException (com.fsck.k9.mail.MessagingException)9 IOException (java.io.IOException)5 AuthenticationFailedException (com.fsck.k9.mail.AuthenticationFailedException)4 Date (java.util.Date)4 SuppressLint (android.annotation.SuppressLint)3 ByteArrayInputStream (java.io.ByteArrayInputStream)3 InputStream (java.io.InputStream)3 ArrayList (java.util.ArrayList)3 CertificateValidationException (com.fsck.k9.mail.CertificateValidationException)2 LocalMessage (com.fsck.k9.mailstore.LocalMessage)2 VisibleForTesting (androidx.annotation.VisibleForTesting)1 Account (com.fsck.k9.Account)1 Body (com.fsck.k9.mail.Body)1 Message (com.fsck.k9.mail.Message)1 MessageRetrievalListener (com.fsck.k9.mail.MessageRetrievalListener)1 Pop3Message (com.fsck.k9.mail.store.pop3.Pop3Message)1 WebDavMessage (com.fsck.k9.mail.store.webdav.WebDavMessage)1 LocalStore (com.fsck.k9.mailstore.LocalStore)1 UnavailableStorageException (com.fsck.k9.mailstore.UnavailableStorageException)1 SearchAccount (com.fsck.k9.search.SearchAccount)1