2323import com .flowcrypt .email .api .email .JavaEmailConstants ;
2424import com .flowcrypt .email .api .email .model .AttachmentInfo ;
2525import com .flowcrypt .email .api .email .model .OutgoingMessageInfo ;
26+ import com .flowcrypt .email .api .email .protocol .ImapProtocolUtil ;
2627import com .flowcrypt .email .api .email .sync .EmailSyncManager ;
2728import com .flowcrypt .email .api .email .sync .SyncListener ;
2829import com .flowcrypt .email .database .dao .source .AccountDao ;
3435import com .sun .mail .imap .IMAPFolder ;
3536
3637import java .io .IOException ;
38+ import java .io .InputStream ;
3739import java .lang .ref .WeakReference ;
3840import java .util .ArrayList ;
3941import java .util .Arrays ;
4951import javax .mail .Part ;
5052import javax .mail .internet .ContentType ;
5153import javax .mail .internet .InternetAddress ;
54+ import javax .mail .internet .InternetHeaders ;
5255
5356/**
5457 * This the email synchronization service. This class is responsible for the logic of
@@ -310,18 +313,25 @@ public void onError(AccountDao accountDao, int errorType, Exception e, String ke
310313 * @param folder The local reflection of the remote folder.
311314 * @param imapFolder The folder where the new messages exist.
312315 * @param messages The new messages.
313- * @throws MessagingException
314- * @throws IOException
316+ * @throws MessagingException This exception meybe happen when we try to call {@code
317+ * {@link IMAPFolder#getUID(javax.mail.Message)}}
315318 */
316319 private void updateAttachmentTable (AccountDao accountDao , com .flowcrypt .email .api .email .Folder folder ,
317320 IMAPFolder imapFolder , javax .mail .Message [] messages )
318- throws MessagingException , IOException {
321+ throws MessagingException {
319322 AttachmentDaoSource attachmentDaoSource = new AttachmentDaoSource ();
320323 ArrayList <ContentValues > contentValuesList = new ArrayList <>();
321324
322325 for (javax .mail .Message message : messages ) {
323- ArrayList <AttachmentInfo > attachmentInfoList = getAttachmentsInfo (message );
324- if (!attachmentInfoList .isEmpty ()) {
326+ ArrayList <AttachmentInfo > attachmentInfoList = null ;
327+
328+ try {
329+ attachmentInfoList = getAttachmentsInfoFromPart (imapFolder , message .getMessageNumber (), message );
330+ } catch (IOException e ) {
331+ e .printStackTrace ();
332+ }
333+
334+ if (attachmentInfoList != null && !attachmentInfoList .isEmpty ()) {
325335 for (AttachmentInfo attachmentInfo : attachmentInfoList ) {
326336 contentValuesList .add (AttachmentDaoSource .prepareContentValues (accountDao .getEmail (),
327337 folder .getFolderAlias (), imapFolder .getUID (message ), attachmentInfo ));
@@ -335,13 +345,16 @@ private void updateAttachmentTable(AccountDao accountDao, com.flowcrypt.email.ap
335345 /**
336346 * Find attachments in the {@link Part}.
337347 *
338- * @param part The parent part.
348+ * @param imapFolder The {@link IMAPFolder} which contains the parent message;
349+ * @param messageNumber This number will be used for fetching {@link Part} details;
350+ * @param part The parent part.
339351 * @return The list of created {@link AttachmentInfo}
340352 * @throws MessagingException
341353 * @throws IOException
342354 */
343355 @ NonNull
344- private ArrayList <AttachmentInfo > getAttachmentsInfo (Part part ) throws MessagingException , IOException {
356+ private ArrayList <AttachmentInfo > getAttachmentsInfoFromPart (IMAPFolder imapFolder , int messageNumber , Part part )
357+ throws MessagingException , IOException {
345358 ArrayList <AttachmentInfo > attachmentInfoList = new ArrayList <>();
346359
347360 if (part .isMimeType (JavaEmailConstants .MIME_TYPE_MULTIPART )) {
@@ -351,19 +364,35 @@ private ArrayList<AttachmentInfo> getAttachmentsInfo(Part part) throws Messaging
351364 for (int partCount = 0 ; partCount < numberOfParts ; partCount ++) {
352365 BodyPart bodyPart = multiPart .getBodyPart (partCount );
353366 if (bodyPart .isMimeType (JavaEmailConstants .MIME_TYPE_MULTIPART )) {
354- ArrayList <AttachmentInfo > attachmentInfoLists = getAttachmentsInfo (bodyPart );
355- if (attachmentInfoLists .isEmpty ()) {
367+ ArrayList <AttachmentInfo > attachmentInfoLists = getAttachmentsInfoFromPart (imapFolder ,
368+ messageNumber , bodyPart );
369+ if (!attachmentInfoLists .isEmpty ()) {
356370 attachmentInfoList .addAll (attachmentInfoLists );
357371 }
358- } else if (Part .ATTACHMENT .equalsIgnoreCase (bodyPart .getDisposition ())
359- && (headers = bodyPart .getHeader (JavaEmailConstants .HEADER_X_ATTACHMENT_ID )) != null
360- && headers .length > 0 ) {
361- AttachmentInfo attachmentInfo = new AttachmentInfo ();
362- attachmentInfo .setName (bodyPart .getFileName ());
363- attachmentInfo .setEncodedSize (bodyPart .getSize ());
364- attachmentInfo .setType (new ContentType (bodyPart .getContentType ()).getPrimaryType ());
365- attachmentInfo .setId (headers [0 ]);
366- attachmentInfoList .add (attachmentInfo );
372+ } else if (Part .ATTACHMENT .equalsIgnoreCase (bodyPart .getDisposition ())) {
373+ InputStream inputStream = ImapProtocolUtil .getHeaderStream (imapFolder , messageNumber ,
374+ partCount + 1 );
375+
376+ if (inputStream == null ) {
377+ throw new MessagingException ("Failed to fetch headers" );
378+ }
379+
380+ InternetHeaders internetHeaders = new InternetHeaders (inputStream );
381+ headers = internetHeaders .getHeader (JavaEmailConstants .HEADER_CONTENT_ID );
382+
383+ if (headers == null ) {
384+ //try to receive custom Gmail attachments header X-Attachment-Id
385+ headers = internetHeaders .getHeader (JavaEmailConstants .HEADER_X_ATTACHMENT_ID );
386+ }
387+
388+ if (headers != null && headers .length > 0 ) {
389+ AttachmentInfo attachmentInfo = new AttachmentInfo ();
390+ attachmentInfo .setName (bodyPart .getFileName ());
391+ attachmentInfo .setEncodedSize (bodyPart .getSize ());
392+ attachmentInfo .setType (new ContentType (bodyPart .getContentType ()).getPrimaryType ());
393+ attachmentInfo .setId (headers [0 ]);
394+ attachmentInfoList .add (attachmentInfo );
395+ }
367396 }
368397 }
369398 }
0 commit comments