private Part findTextPartInMultipart(Multipart multipart) { for (BodyPart bodyPart : multipart.getBodyParts()) { String mimeType = bodyPart.getMimeType(); Body body = bodyPart.getBody(); if (body instanceof Multipart) { Part candidatePart = findFirstTextPart(bodyPart); if (candidatePart != null) { return candidatePart; } } else if (isSameMimeType(mimeType, "text/plain") || isSameMimeType(mimeType, "text/html")) { return bodyPart; } } return null; } }
@Override public void writeTo(OutputStream os) throws IOException { try { Multipart multipartSignedMultipart = (Multipart) signedPart.getBody(); BodyPart signatureBodyPart = multipartSignedMultipart.getBodyPart(0); Timber.d("signed data type: %s", signatureBodyPart.getMimeType()); signatureBodyPart.writeTo(os); } catch (MessagingException e) { Timber.e(e, "Exception while writing message to crypto provider"); } } };
public static MimeMessage messageFromBody(BodyPart bodyPart) throws MessagingException { MimeMessage message = new MimeMessage(); MimeMessageHelper.setBody(message, bodyPart.getBody()); if (bodyPart.getContentType() != null) { message.setHeader("Content-Type", bodyPart.getContentType()); } message.setUid("msguid"); return message; }
public void setCharset(String charset) throws MessagingException { if (mParts.isEmpty()) return; BodyPart part = mParts.get(0); Body body = part.getBody(); if (body instanceof TextBody) { CharsetSupport.setCharset(charset, part); ((TextBody)body).setCharset(charset); } }
@Test public void build_usingHtmlFormat_shouldUseMultipartAlternativeInCorrectOrder() { MessageBuilder messageBuilder = createHtmlMessageBuilder(); messageBuilder.buildAsync(callback); MimeMessage message = getMessageFromCallback(); assertEquals(MimeMultipart.class, message.getBody().getClass()); assertEquals("multipart/alternative", ((MimeMultipart) message.getBody()).getMimeType()); List<BodyPart> parts = ((MimeMultipart) message.getBody()).getBodyParts(); //RFC 2046 - 5.1.4. - Best type is last displayable assertEquals("text/plain", parts.get(0).getMimeType()); assertEquals("text/html", parts.get(1).getMimeType()); }
@Override public void writeTo(OutputStream out) throws IOException, MessagingException { BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024); if (preamble != null) { out.write(preamble); writer.write("\r\n"); } if (getBodyParts().isEmpty()) { writer.write("--"); writer.write(boundary); writer.write("\r\n"); } else { for (BodyPart bodyPart : getBodyParts()) { writer.write("--"); writer.write(boundary); writer.write("\r\n"); writer.flush(); bodyPart.writeTo(out); writer.write("\r\n"); } } writer.write("--"); writer.write(boundary); writer.write("--\r\n"); writer.flush(); if (epilogue != null) { out.write(epilogue); } }
private static Message getMessageFromPart(Part part) { while (part != null) { if (part instanceof Message) return (Message)part; if (!(part instanceof BodyPart)) return null; Multipart multipart = ((BodyPart)part).getParent(); if (multipart == null) return null; part = multipart.getParent(); } return null; }
@Test public void buildCidMap__onMultipartWithEmptyBodyPart__shouldReturnEmptyMap() throws Exception { Multipart multipartBody = MimeMultipart.newInstance(); BodyPart bodyPart = spy(new MimeBodyPart()); Part multipartPart = new MimeBodyPart(multipartBody); multipartBody.addBodyPart(bodyPart); Map<String,Uri> result = AttachmentResolver.buildCidToAttachmentUriMap(attachmentInfoExtractor, multipartPart); verify(bodyPart).getContentId(); assertTrue(result.isEmpty()); }
public static byte[] getSignatureData(Part part) throws IOException, MessagingException { if (isPartMultipartSigned(part)) { Body body = part.getBody(); if (body instanceof Multipart) { Multipart multi = (Multipart) body; BodyPart signatureBody = multi.getBodyPart(1); ByteArrayOutputStream bos = new ByteArrayOutputStream(); signatureBody.getBody().writeTo(bos); return bos.toByteArray(); } } return null; }
@Test public void migratePgpMimeSignedMessage() throws Exception { SQLiteDatabase db = createV50Database(); insertPgpMimeSignedMessage(db); db.close(); LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account); LocalMessage msg = localStore.getFolder("dev").getMessage("5"); FetchProfile fp = new FetchProfile(); fp.add(FetchProfile.Item.BODY); localStore.getFolder("dev").fetch(Collections.singletonList(msg), fp, null); Assert.assertEquals(4, msg.getDatabaseId()); Assert.assertEquals(8, msg.getHeaderNames().size()); Assert.assertEquals("multipart/mixed", msg.getMimeType()); Assert.assertEquals(2, msg.getAttachmentCount()); Multipart body = (Multipart) msg.getBody(); Assert.assertEquals(3, body.getCount()); Assert.assertEquals("multipart/alternative", body.getBodyPart(0).getMimeType()); Assert.assertEquals("image/png", body.getBodyPart(1).getMimeType()); Assert.assertEquals("application/pgp-signature", body.getBodyPart(2).getMimeType()); }
private void processSignedMessageAndCaptureMocks(Message message, BodyPart signedBodyPart, OutputStream outputStream) throws Exception { messageCryptoHelper.asyncStartOrResumeProcessingMessage(message, messageCryptoCallback, null, true); ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); ArgumentCaptor<OpenPgpDataSource> dataSourceCaptor = ArgumentCaptor.forClass(OpenPgpDataSource.class); ArgumentCaptor<IOpenPgpSinkResultCallback> callbackCaptor = ArgumentCaptor.forClass(IOpenPgpSinkResultCallback.class); verify(openPgpApi).executeApiAsync(intentCaptor.capture(), dataSourceCaptor.capture(), callbackCaptor.capture()); capturedApiIntent = intentCaptor.getValue(); capturedCallback = callbackCaptor.getValue(); OpenPgpDataSource dataSource = dataSourceCaptor.getValue(); dataSource.writeTo(outputStream); verify(signedBodyPart).writeTo(outputStream); }
private Part findTextPartInMultipartAlternative(Multipart multipart) { Part htmlPart = null; for (BodyPart bodyPart : multipart.getBodyParts()) { String mimeType = bodyPart.getMimeType(); Body body = bodyPart.getBody(); if (body instanceof Multipart) { Part candidatePart = findFirstTextPart(bodyPart); if (candidatePart != null) { if (isSameMimeType(candidatePart.getMimeType(), "text/html")) { htmlPart = candidatePart; } else { return candidatePart; } } } else if (isSameMimeType(mimeType, "text/plain")) { return bodyPart; } else if (isSameMimeType(mimeType, "text/html") && htmlPart == null) { htmlPart = bodyPart; } } if (htmlPart != null) { return htmlPart; } return null; }
private static List<Body> getLeafParts(Body body) { if (body instanceof Multipart) { List<Body> ret = new ArrayList<>(); for (BodyPart child : ((Multipart) body).getBodyParts()) { ret.addAll(getLeafParts(child.getBody())); } return ret; } else { return Collections.singletonList(body); } }
@Test public void migratePgpMimeEncryptedMessage() throws Exception { SQLiteDatabase db = createV50Database(); insertPgpMimeEncryptedMessage(db); db.close(); LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account); LocalMessage msg = localStore.getFolder("dev").getMessage("6"); FetchProfile fp = new FetchProfile(); fp.add(FetchProfile.Item.BODY); localStore.getFolder("dev").fetch(Collections.singletonList(msg), fp, null); Assert.assertEquals(5, msg.getDatabaseId()); Assert.assertEquals(13, msg.getHeaderNames().size()); Assert.assertEquals("multipart/encrypted", msg.getMimeType()); Assert.assertEquals(2, msg.getAttachmentCount()); Multipart body = (Multipart) msg.getBody(); Assert.assertEquals(1, msg.getHeader(MimeHeader.HEADER_CONTENT_TYPE).length); Assert.assertEquals("application/pgp-encrypted", MimeUtility.getHeaderParameter(msg.getHeader(MimeHeader.HEADER_CONTENT_TYPE)[0], "protocol")); Assert.assertEquals("UoPmpPX/dBe4BELn", MimeUtility.getHeaderParameter(msg.getHeader(MimeHeader.HEADER_CONTENT_TYPE)[0], "boundary")); Assert.assertEquals("UoPmpPX/dBe4BELn", body.getBoundary()); Assert.assertEquals(2, body.getCount()); Assert.assertEquals("application/pgp-encrypted", body.getBodyPart(0).getMimeType()); Assert.assertEquals("application/octet-stream", body.getBodyPart(1).getMimeType()); }
public static boolean isPartMultipartEncrypted(Part part) { if (!isSameMimeType(part.getMimeType(), MULTIPART_ENCRYPTED)) { return false; } if (! (part.getBody() instanceof MimeMultipart)) { return false; } MimeMultipart mimeMultipart = (MimeMultipart) part.getBody(); if (mimeMultipart.getCount() != 2) { return false; } String protocolParameter = MimeUtility.getHeaderParameter(part.getContentType(), PROTOCOL_PARAMETER); // for partially downloaded messages the protocol parameter isn't yet available, so we'll just assume it's ok boolean dataUnavailable = protocolParameter == null && mimeMultipart.getBodyPart(1).getBody() == null; boolean protocolMatches = isSameMimeType(protocolParameter, mimeMultipart.getBodyPart(0).getMimeType()); return dataUnavailable || protocolMatches; }
@Override public Long getSizeForProgress() { Part part = currentCryptoPart.part; CryptoPartType cryptoPartType = currentCryptoPart.type; Body body; if (cryptoPartType == CryptoPartType.PGP_ENCRYPTED) { Multipart multipartEncryptedMultipart = (Multipart) part.getBody(); BodyPart encryptionPayloadPart = multipartEncryptedMultipart.getBodyPart(1); body = encryptionPayloadPart.getBody(); } else if (cryptoPartType == CryptoPartType.PGP_INLINE) { body = part.getBody(); } else { throw new IllegalStateException("part to stream must be encrypted or inline!"); } if (body instanceof SizeAware) { return ((SizeAware) body).getSize(); } return null; }
private static boolean isPartMultipartSigned(Part part) { if (!isSameMimeType(part.getMimeType(), MULTIPART_SIGNED)) { return false; } if (! (part.getBody() instanceof MimeMultipart)) { return false; } MimeMultipart mimeMultipart = (MimeMultipart) part.getBody(); if (mimeMultipart.getCount() != 2) { return false; } String protocolParameter = MimeUtility.getHeaderParameter(part.getContentType(), PROTOCOL_PARAMETER); // for partially downloaded messages the protocol parameter isn't yet available, so we'll just assume it's ok boolean dataUnavailable = protocolParameter == null && mimeMultipart.getBodyPart(0).getBody() == null; boolean protocolMatches = isSameMimeType(protocolParameter, mimeMultipart.getBodyPart(1).getMimeType()); return dataUnavailable || protocolMatches; }
@Override @WorkerThread public void writeTo(OutputStream os) throws IOException { try { Part part = currentCryptoPart.part; CryptoPartType cryptoPartType = currentCryptoPart.type; if (cryptoPartType == CryptoPartType.PGP_ENCRYPTED) { Multipart multipartEncryptedMultipart = (Multipart) part.getBody(); BodyPart encryptionPayloadPart = multipartEncryptedMultipart.getBodyPart(1); Body encryptionPayloadBody = encryptionPayloadPart.getBody(); encryptionPayloadBody.writeTo(os); } else if (cryptoPartType == CryptoPartType.PGP_INLINE) { String text = MessageExtractor.getTextFromPart(part); os.write(text.getBytes()); } else { throw new IllegalStateException("part to stream must be encrypted or inline!"); } } catch (MessagingException e) { Timber.e(e, "MessagingException while writing message to crypto provider"); } } };
@Test public void migrateHtmlWithRelatedMessage() throws Exception { SQLiteDatabase db = createV50Database(); insertHtmlWithRelatedMessage(db); db.close(); LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account); LocalMessage msg = localStore.getFolder("dev").getMessage("10"); FetchProfile fp = new FetchProfile(); fp.add(FetchProfile.Item.BODY); localStore.getFolder("dev").fetch(Collections.singletonList(msg), fp, null); Assert.assertEquals(9, msg.getDatabaseId()); Assert.assertEquals(11, msg.getHeaderNames().size()); Assert.assertEquals("multipart/mixed", msg.getMimeType()); Assert.assertEquals(1, msg.getAttachmentCount()); Multipart msgBody = (Multipart) msg.getBody(); Assert.assertEquals("------------050707070308090509030605", msgBody.getBoundary()); Multipart multipartAlternativePart = (Multipart) msgBody.getBodyPart(0).getBody(); BodyPart htmlPart = multipartAlternativePart.getBodyPart(1); String msgTextContent = MessageExtractor.getTextFromPart(htmlPart); Assert.assertNotNull(msgTextContent); Assert.assertTrue(msgTextContent.contains("cid:part1.07090108.09020601@example.org")); Assert.assertEquals("image/jpeg", msgBody.getBodyPart(1).getMimeType()); }
Assert.assertEquals(3, body.getCount()); Assert.assertEquals("multipart/alternative", body.getBodyPart(0).getMimeType()); LocalBodyPart attachmentPart = (LocalBodyPart) body.getBodyPart(1); Assert.assertEquals("image/png", attachmentPart.getMimeType()); Assert.assertEquals(MimeUtil.ENC_BINARY, attachmentBody.getEncoding()); Assert.assertEquals("application/whatevs", body.getBodyPart(2).getMimeType()); Assert.assertNull(body.getBodyPart(2).getBody());