/** * Add a single attachment part to the message * * <p>This will skip adding attachments if they are already found in the attachments table. The * heuristic for this will fail (false-positive) if two identical attachments are included in a * single POP3 message. TODO: Fix that, by (elsewhere) simulating an mLocation value based on the * attachments position within the list of multipart/mixed elements. This would make every POP3 * attachment unique, and might also simplify the code (since we could just look at the positions, * and ignore the filename, etc.) * * <p>TODO: Take a closer look at encoding and deal with it if necessary. * * @param context a context for file operations * @param localMessage the attachments will be built against this message * @param part a single attachment part from POP or IMAP */ public static void addOneAttachment( final Context context, final EmailContent.Message localMessage, final Part part) throws MessagingException, IOException { final Attachment localAttachment = mimePartToAttachment(part); localAttachment.mMessageKey = localMessage.mId; localAttachment.mAccountKey = localMessage.mAccountKey; if (DEBUG_ATTACHMENTS) { LogUtils.d(Logging.LOG_TAG, "Add attachment " + localAttachment); } // To prevent duplication - do we already have a matching attachment? // The fields we'll check for equality are: // mFileName, mMimeType, mContentId, mMessageKey, mLocation // NOTE: This will false-positive if you attach the exact same file, twice, to a POP3 // message. We can live with that - you'll get one of the copies. final Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, localMessage.mId); final Cursor cursor = context.getContentResolver().query(uri, Attachment.CONTENT_PROJECTION, null, null, null); boolean attachmentFoundInDb = false; try { while (cursor.moveToNext()) { final Attachment dbAttachment = new Attachment(); dbAttachment.restore(cursor); // We test each of the fields here (instead of in SQL) because they may be // null, or may be strings. if (!TextUtils.equals(dbAttachment.mFileName, localAttachment.mFileName) || !TextUtils.equals(dbAttachment.mMimeType, localAttachment.mMimeType) || !TextUtils.equals(dbAttachment.mContentId, localAttachment.mContentId) || !TextUtils.equals(dbAttachment.mLocation, localAttachment.mLocation)) { continue; } // We found a match, so use the existing attachment id, and stop looking/looping attachmentFoundInDb = true; localAttachment.mId = dbAttachment.mId; if (DEBUG_ATTACHMENTS) { LogUtils.d(Logging.LOG_TAG, "Skipped, found db attachment " + dbAttachment); } break; } } finally { cursor.close(); } // Save the attachment (so far) in order to obtain an id if (!attachmentFoundInDb) { localAttachment.save(context); } // If an attachment body was actually provided, we need to write the file now saveAttachmentBody(context, part, localAttachment, localMessage.mAccountKey); if (localMessage.mAttachments == null) { localMessage.mAttachments = new ArrayList<Attachment>(); } localMessage.mAttachments.add(localAttachment); localMessage.mFlagAttachment = true; }
private void attachmentParser( final ArrayList<EmailContent.Attachment> atts, final EmailContent.Message msg, final int endingTag) throws IOException { String fileName = null; String length = null; String location = null; boolean isInline = false; String contentId = null; while (nextTag(endingTag) != END) { switch (tag) { // We handle both EAS 2.5 and 12.0+ attachments here case Tags.EMAIL_DISPLAY_NAME: case Tags.BASE_DISPLAY_NAME: fileName = getValue(); break; case Tags.EMAIL_ATT_NAME: case Tags.BASE_FILE_REFERENCE: location = getValue(); break; case Tags.EMAIL_ATT_SIZE: case Tags.BASE_ESTIMATED_DATA_SIZE: length = getValue(); break; case Tags.BASE_IS_INLINE: String isInlineStr = getValue(); isInline = "true".equalsIgnoreCase(isInlineStr) || "1".equals(isInlineStr); break; case Tags.BASE_CONTENT_ID: contentId = getValue(); break; default: skipTag(); } } if ((fileName != null) && (length != null) && (location != null)) { EmailContent.Attachment att = new EmailContent.Attachment(); att.mEncoding = "base64"; att.mSize = Long.parseLong(length); att.mFileName = fileName; att.mLocation = location; att.mMimeType = getMimeTypeFromFileName(fileName); att.mAccountKey = mAccount.mId; // Save away the contentId, if we've got one (for inline images); note that the // EAS docs appear to be wrong about the tags used; inline images come with // contentId rather than contentLocation, when sent from Ex03, Ex07, and Ex10 if (isInline && !TextUtils.isEmpty(contentId)) { att.mContentId = contentId; } // Check if this attachment can't be downloaded due to an account policy if (mPolicy != null) { if (mPolicy.mDontAllowAttachments || (mPolicy.mMaxAttachmentSize > 0 && (att.mSize > mPolicy.mMaxAttachmentSize))) { att.mFlags = EmailContent.Attachment.FLAG_POLICY_DISALLOWS_DOWNLOAD; } } atts.add(att); msg.mFlagAttachment = true; } }