Search in sources :

Example 31 with K9

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

the class LocalFolder method saveMessage.

protected void saveMessage(SQLiteDatabase db, Message message, boolean copy, Map<String, String> uidMap) throws MessagingException {
    if (!(message instanceof MimeMessage)) {
        throw new Error("LocalStore can only store Messages that extend MimeMessage");
    }
    long oldMessageId = -1;
    String uid = message.getUid();
    boolean shouldCreateNewMessage = uid == null || copy;
    if (shouldCreateNewMessage) {
        String randomLocalUid = K9.LOCAL_UID_PREFIX + UUID.randomUUID().toString();
        if (copy) {
            // Save mapping: source UID -> target UID
            uidMap.put(uid, randomLocalUid);
        } else {
            // Modify the Message instance to reference the new UID
            message.setUid(randomLocalUid);
        }
        // The message will be saved with the newly generated UID
        uid = randomLocalUid;
    } else {
        LocalMessage oldMessage = getMessage(uid);
        if (oldMessage != null) {
            oldMessageId = oldMessage.getId();
            long oldRootMessagePartId = oldMessage.getMessagePartId();
            deleteMessagePartsAndDataFromDisk(oldRootMessagePartId);
        }
    }
    long rootId = -1;
    long parentId = -1;
    long msgId;
    if (oldMessageId == -1) {
        // This is a new message. Do the message threading.
        ThreadInfo threadInfo = doMessageThreading(db, message);
        oldMessageId = threadInfo.msgId;
        rootId = threadInfo.rootId;
        parentId = threadInfo.parentId;
    }
    try {
        MessagePreviewCreator previewCreator = localStore.getMessagePreviewCreator();
        PreviewResult previewResult = previewCreator.createPreview(message);
        PreviewType previewType = previewResult.getPreviewType();
        DatabasePreviewType databasePreviewType = DatabasePreviewType.fromPreviewType(previewType);
        MessageFulltextCreator fulltextCreator = localStore.getMessageFulltextCreator();
        String fulltext = fulltextCreator.createFulltext(message);
        AttachmentCounter attachmentCounter = localStore.getAttachmentCounter();
        int attachmentCount = attachmentCounter.getAttachmentCount(message);
        long rootMessagePartId = saveMessageParts(db, message);
        ContentValues cv = new ContentValues();
        cv.put("message_part_id", rootMessagePartId);
        cv.put("uid", uid);
        cv.put("subject", message.getSubject());
        cv.put("sender_list", Address.pack(message.getFrom()));
        cv.put("date", message.getSentDate() == null ? System.currentTimeMillis() : message.getSentDate().getTime());
        cv.put("flags", this.localStore.serializeFlags(message.getFlags()));
        cv.put("deleted", message.isSet(Flag.DELETED) ? 1 : 0);
        cv.put("read", message.isSet(Flag.SEEN) ? 1 : 0);
        cv.put("flagged", message.isSet(Flag.FLAGGED) ? 1 : 0);
        cv.put("answered", message.isSet(Flag.ANSWERED) ? 1 : 0);
        cv.put("forwarded", message.isSet(Flag.FORWARDED) ? 1 : 0);
        cv.put("folder_id", mFolderId);
        cv.put("to_list", Address.pack(message.getRecipients(RecipientType.TO)));
        cv.put("cc_list", Address.pack(message.getRecipients(RecipientType.CC)));
        cv.put("bcc_list", Address.pack(message.getRecipients(RecipientType.BCC)));
        cv.put("reply_to_list", Address.pack(message.getReplyTo()));
        cv.put("attachment_count", attachmentCount);
        cv.put("internal_date", message.getInternalDate() == null ? System.currentTimeMillis() : message.getInternalDate().getTime());
        cv.put("mime_type", message.getMimeType());
        cv.put("empty", 0);
        cv.put("preview_type", databasePreviewType.getDatabaseValue());
        if (previewResult.isPreviewTextAvailable()) {
            cv.put("preview", previewResult.getPreviewText());
        } else {
            cv.putNull("preview");
        }
        String messageId = message.getMessageId();
        if (messageId != null) {
            cv.put("message_id", messageId);
        }
        if (oldMessageId == -1) {
            msgId = db.insert("messages", "uid", cv);
            // Create entry in 'threads' table
            cv.clear();
            cv.put("message_id", msgId);
            if (rootId != -1) {
                cv.put("root", rootId);
            }
            if (parentId != -1) {
                cv.put("parent", parentId);
            }
            db.insert("threads", null, cv);
        } else {
            msgId = oldMessageId;
            db.update("messages", cv, "id = ?", new String[] { Long.toString(oldMessageId) });
        }
        if (fulltext != null) {
            cv.clear();
            cv.put("docid", msgId);
            cv.put("fulltext", fulltext);
            db.replace("messages_fulltext", null, cv);
        }
    } catch (Exception e) {
        throw new MessagingException("Error appending message: " + message.getSubject(), e);
    }
}
Also used : ContentValues(android.content.ContentValues) MessageFulltextCreator(com.fsck.k9.message.extractors.MessageFulltextCreator) MessagingException(com.fsck.k9.mail.MessagingException) AttachmentCounter(com.fsck.k9.message.extractors.AttachmentCounter) PreviewResult(com.fsck.k9.message.extractors.PreviewResult) MessagePreviewCreator(com.fsck.k9.message.extractors.MessagePreviewCreator) WrappedException(com.fsck.k9.mailstore.LockableDatabase.WrappedException) IOException(java.io.IOException) MessagingException(com.fsck.k9.mail.MessagingException) PreviewType(com.fsck.k9.message.extractors.PreviewResult.PreviewType) MimeMessage(com.fsck.k9.mail.internet.MimeMessage)

