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);
}
}
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);
}
}
}
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);
}
}
}
}
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();
}
}
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;
}
Aggregations