use of com.fsck.k9.mail.MimeType in project k-9 by k9mail.
the class MigrationTo51 method insertMimeAttachmentPart.
private static MimeStructureState insertMimeAttachmentPart(SQLiteDatabase db, File attachmentDirOld, File attachmentDirNew, MimeStructureState structureState, long id, int size, String name, String mimeType, String storeData, String contentUriString, String contentId, String contentDisposition) {
Timber.d("processing attachment %d, %s, %s, %s, %s", id, name, mimeType, storeData, contentUriString);
if (contentDisposition == null) {
contentDisposition = "attachment";
}
MimeHeader mimeHeader = new MimeHeader();
mimeHeader.setHeader(MimeHeader.HEADER_CONTENT_TYPE, String.format("%s;\r\n name=\"%s\"", mimeType, name));
mimeHeader.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, String.format(Locale.US, "%s;\r\n filename=\"%s\";\r\n size=%d", contentDisposition, name, // TODO: Should use encoded word defined in RFC 2231.
size));
if (contentId != null) {
mimeHeader.setHeader(MimeHeader.HEADER_CONTENT_ID, contentId);
}
boolean hasData = contentUriString != null;
File attachmentFileToMove;
if (hasData) {
try {
Uri contentUri = Uri.parse(contentUriString);
List<String> pathSegments = contentUri.getPathSegments();
String attachmentId = pathSegments.get(1);
boolean isMatchingAttachmentId = Long.parseLong(attachmentId) == id;
File attachmentFile = new File(attachmentDirOld, attachmentId);
boolean isExistingAttachmentFile = attachmentFile.exists();
if (!isMatchingAttachmentId) {
Timber.e("mismatched attachment id. mark as missing");
attachmentFileToMove = null;
} else if (!isExistingAttachmentFile) {
Timber.e("attached file doesn't exist. mark as missing");
attachmentFileToMove = null;
} else {
attachmentFileToMove = attachmentFile;
}
} catch (Exception e) {
// anything here fails, conservatively assume the data doesn't exist
attachmentFileToMove = null;
}
} else {
attachmentFileToMove = null;
}
if (attachmentFileToMove == null) {
Timber.d("matching attachment is in local cache");
}
boolean hasContentTypeAndIsInline = !TextUtils.isEmpty(contentId) && "inline".equalsIgnoreCase(contentDisposition);
int messageType = hasContentTypeAndIsInline ? MESSAGE_PART_TYPE__HIDDEN_ATTACHMENT : MESSAGE_PART_TYPE__UNKNOWN;
ContentValues cv = new ContentValues();
cv.put("type", messageType);
cv.put("mime_type", mimeType);
cv.put("decoded_body_size", size);
cv.put("display_name", name);
cv.put("header", mimeHeader.toString());
cv.put("encoding", MimeUtil.ENC_BINARY);
cv.put("data_location", attachmentFileToMove != null ? DATA_LOCATION__ON_DISK : DATA_LOCATION__MISSING);
cv.put("content_id", contentId);
cv.put("server_extra", storeData);
structureState.applyValues(cv);
long partId = db.insertOrThrow("message_parts", null, cv);
structureState = structureState.nextChild(partId);
if (attachmentFileToMove != null) {
boolean moveOk = attachmentFileToMove.renameTo(new File(attachmentDirNew, Long.toString(partId)));
if (!moveOk) {
Timber.e("Moving attachment to new dir failed!");
}
}
return structureState;
}
use of com.fsck.k9.mail.MimeType in project k-9 by k9mail.
the class MessageFulltextCreator method extractText.
private String extractText(Message message) {
Part textPart = textPartFinder.findFirstTextPart(message);
if (textPart == null || hasEmptyBody(textPart)) {
return null;
}
String text = MessageExtractor.getTextFromPart(textPart, MAX_CHARACTERS_CHECKED_FOR_FTS);
String mimeType = textPart.getMimeType();
if (!MimeUtility.isSameMimeType(mimeType, "text/html")) {
return text;
}
return HtmlConverter.htmlToText(text);
}
use of com.fsck.k9.mail.MimeType in project k-9 by k9mail.
the class ImapFolder method parseBodyStructure.
private void parseBodyStructure(ImapList bs, Part part, String id) throws MessagingException {
if (bs.get(0) instanceof ImapList) {
/*
* This is a multipart/*
*/
MimeMultipart mp = MimeMultipart.newInstance();
for (int i = 0, count = bs.size(); i < count; i++) {
if (bs.get(i) instanceof ImapList) {
/*
* For each part in the message we're going to add a new BodyPart and parse
* into it.
*/
MimeBodyPart bp = new MimeBodyPart();
if (id.equalsIgnoreCase("TEXT")) {
parseBodyStructure(bs.getList(i), bp, Integer.toString(i + 1));
} else {
parseBodyStructure(bs.getList(i), bp, id + "." + (i + 1));
}
mp.addBodyPart(bp);
} else {
/*
* We've got to the end of the children of the part, so now we can find out
* what type it is and bail out.
*/
String subType = bs.getString(i);
mp.setSubType(subType.toLowerCase(Locale.US));
break;
}
}
MimeMessageHelper.setBody(part, mp);
} else {
/*
* This is a body. We need to add as much information as we can find out about
* it to the Part.
*/
/*
* 0| 0 body type
* 1| 1 body subtype
* 2| 2 body parameter parenthesized list
* 3| 3 body id (unused)
* 4| 4 body description (unused)
* 5| 5 body encoding
* 6| 6 body size
* -| 7 text lines (only for type TEXT, unused)
* Extensions (optional):
* 7| 8 body MD5 (unused)
* 8| 9 body disposition
* 9|10 body language (unused)
* 10|11 body location (unused)
*/
String type = bs.getString(0);
String subType = bs.getString(1);
String mimeType = (type + "/" + subType).toLowerCase(Locale.US);
ImapList bodyParams = null;
if (bs.get(2) instanceof ImapList) {
bodyParams = bs.getList(2);
}
String encoding = bs.getString(5);
int size = bs.getNumber(6);
if (MimeUtility.isMessage(mimeType)) {
/*
* This will be caught by fetch and handled appropriately.
*/
throw new MessagingException("BODYSTRUCTURE message/rfc822 not yet supported.");
}
/*
* Set the content type with as much information as we know right now.
*/
StringBuilder contentType = new StringBuilder();
contentType.append(mimeType);
if (bodyParams != null) {
/*
* If there are body params we might be able to get some more information out
* of them.
*/
for (int i = 0, count = bodyParams.size(); i < count; i += 2) {
String paramName = bodyParams.getString(i);
String paramValue = bodyParams.getString(i + 1);
contentType.append(String.format(";\r\n %s=\"%s\"", paramName, paramValue));
}
}
part.setHeader(MimeHeader.HEADER_CONTENT_TYPE, contentType.toString());
// Extension items
ImapList bodyDisposition = null;
if ("text".equalsIgnoreCase(type) && bs.size() > 9 && bs.get(9) instanceof ImapList) {
bodyDisposition = bs.getList(9);
} else if (!("text".equalsIgnoreCase(type)) && bs.size() > 8 && bs.get(8) instanceof ImapList) {
bodyDisposition = bs.getList(8);
}
StringBuilder contentDisposition = new StringBuilder();
if (bodyDisposition != null && !bodyDisposition.isEmpty()) {
if (!"NIL".equalsIgnoreCase(bodyDisposition.getString(0))) {
contentDisposition.append(bodyDisposition.getString(0).toLowerCase(Locale.US));
}
if (bodyDisposition.size() > 1 && bodyDisposition.get(1) instanceof ImapList) {
ImapList bodyDispositionParams = bodyDisposition.getList(1);
/*
* If there is body disposition information we can pull some more information
* about the attachment out.
*/
for (int i = 0, count = bodyDispositionParams.size(); i < count; i += 2) {
String paramName = bodyDispositionParams.getString(i).toLowerCase(Locale.US);
String paramValue = bodyDispositionParams.getString(i + 1);
contentDisposition.append(String.format(";\r\n %s=\"%s\"", paramName, paramValue));
}
}
}
if (MimeUtility.getHeaderParameter(contentDisposition.toString(), "size") == null) {
contentDisposition.append(String.format(Locale.US, ";\r\n size=%d", size));
}
/*
* Set the content disposition containing at least the size. Attachment
* handling code will use this down the road.
*/
part.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, contentDisposition.toString());
/*
* Set the Content-Transfer-Encoding header. Attachment code will use this
* to parse the body.
*/
part.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, encoding);
if (part instanceof ImapMessage) {
((ImapMessage) part).setSize(size);
}
part.setServerExtra(id);
}
}
use of com.fsck.k9.mail.MimeType in project k-9 by k9mail.
the class MessageCreationHelper method createMessage.
private static Message createMessage(String mimeType, Body body) {
MimeMessage message = new MimeMessage();
message.setBody(body);
message.setHeader(MimeHeader.HEADER_CONTENT_TYPE, mimeType);
return message;
}
use of com.fsck.k9.mail.MimeType in project k-9 by k9mail.
the class LocalMessage method populateFromGetMessageCursor.
void populateFromGetMessageCursor(Cursor cursor) throws MessagingException {
final String subject = cursor.getString(LocalStore.MSG_INDEX_SUBJECT);
this.setSubject(subject == null ? "" : subject);
Address[] from = Address.unpack(cursor.getString(LocalStore.MSG_INDEX_SENDER_LIST));
if (from.length > 0) {
this.setFrom(from[0]);
}
this.setInternalSentDate(new Date(cursor.getLong(LocalStore.MSG_INDEX_DATE)));
this.setUid(cursor.getString(LocalStore.MSG_INDEX_UID));
String flagList = cursor.getString(LocalStore.MSG_INDEX_FLAGS);
if (flagList != null && flagList.length() > 0) {
String[] flags = flagList.split(",");
for (String flag : flags) {
try {
this.setFlagInternal(Flag.valueOf(flag), true);
} catch (Exception e) {
if (!"X_BAD_FLAG".equals(flag)) {
Timber.w("Unable to parse flag %s", flag);
}
}
}
}
this.databaseId = cursor.getLong(LocalStore.MSG_INDEX_ID);
mTo = getAddressesOrNull(Address.unpack(cursor.getString(LocalStore.MSG_INDEX_TO)));
mCc = getAddressesOrNull(Address.unpack(cursor.getString(LocalStore.MSG_INDEX_CC)));
mBcc = getAddressesOrNull(Address.unpack(cursor.getString(LocalStore.MSG_INDEX_BCC)));
headerNeedsUpdating = true;
this.setReplyTo(Address.unpack(cursor.getString(LocalStore.MSG_INDEX_REPLY_TO)));
this.attachmentCount = cursor.getInt(LocalStore.MSG_INDEX_ATTACHMENT_COUNT);
this.setInternalDate(new Date(cursor.getLong(LocalStore.MSG_INDEX_INTERNAL_DATE)));
this.setMessageId(cursor.getString(LocalStore.MSG_INDEX_MESSAGE_ID_HEADER));
String previewTypeString = cursor.getString(LocalStore.MSG_INDEX_PREVIEW_TYPE);
DatabasePreviewType databasePreviewType = DatabasePreviewType.fromDatabaseValue(previewTypeString);
previewType = databasePreviewType.getPreviewType();
if (previewType == PreviewType.TEXT) {
preview = cursor.getString(LocalStore.MSG_INDEX_PREVIEW);
} else {
preview = "";
}
if (this.mFolder == null) {
LocalFolder f = new LocalFolder(this.localStore, cursor.getInt(LocalStore.MSG_INDEX_FOLDER_ID));
f.open();
this.mFolder = f;
}
threadId = (cursor.isNull(LocalStore.MSG_INDEX_THREAD_ID)) ? -1 : cursor.getLong(LocalStore.MSG_INDEX_THREAD_ID);
rootId = (cursor.isNull(LocalStore.MSG_INDEX_THREAD_ROOT_ID)) ? -1 : cursor.getLong(LocalStore.MSG_INDEX_THREAD_ROOT_ID);
boolean deleted = (cursor.getInt(LocalStore.MSG_INDEX_FLAG_DELETED) == 1);
boolean read = (cursor.getInt(LocalStore.MSG_INDEX_FLAG_READ) == 1);
boolean flagged = (cursor.getInt(LocalStore.MSG_INDEX_FLAG_FLAGGED) == 1);
boolean answered = (cursor.getInt(LocalStore.MSG_INDEX_FLAG_ANSWERED) == 1);
boolean forwarded = (cursor.getInt(LocalStore.MSG_INDEX_FLAG_FORWARDED) == 1);
setFlagInternal(Flag.DELETED, deleted);
setFlagInternal(Flag.SEEN, read);
setFlagInternal(Flag.FLAGGED, flagged);
setFlagInternal(Flag.ANSWERED, answered);
setFlagInternal(Flag.FORWARDED, forwarded);
setMessagePartId(cursor.getLong(LocalStore.MSG_INDEX_MESSAGE_PART_ID));
MimeType mimeType = MimeType.parseOrNull(cursor.getString(LocalStore.MSG_INDEX_MIME_TYPE));
this.mimeType = mimeType != null ? mimeType.toString() : DEFAULT_MIME_TYPE;
byte[] header = cursor.getBlob(LocalStore.MSG_INDEX_HEADER_DATA);
if (header != null) {
MessageHeaderParser.parse(new ByteArrayInputStream(header), this::addRawHeader);
} else {
Timber.d("No headers available for this message!");
}
headerNeedsUpdating = false;
}
Aggregations