Example 32 with K9

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

the class MessageListFragment method onSpamConfirmed.

private void onSpamConfirmed(List<MessageReference> messages) {
    Map<Account, List<MessageReference>> messagesByAccount = groupMessagesByAccount(messages);
    for (Entry<Account, List<MessageReference>> entry : messagesByAccount.entrySet()) {
        Account account = entry.getKey();
        String spamFolder = account.getSpamFolderName();
        if (!K9.FOLDER_NONE.equals(spamFolder)) {
            move(entry.getValue(), spamFolder);
        }
    }
}
Also used : Account(com.fsck.k9.Account) ArrayList(java.util.ArrayList) List(java.util.List)

Example 33 with K9

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

the class MessageListFragment method copyOrMove.

/**
     * The underlying implementation for {@link #copy(List, String)} and
     * {@link #move(List, String)}. This method was added mainly because those 2
     * methods share common behavior.
     *
     * @param messages
     *         The list of messages to copy or move. Never {@code null}.
     * @param destination
     *         The name of the destination folder. Never {@code null} or {@link K9#FOLDER_NONE}.
     * @param operation
     *         Specifies what operation to perform. Never {@code null}.
     */
private void copyOrMove(List<MessageReference> messages, final String destination, final FolderOperation operation) {
    Map<String, List<MessageReference>> folderMap = new HashMap<>();
    for (MessageReference message : messages) {
        if ((operation == FolderOperation.MOVE && !messagingController.isMoveCapable(message)) || (operation == FolderOperation.COPY && !messagingController.isCopyCapable(message))) {
            Toast.makeText(getActivity(), R.string.move_copy_cannot_copy_unsynced_message, Toast.LENGTH_LONG).show();
            // message isn't synchronized
            return;
        }
        String folderName = message.getFolderName();
        if (folderName.equals(destination)) {
            // Skip messages already in the destination folder
            continue;
        }
        List<MessageReference> outMessages = folderMap.get(folderName);
        if (outMessages == null) {
            outMessages = new ArrayList<>();
            folderMap.put(folderName, outMessages);
        }
        outMessages.add(message);
    }
    for (Map.Entry<String, List<MessageReference>> entry : folderMap.entrySet()) {
        String folderName = entry.getKey();
        List<MessageReference> outMessages = entry.getValue();
        Account account = preferences.getAccount(outMessages.get(0).getAccountUuid());
        if (operation == FolderOperation.MOVE) {
            if (showingThreadedList) {
                messagingController.moveMessagesInThread(account, folderName, outMessages, destination);
            } else {
                messagingController.moveMessages(account, folderName, outMessages, destination);
            }
        } else {
            if (showingThreadedList) {
                messagingController.copyMessagesInThread(account, folderName, outMessages, destination);
            } else {
                messagingController.copyMessages(account, folderName, outMessages, destination);
            }
        }
    }
}
Also used : Account(com.fsck.k9.Account) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) List(java.util.List) MessageReference(com.fsck.k9.activity.MessageReference) Map(java.util.Map) EnumMap(java.util.EnumMap) HashMap(java.util.HashMap)

Example 34 with K9

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

the class LockableDatabase method execute.

/**
     * Execute a DB callback in a shared context (doesn't prevent concurrent
     * shared executions), taking care of locking the DB storage.
     *
     * <p>
     * Can be instructed to start a transaction if none is currently active in
     * the current thread. Callback will participate in any active transaction (no
     * inner transaction created).
     * </p>
     *
     * @param transactional
     *            <code>true</code> the callback must be executed in a
     *            transactional context.
     * @param callback
     *            Never <code>null</code>.
     * @return Whatever {@link DbCallback#doDbWork(SQLiteDatabase)} returns.
     * @throws UnavailableStorageException
     */
