13f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen/* 23f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * Copyright (C) 2015 The Android Open Source Project 33f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * 43f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * Licensed under the Apache License, Version 2.0 (the "License"); 53f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * you may not use this file except in compliance with the License. 63f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * You may obtain a copy of the License at 73f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * 83f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * http://www.apache.org/licenses/LICENSE-2.0 93f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * 103f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * Unless required by applicable law or agreed to in writing, software 113f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * distributed under the License is distributed on an "AS IS" BASIS, 123f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * See the License for the specific language governing permissions and 143f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * limitations under the License. 153f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen */ 163f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenpackage com.android.phone.common.mail.internet; 173f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 183f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport com.android.phone.common.mail.Body; 193f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport com.android.phone.common.mail.BodyPart; 203f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport com.android.phone.common.mail.MessagingException; 213f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 223f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport java.io.BufferedWriter; 233f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport java.io.IOException; 243f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport java.io.OutputStream; 253f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport java.io.OutputStreamWriter; 263f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenimport java.util.regex.Pattern; 273f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 283f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen/** 293f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * TODO this is a close approximation of Message, need to update along with 303f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * Message. 313f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen */ 323f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chenpublic class MimeBodyPart extends BodyPart { 333f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen protected MimeHeader mHeader = new MimeHeader(); 343f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen protected MimeHeader mExtendedHeader; 353f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen protected Body mBody; 363f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen protected int mSize; 373f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 383f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen // regex that matches content id surrounded by "<>" optionally. 393f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen private static final Pattern REMOVE_OPTIONAL_BRACKETS = Pattern.compile("^<?([^>]+)>?$"); 403f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen // regex that matches end of line. 413f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen private static final Pattern END_OF_LINE = Pattern.compile("\r?\n"); 423f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 433f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public MimeBodyPart() throws MessagingException { 443f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen this(null); 453f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 463f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 473f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public MimeBodyPart(Body body) throws MessagingException { 483f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen this(body, null); 493f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 503f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 513f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public MimeBodyPart(Body body, String mimeType) throws MessagingException { 523f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen if (mimeType != null) { 533f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen setHeader(MimeHeader.HEADER_CONTENT_TYPE, mimeType); 543f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 553f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen setBody(body); 563f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 573f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 583f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen protected String getFirstHeader(String name) throws MessagingException { 593f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen return mHeader.getFirstHeader(name); 603f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 613f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 623f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen @Override 633f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public void addHeader(String name, String value) throws MessagingException { 643f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen mHeader.addHeader(name, value); 653f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 663f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 673f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen @Override 683f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public void setHeader(String name, String value) throws MessagingException { 693f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen mHeader.setHeader(name, value); 703f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 713f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 723f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen @Override 733f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public String[] getHeader(String name) throws MessagingException { 743f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen return mHeader.getHeader(name); 753f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 763f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 773f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen @Override 783f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public void removeHeader(String name) throws MessagingException { 793f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen mHeader.removeHeader(name); 803f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 813f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 823f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen @Override 833f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public Body getBody() throws MessagingException { 843f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen return mBody; 853f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 863f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 873f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen @Override 883f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public void setBody(Body body) throws MessagingException { 893f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen this.mBody = body; 903f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen if (body instanceof com.android.phone.common.mail.Multipart) { 913f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen com.android.phone.common.mail.Multipart multipart = 923f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen ((com.android.phone.common.mail.Multipart)body); 933f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen multipart.setParent(this); 943f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen setHeader(MimeHeader.HEADER_CONTENT_TYPE, multipart.getContentType()); 953f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 963f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen else if (body instanceof TextBody) { 973f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen String contentType = String.format("%s;\n charset=utf-8", getMimeType()); 983f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen String name = MimeUtility.getHeaderParameter(getContentType(), "name"); 993f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen if (name != null) { 1003f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen contentType += String.format(";\n name=\"%s\"", name); 1013f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1023f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen setHeader(MimeHeader.HEADER_CONTENT_TYPE, contentType); 1033f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64"); 1043f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1053f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1063f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 1073f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen @Override 1083f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public String getContentType() throws MessagingException { 1093f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen String contentType = getFirstHeader(MimeHeader.HEADER_CONTENT_TYPE); 1103f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen if (contentType == null) { 1113f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen return "text/plain"; 1123f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } else { 1133f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen return contentType; 1143f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1153f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1163f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 1173f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen @Override 1183f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public String getDisposition() throws MessagingException { 1193f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen String contentDisposition = getFirstHeader(MimeHeader.HEADER_CONTENT_DISPOSITION); 1203f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen if (contentDisposition == null) { 1213f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen return null; 1223f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } else { 1233f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen return contentDisposition; 1243f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1253f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1263f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 1273f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen @Override 1283f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public String getContentId() throws MessagingException { 1293f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen String contentId = getFirstHeader(MimeHeader.HEADER_CONTENT_ID); 1303f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen if (contentId == null) { 1313f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen return null; 1323f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } else { 1333f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen // remove optionally surrounding brackets. 1343f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen return REMOVE_OPTIONAL_BRACKETS.matcher(contentId).replaceAll("$1"); 1353f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1363f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1373f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 1383f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen @Override 1393f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public String getMimeType() throws MessagingException { 1403f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen return MimeUtility.getHeaderParameter(getContentType(), null); 1413f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1423f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 1433f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen @Override 1443f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public boolean isMimeType(String mimeType) throws MessagingException { 1453f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen return getMimeType().equals(mimeType); 1463f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1473f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 1483f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public void setSize(int size) { 1493f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen this.mSize = size; 1503f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1513f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 1523f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen @Override 1533f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public int getSize() throws MessagingException { 1543f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen return mSize; 1553f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1563f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 1573f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen /** 1583f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * Set extended header 1593f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * 1603f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * @param name Extended header name 1613f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * @param value header value - flattened by removing CR-NL if any 1623f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * remove header if value is null 1633f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * @throws MessagingException 1643f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen */ 1653f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen @Override 1663f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public void setExtendedHeader(String name, String value) throws MessagingException { 1673f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen if (value == null) { 1683f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen if (mExtendedHeader != null) { 1693f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen mExtendedHeader.removeHeader(name); 1703f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1713f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen return; 1723f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1733f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen if (mExtendedHeader == null) { 1743f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen mExtendedHeader = new MimeHeader(); 1753f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1763f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen mExtendedHeader.setHeader(name, END_OF_LINE.matcher(value).replaceAll("")); 1773f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1783f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 1793f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen /** 1803f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * Get extended header 1813f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * 1823f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * @param name Extended header name 1833f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * @return header value - null if header does not exist 1843f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * @throws MessagingException 1853f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen */ 1863f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen @Override 1873f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public String getExtendedHeader(String name) throws MessagingException { 1883f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen if (mExtendedHeader == null) { 1893f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen return null; 1903f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1913f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen return mExtendedHeader.getFirstHeader(name); 1923f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 1933f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen 1943f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen /** 1953f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen * Write the MimeMessage out in MIME format. 1963f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen */ 1973f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen @Override 1983f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen public void writeTo(OutputStream out) throws IOException, MessagingException { 1993f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024); 2003f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen mHeader.writeTo(out); 2013f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen writer.write("\r\n"); 2023f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen writer.flush(); 2033f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen if (mBody != null) { 2043f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen mBody.writeTo(out); 2053f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 2063f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen } 2073f51d09afa61649a1bcf02599bc1df5aafccf088Nancy Chen} 208