public <T> T execute(final boolean transactional, final DbCallback<T> callback) throws MessagingException {
    lockRead();
    final boolean doTransaction = transactional && inTransaction.get() == null;
    try {
        final boolean debug = K9.isDebug();
        if (doTransaction) {
            inTransaction.set(Boolean.TRUE);
            mDb.beginTransaction();
        }
        try {
            final T result = callback.doDbWork(mDb);
            if (doTransaction) {
                mDb.setTransactionSuccessful();
            }
            return result;
        } finally {
            if (doTransaction) {
                final long begin;
                if (debug) {
                    begin = System.currentTimeMillis();
                } else {
                    begin = 0L;
                }
                // not doing endTransaction in the same 'finally' block of unlockRead() because endTransaction() may throw an exception
                mDb.endTransaction();
                if (debug) {
                    Timber.v("LockableDatabase: Transaction ended, took %d ms / %s", currentTimeMillis() - begin, new Exception().getStackTrace()[1]);
                }
            }
        }
    } finally {
        if (doTransaction) {
            inTransaction.set(null);
        }
        unlockRead();
    }
}
Also used : SQLiteException(android.database.sqlite.SQLiteException) MessagingException(com.fsck.k9.mail.MessagingException)

Example 35 with K9

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

the class TextBodyBuilder method buildTextHtml.

/**
     * Build the {@link Body} that will contain the text of the message.
     *
     * @return {@link com.fsck.k9.mail.internet.TextBody} instance that contains the entered text and
     *         possibly the quoted original message.
     */
public TextBody buildTextHtml() {
    // The length of the formatted version of the user-supplied text/reply
    int composedMessageLength;
    // The offset of the user-supplied text/reply in the final text body
    int composedMessageOffset;
    // Get the user-supplied text
    String text = mMessageContent;
    // Do we have to modify an existing message to include our reply?
    if (mIncludeQuotedText) {
        InsertableHtmlContent quotedHtmlContent = getQuotedTextHtml();
        if (K9.isDebug()) {
            Timber.d("insertable: %s", quotedHtmlContent.toDebugString());
        }
        if (mAppendSignature) {
            // Append signature to the reply
            if (mReplyAfterQuote || mSignatureBeforeQuotedText) {
                text += getSignature();
            }
        }
        // Convert the text to HTML
        text = textToHtmlFragment(text);
        /*
             * Set the insertion location based upon our reply after quote
             * setting. Additionally, add some extra separators between the
             * composed message and quoted message depending on the quote
             * location. We only add the extra separators when we're
             * sending, that way when we load a draft, we don't have to know
             * the length of the separators to remove them before editing.
             */
        if (mReplyAfterQuote) {
            quotedHtmlContent.setInsertionLocation(InsertableHtmlContent.InsertionLocation.AFTER_QUOTE);
            if (mInsertSeparator) {
                text = "<br clear=\"all\">" + text;
            }
        } else {
            quotedHtmlContent.setInsertionLocation(InsertableHtmlContent.InsertionLocation.BEFORE_QUOTE);
            if (mInsertSeparator) {
                text += "<br><br>";
            }
        }
        if (mAppendSignature) {
            // Place signature immediately after the quoted text
            if (!(mReplyAfterQuote || mSignatureBeforeQuotedText)) {
                quotedHtmlContent.insertIntoQuotedFooter(getSignatureHtml());
            }
        }
        quotedHtmlContent.setUserContent(text);
        // Save length of the body and its offset.  This is used when thawing drafts.
        composedMessageLength = text.length();
        composedMessageOffset = quotedHtmlContent.getInsertionPoint();
        text = quotedHtmlContent.toString();
    } else {
        // There is no text to quote so simply append the signature if available
        if (mAppendSignature) {
            text += getSignature();
        }
        // Convert the text to HTML
        text = textToHtmlFragment(text);
        //TODO: Wrap this in proper HTML tags
        composedMessageLength = text.length();
        composedMessageOffset = 0;
    }
    TextBody body = new TextBody(text);
    body.setComposedMessageLength(composedMessageLength);
    body.setComposedMessageOffset(composedMessageOffset);
    return body;
}
Also used : TextBody(com.fsck.k9.mail.internet.TextBody) InsertableHtmlContent(com.fsck.k9.message.quote.InsertableHtmlContent)

Aggregations

Account (com.fsck.k9.Account)20 MessagingException (com.fsck.k9.mail.MessagingException)13 IOException (java.io.IOException)11 ArrayList (java.util.ArrayList)11 MimeMessage (com.fsck.k9.mail.internet.MimeMessage)10 LocalStore (com.fsck.k9.mailstore.LocalStore)10 Message (com.fsck.k9.mail.Message)9 Store (com.fsck.k9.mail.Store)9 LocalFolder (com.fsck.k9.mailstore.LocalFolder)9 UnavailableStorageException (com.fsck.k9.mailstore.UnavailableStorageException)9 Intent (android.content.Intent)8 Pop3Store (com.fsck.k9.mail.store.pop3.Pop3Store)8 LocalMessage (com.fsck.k9.mailstore.LocalMessage)8 SuppressLint (android.annotation.SuppressLint)7 BaseAccount (com.fsck.k9.BaseAccount)7 Preferences (com.fsck.k9.Preferences)7 AuthenticationFailedException (com.fsck.k9.mail.AuthenticationFailedException)7 CertificateValidationException (com.fsck.k9.mail.CertificateValidationException)7 Folder (com.fsck.k9.mail.Folder)7 SearchAccount (com.fsck.k9.search.SearchAccount)7