MimeMessage.java revision b3f7dd0169a35221184b9327c8ce337b09dc6d1f
196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/* 296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * you may not use this file except in compliance with the License. 696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * You may obtain a copy of the License at 796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 1096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * See the License for the specific language governing permissions and 1496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * limitations under the License. 1596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 1696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 1796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectpackage com.android.email.mail.internet; 1896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 19d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadlerimport com.android.email.mail.Address; 20d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadlerimport com.android.email.mail.Body; 21d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadlerimport com.android.email.mail.BodyPart; 22d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadlerimport com.android.email.mail.Message; 23d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadlerimport com.android.email.mail.MessagingException; 24d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadlerimport com.android.email.mail.Part; 25d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler 26d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadlerimport org.apache.james.mime4j.BodyDescriptor; 27d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadlerimport org.apache.james.mime4j.ContentHandler; 28d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadlerimport org.apache.james.mime4j.EOLConvertingInputStream; 29d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadlerimport org.apache.james.mime4j.MimeStreamParser; 30d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadlerimport org.apache.james.mime4j.field.DateTimeField; 31d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadlerimport org.apache.james.mime4j.field.Field; 32d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler 33a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaokaimport android.text.TextUtils; 34a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka 3596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.io.BufferedWriter; 3696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.io.IOException; 3796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.io.InputStream; 3896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.io.OutputStream; 3996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.io.OutputStreamWriter; 4096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.text.SimpleDateFormat; 4196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.util.Date; 4296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.util.Locale; 4396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.util.Stack; 443469902379242c723b871d1dcb09b02d0998d538The Android Open Source Projectimport java.util.regex.Pattern; 4596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 4696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/** 47dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler * An implementation of Message that stores all of its metadata in RFC 822 and 4896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * RFC 2045 style headers. 49dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler * 50dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler * NOTE: Automatic generation of a local message-id is becoming unwieldy and should be removed. 51dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler * It would be better to simply do it explicitly on local creation of new outgoing messages. 5296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 5396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectpublic class MimeMessage extends Message { 5444552da606048720de11f89321dc767ef291c391Andrew Stadler private MimeHeader mHeader; 5544552da606048720de11f89321dc767ef291c391Andrew Stadler private MimeHeader mExtendedHeader; 563469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 573469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project // NOTE: The fields here are transcribed out of headers, and values stored here will supercede 583469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project // the values found in the headers. Use caution to prevent any out-of-phase errors. In 593469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project // particular, any adds/changes/deletes here must be echoed by changes in the parse() function. 6044552da606048720de11f89321dc767ef291c391Andrew Stadler private Address[] mFrom; 6144552da606048720de11f89321dc767ef291c391Andrew Stadler private Address[] mTo; 6244552da606048720de11f89321dc767ef291c391Andrew Stadler private Address[] mCc; 6344552da606048720de11f89321dc767ef291c391Andrew Stadler private Address[] mBcc; 6444552da606048720de11f89321dc767ef291c391Andrew Stadler private Address[] mReplyTo; 6544552da606048720de11f89321dc767ef291c391Andrew Stadler private Date mSentDate; 6644552da606048720de11f89321dc767ef291c391Andrew Stadler private Body mBody; 6744552da606048720de11f89321dc767ef291c391Andrew Stadler protected int mSize; 68dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler private boolean mInhibitLocalMessageId = false; 6944552da606048720de11f89321dc767ef291c391Andrew Stadler 7044552da606048720de11f89321dc767ef291c391Andrew Stadler // Shared random source for generating local message-id values 71b3f7dd0169a35221184b9327c8ce337b09dc6d1fMakoto Onuki private static final java.util.Random sRandom = new java.util.Random(); 723469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 7396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // In MIME, en_US-like date format should be used. In other words "MMM" should be encoded to 7496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // "Jan", not the other localized format like "Ene" (meaning January in locale es). 7596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // This conversion is used when generating outgoing MIME messages. Incoming MIME date 7696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // headers are parsed by org.apache.james.mime4j.field.DateTimeField which does not have any 7796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // localization code. 7844552da606048720de11f89321dc767ef291c391Andrew Stadler private static final SimpleDateFormat DATE_FORMAT = 7996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US); 8096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 813469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project // regex that matches content id surrounded by "<>" optionally. 823469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project private static final Pattern REMOVE_OPTIONAL_BRACKETS = Pattern.compile("^<?([^>]+)>?$"); 83a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka // regex that matches end of line. 84a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka private static final Pattern END_OF_LINE = Pattern.compile("\r?\n"); 853469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 8696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public MimeMessage() { 8744552da606048720de11f89321dc767ef291c391Andrew Stadler mHeader = null; 8896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 8996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 9044552da606048720de11f89321dc767ef291c391Andrew Stadler /** 9144552da606048720de11f89321dc767ef291c391Andrew Stadler * Generate a local message id. This is only used when none has been assigned, and is 9244552da606048720de11f89321dc767ef291c391Andrew Stadler * installed lazily. Any remote (typically server-assigned) message id takes precedence. 9344552da606048720de11f89321dc767ef291c391Andrew Stadler * @return a long, locally-generated message-ID value 9444552da606048720de11f89321dc767ef291c391Andrew Stadler */ 9596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private String generateMessageId() { 9696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project StringBuffer sb = new StringBuffer(); 9796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project sb.append("<"); 9896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project for (int i = 0; i < 24; i++) { 9944552da606048720de11f89321dc767ef291c391Andrew Stadler // We'll use a 5-bit range (0..31) 10044552da606048720de11f89321dc767ef291c391Andrew Stadler int value = sRandom.nextInt() & 31; 10144552da606048720de11f89321dc767ef291c391Andrew Stadler char c = "0123456789abcdefghijklmnopqrstuv".charAt(value); 10244552da606048720de11f89321dc767ef291c391Andrew Stadler sb.append(c); 10396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 10496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project sb.append("."); 10596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project sb.append(Long.toString(System.currentTimeMillis())); 10696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project sb.append("@email.android.com>"); 10796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return sb.toString(); 10896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 10996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 11096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 11196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Parse the given InputStream using Apache Mime4J to build a MimeMessage. 11296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 11396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @param in 11496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @throws IOException 11596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @throws MessagingException 11696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 11796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public MimeMessage(InputStream in) throws IOException, MessagingException { 11896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project parse(in); 11996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 12096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 12196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project protected void parse(InputStream in) throws IOException, MessagingException { 1223469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project // Before parsing the input stream, clear all local fields that may be superceded by 1233469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project // the new incoming message. 12444552da606048720de11f89321dc767ef291c391Andrew Stadler getMimeHeaders().clear(); 125dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler mInhibitLocalMessageId = true; 12696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mFrom = null; 1273469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project mTo = null; 1283469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project mCc = null; 1293469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project mBcc = null; 1303469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project mReplyTo = null; 13196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mSentDate = null; 1323469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project mBody = null; 13396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 13496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project MimeStreamParser parser = new MimeStreamParser(); 13596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project parser.setContentHandler(new MimeMessageBuilder()); 13696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project parser.parse(new EOLConvertingInputStream(in)); 13796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 13896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 13944552da606048720de11f89321dc767ef291c391Andrew Stadler /** 14044552da606048720de11f89321dc767ef291c391Andrew Stadler * Return the internal mHeader value, with very lazy initialization. 14144552da606048720de11f89321dc767ef291c391Andrew Stadler * The goal is to save memory by not creating the headers until needed. 14244552da606048720de11f89321dc767ef291c391Andrew Stadler */ 14344552da606048720de11f89321dc767ef291c391Andrew Stadler private MimeHeader getMimeHeaders() { 14444552da606048720de11f89321dc767ef291c391Andrew Stadler if (mHeader == null) { 14544552da606048720de11f89321dc767ef291c391Andrew Stadler mHeader = new MimeHeader(); 14644552da606048720de11f89321dc767ef291c391Andrew Stadler } 14744552da606048720de11f89321dc767ef291c391Andrew Stadler return mHeader; 14844552da606048720de11f89321dc767ef291c391Andrew Stadler } 14944552da606048720de11f89321dc767ef291c391Andrew Stadler 150165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 15196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public Date getReceivedDate() throws MessagingException { 15296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return null; 15396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 15496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 155165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 15696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public Date getSentDate() throws MessagingException { 15796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (mSentDate == null) { 15896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project try { 15996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project DateTimeField field = (DateTimeField)Field.parse("Date: " 16096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project + MimeUtility.unfoldAndDecode(getFirstHeader("Date"))); 16196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mSentDate = field.getDate(); 16296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } catch (Exception e) { 16396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 16496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 16596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 16696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return mSentDate; 16796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 16896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 169165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 17096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void setSentDate(Date sentDate) throws MessagingException { 17144552da606048720de11f89321dc767ef291c391Andrew Stadler setHeader("Date", DATE_FORMAT.format(sentDate)); 17296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project this.mSentDate = sentDate; 17396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 17496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 175165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 17696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public String getContentType() throws MessagingException { 17796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String contentType = getFirstHeader(MimeHeader.HEADER_CONTENT_TYPE); 17896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (contentType == null) { 17996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return "text/plain"; 18096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else { 18196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return contentType; 18296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 18396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 18496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 18596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public String getDisposition() throws MessagingException { 18696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String contentDisposition = getFirstHeader(MimeHeader.HEADER_CONTENT_DISPOSITION); 18796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (contentDisposition == null) { 18896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return null; 18996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else { 19096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return contentDisposition; 19196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 19296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 19396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 1943469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project public String getContentId() throws MessagingException { 1953469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project String contentId = getFirstHeader(MimeHeader.HEADER_CONTENT_ID); 1963469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project if (contentId == null) { 1973469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project return null; 1983469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project } else { 1993469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project // remove optionally surrounding brackets. 2003469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project return REMOVE_OPTIONAL_BRACKETS.matcher(contentId).replaceAll("$1"); 2013469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project } 2023469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project } 2033469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 20496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public String getMimeType() throws MessagingException { 20596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return MimeUtility.getHeaderParameter(getContentType(), null); 20696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 20796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 20896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public int getSize() throws MessagingException { 20996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return mSize; 21096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 21196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 21296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 21396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Returns a list of the given recipient type from this message. If no addresses are 21496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * found the method returns an empty array. 21596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 216165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 21796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public Address[] getRecipients(RecipientType type) throws MessagingException { 21896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (type == RecipientType.TO) { 21996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (mTo == null) { 22096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mTo = Address.parse(MimeUtility.unfold(getFirstHeader("To"))); 22196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 22296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return mTo; 22396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else if (type == RecipientType.CC) { 22496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (mCc == null) { 22596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mCc = Address.parse(MimeUtility.unfold(getFirstHeader("CC"))); 22696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 22796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return mCc; 22896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else if (type == RecipientType.BCC) { 22996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (mBcc == null) { 23096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mBcc = Address.parse(MimeUtility.unfold(getFirstHeader("BCC"))); 23196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 23296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return mBcc; 23396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else { 23496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project throw new MessagingException("Unrecognized recipient type."); 23596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 23696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 23796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 238165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 23996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void setRecipients(RecipientType type, Address[] addresses) throws MessagingException { 240d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler final int TO_LENGTH = 4; // "To: " 241d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler final int CC_LENGTH = 4; // "Cc: " 242d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler final int BCC_LENGTH = 5; // "Bcc: " 24396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (type == RecipientType.TO) { 24496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (addresses == null || addresses.length == 0) { 24596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project removeHeader("To"); 24696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project this.mTo = null; 24796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else { 248d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler setHeader("To", MimeUtility.fold(Address.toHeader(addresses), TO_LENGTH)); 24996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project this.mTo = addresses; 25096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 25196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else if (type == RecipientType.CC) { 25296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (addresses == null || addresses.length == 0) { 25396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project removeHeader("CC"); 25496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project this.mCc = null; 25596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else { 256d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler setHeader("CC", MimeUtility.fold(Address.toHeader(addresses), CC_LENGTH)); 25796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project this.mCc = addresses; 25896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 25996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else if (type == RecipientType.BCC) { 26096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (addresses == null || addresses.length == 0) { 26196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project removeHeader("BCC"); 26296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project this.mBcc = null; 26396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else { 264d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler setHeader("BCC", MimeUtility.fold(Address.toHeader(addresses), BCC_LENGTH)); 26596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project this.mBcc = addresses; 26696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 26796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else { 26896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project throw new MessagingException("Unrecognized recipient type."); 26996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 27096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 27196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 27296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 27396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Returns the unfolded, decoded value of the Subject header. 27496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 275165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 27696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public String getSubject() throws MessagingException { 27796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return MimeUtility.unfoldAndDecode(getFirstHeader("Subject")); 27896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 27996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 280165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 28196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void setSubject(String subject) throws MessagingException { 2827dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler final int HEADER_NAME_LENGTH = 9; // "Subject: " 2837dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler setHeader("Subject", MimeUtility.foldAndEncode2(subject, HEADER_NAME_LENGTH)); 28496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 28596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 286165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 28796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public Address[] getFrom() throws MessagingException { 28896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (mFrom == null) { 28996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String list = MimeUtility.unfold(getFirstHeader("From")); 29096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (list == null || list.length() == 0) { 29196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project list = MimeUtility.unfold(getFirstHeader("Sender")); 29296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 29396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mFrom = Address.parse(list); 29496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 29596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return mFrom; 29696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 29796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 298165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 29996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void setFrom(Address from) throws MessagingException { 300d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler final int FROM_LENGTH = 6; // "From: " 30196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (from != null) { 302d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler setHeader("From", MimeUtility.fold(from.toHeader(), FROM_LENGTH)); 30396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project this.mFrom = new Address[] { 30496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project from 30596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project }; 30696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else { 30796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project this.mFrom = null; 30896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 30996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 31096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 311165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 31296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public Address[] getReplyTo() throws MessagingException { 31396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (mReplyTo == null) { 31496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mReplyTo = Address.parse(MimeUtility.unfold(getFirstHeader("Reply-to"))); 31596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 31696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return mReplyTo; 31796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 31896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 319165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 32096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void setReplyTo(Address[] replyTo) throws MessagingException { 321d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler final int REPLY_TO_LENGTH = 10; // "Reply-to: " 32296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (replyTo == null || replyTo.length == 0) { 32396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project removeHeader("Reply-to"); 32496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mReplyTo = null; 32596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else { 326d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler setHeader("Reply-to", MimeUtility.fold(Address.toHeader(replyTo), REPLY_TO_LENGTH)); 32796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mReplyTo = replyTo; 32896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 32996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 3303b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project 3313b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project /** 3323b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project * Set the mime "Message-ID" header 3333b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project * @param messageId the new Message-ID value 3343b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project * @throws MessagingException 3353b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project */ 33644552da606048720de11f89321dc767ef291c391Andrew Stadler @Override 3373b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project public void setMessageId(String messageId) throws MessagingException { 3383b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project setHeader("Message-ID", messageId); 3393b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project } 3403b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project 3413b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project /** 34244552da606048720de11f89321dc767ef291c391Andrew Stadler * Get the mime "Message-ID" header. This value will be preloaded with a locally-generated 343dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler * random ID, if the value has not previously been set. Local generation can be inhibited/ 344dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler * overridden by explicitly clearing the headers, removing the message-id header, etc. 345dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler * @return the Message-ID header string, or null if explicitly has been set to null 3463b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project */ 34744552da606048720de11f89321dc767ef291c391Andrew Stadler @Override 3483b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project public String getMessageId() throws MessagingException { 34944552da606048720de11f89321dc767ef291c391Andrew Stadler String messageId = getFirstHeader("Message-ID"); 350dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler if (messageId == null && !mInhibitLocalMessageId) { 35144552da606048720de11f89321dc767ef291c391Andrew Stadler messageId = generateMessageId(); 35244552da606048720de11f89321dc767ef291c391Andrew Stadler setMessageId(messageId); 3533b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project } 35444552da606048720de11f89321dc767ef291c391Andrew Stadler return messageId; 3553b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project } 35696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 357165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 35896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void saveChanges() throws MessagingException { 35996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project throw new MessagingException("saveChanges not yet implemented"); 36096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 36196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 362165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 36396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public Body getBody() throws MessagingException { 36496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return mBody; 36596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 36696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 367165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 36896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void setBody(Body body) throws MessagingException { 36996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project this.mBody = body; 37096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (body instanceof com.android.email.mail.Multipart) { 37196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project com.android.email.mail.Multipart multipart = ((com.android.email.mail.Multipart)body); 37296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project multipart.setParent(this); 37396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project setHeader(MimeHeader.HEADER_CONTENT_TYPE, multipart.getContentType()); 37496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project setHeader("MIME-Version", "1.0"); 37596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 37696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project else if (body instanceof TextBody) { 37796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project setHeader(MimeHeader.HEADER_CONTENT_TYPE, String.format("%s;\n charset=utf-8", 37896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project getMimeType())); 37996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64"); 38096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 38196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 38296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 38396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project protected String getFirstHeader(String name) throws MessagingException { 38444552da606048720de11f89321dc767ef291c391Andrew Stadler return getMimeHeaders().getFirstHeader(name); 38596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 38696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 387165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 38896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void addHeader(String name, String value) throws MessagingException { 38944552da606048720de11f89321dc767ef291c391Andrew Stadler getMimeHeaders().addHeader(name, value); 39096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 39196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 392165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 39396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void setHeader(String name, String value) throws MessagingException { 39444552da606048720de11f89321dc767ef291c391Andrew Stadler getMimeHeaders().setHeader(name, value); 39596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 39696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 397165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 39896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public String[] getHeader(String name) throws MessagingException { 39944552da606048720de11f89321dc767ef291c391Andrew Stadler return getMimeHeaders().getHeader(name); 40096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 40196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 402165e8bfe7a46564ea98bb16cb059102ba356a1b5Makoto Onuki @Override 40396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void removeHeader(String name) throws MessagingException { 40444552da606048720de11f89321dc767ef291c391Andrew Stadler getMimeHeaders().removeHeader(name); 405dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler if ("Message-ID".equalsIgnoreCase(name)) { 406dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler mInhibitLocalMessageId = true; 407dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler } 40896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 40996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 410a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka /** 411a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * Set extended header 412a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * 413a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * @param name Extended header name 414a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * @param value header value - flattened by removing CR-NL if any 415a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * remove header if value is null 416a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * @throws MessagingException 417a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka */ 418a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka public void setExtendedHeader(String name, String value) throws MessagingException { 419a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka if (value == null) { 420a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka if (mExtendedHeader != null) { 421a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka mExtendedHeader.removeHeader(name); 422a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 423a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka return; 424a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 425a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka if (mExtendedHeader == null) { 426a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka mExtendedHeader = new MimeHeader(); 427a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 428a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka mExtendedHeader.setHeader(name, END_OF_LINE.matcher(value).replaceAll("")); 429a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 430a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka 431a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka /** 432a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * Get extended header 433a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * 434a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * @param name Extended header name 435a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * @return header value - null if header does not exist 436a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * @throws MessagingException 437a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka */ 438a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka public String getExtendedHeader(String name) throws MessagingException { 439a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka if (mExtendedHeader == null) { 440a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka return null; 441a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 442a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka return mExtendedHeader.getFirstHeader(name); 443a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 444a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka 445a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka /** 446a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * Set entire extended headers from String 447a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * 448a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * @param headers Extended header and its value - "CR-NL-separated pairs 449a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * if null or empty, remove entire extended headers 450a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * @throws MessagingException 451a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka */ 452a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka public void setExtendedHeaders(String headers) throws MessagingException { 453a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka if (TextUtils.isEmpty(headers)) { 454a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka mExtendedHeader = null; 455a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } else { 456a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka mExtendedHeader = new MimeHeader(); 457a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka for (String header : END_OF_LINE.split(headers)) { 458a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka String[] tokens = header.split(":", 2); 459a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka if (tokens.length != 2) { 460a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka throw new MessagingException("Illegal extended headers: " + headers); 461a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 462a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka mExtendedHeader.setHeader(tokens[0].trim(), tokens[1].trim()); 463a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 464a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 465a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 466a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka 467a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka /** 468a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * Get entire extended headers as String 469a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * 470a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * @return "CR-NL-separated extended headers - null if extended header does not exist 471a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka */ 472a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka public String getExtendedHeaders() { 473a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka if (mExtendedHeader != null) { 474a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka return mExtendedHeader.writeToString(); 475a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 476a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka return null; 477a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 478a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka 479a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka /** 480a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * Write message header and body to output stream 481a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * 482a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * @param out Output steam to write message header and body. 483a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka */ 48496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void writeTo(OutputStream out) throws IOException, MessagingException { 48596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024); 48644552da606048720de11f89321dc767ef291c391Andrew Stadler // Force creation of local message-id 48744552da606048720de11f89321dc767ef291c391Andrew Stadler getMessageId(); 48844552da606048720de11f89321dc767ef291c391Andrew Stadler getMimeHeaders().writeTo(out); 489a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka // mExtendedHeader will not be write out to external output stream, 490a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka // because it is intended to internal use. 49196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project writer.write("\r\n"); 49296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project writer.flush(); 49396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (mBody != null) { 49496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mBody.writeTo(out); 49596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 49696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 49796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 49896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public InputStream getInputStream() throws MessagingException { 49996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return null; 50096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 50196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 50296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project class MimeMessageBuilder implements ContentHandler { 50396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private Stack stack = new Stack(); 50496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 50596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public MimeMessageBuilder() { 50696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 50796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 50896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private void expect(Class c) { 50996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (!c.isInstance(stack.peek())) { 51096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project throw new IllegalStateException("Internal stack error: " + "Expected '" 51196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project + c.getName() + "' found '" + stack.peek().getClass().getName() + "'"); 51296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 51396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 51496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 51596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void startMessage() { 51696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (stack.isEmpty()) { 51796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project stack.push(MimeMessage.this); 51896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else { 51996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project expect(Part.class); 52096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project try { 52196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project MimeMessage m = new MimeMessage(); 52296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project ((Part)stack.peek()).setBody(m); 52396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project stack.push(m); 52496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } catch (MessagingException me) { 52596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project throw new Error(me); 52696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 52796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 52896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 52996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 53096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void endMessage() { 53196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project expect(MimeMessage.class); 53296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project stack.pop(); 53396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 53496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 53596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void startHeader() { 53696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project expect(Part.class); 53796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 53896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 53996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void field(String fieldData) { 54096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project expect(Part.class); 54196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project try { 54296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String[] tokens = fieldData.split(":", 2); 54396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project ((Part)stack.peek()).addHeader(tokens[0], tokens[1].trim()); 54496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } catch (MessagingException me) { 54596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project throw new Error(me); 54696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 54796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 54896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 54996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void endHeader() { 55096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project expect(Part.class); 55196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 55296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 55396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void startMultipart(BodyDescriptor bd) { 55496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project expect(Part.class); 55596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 55696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Part e = (Part)stack.peek(); 55796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project try { 55896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project MimeMultipart multiPart = new MimeMultipart(e.getContentType()); 55996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project e.setBody(multiPart); 56096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project stack.push(multiPart); 56196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } catch (MessagingException me) { 56296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project throw new Error(me); 56396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 56496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 56596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 56696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void body(BodyDescriptor bd, InputStream in) throws IOException { 56796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project expect(Part.class); 56896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Body body = MimeUtility.decodeBody(in, bd.getTransferEncoding()); 56996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project try { 57096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project ((Part)stack.peek()).setBody(body); 57196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } catch (MessagingException me) { 57296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project throw new Error(me); 57396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 57496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 57596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 57696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void endMultipart() { 57796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project stack.pop(); 57896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 57996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 58096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void startBodyPart() { 58196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project expect(MimeMultipart.class); 58296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 58396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project try { 58496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project MimeBodyPart bodyPart = new MimeBodyPart(); 58596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project ((MimeMultipart)stack.peek()).addBodyPart(bodyPart); 58696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project stack.push(bodyPart); 58796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } catch (MessagingException me) { 58896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project throw new Error(me); 58996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 59096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 59196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 59296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void endBodyPart() { 59396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project expect(BodyPart.class); 59496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project stack.pop(); 59596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 59696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 59796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void epilogue(InputStream is) throws IOException { 59896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project expect(MimeMultipart.class); 59996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project StringBuffer sb = new StringBuffer(); 60096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project int b; 60196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project while ((b = is.read()) != -1) { 60296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project sb.append((char)b); 60396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 60496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // ((Multipart) stack.peek()).setEpilogue(sb.toString()); 60596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 60696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 60796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void preamble(InputStream is) throws IOException { 60896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project expect(MimeMultipart.class); 60996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project StringBuffer sb = new StringBuffer(); 61096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project int b; 61196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project while ((b = is.read()) != -1) { 61296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project sb.append((char)b); 61396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 61496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project try { 61596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project ((MimeMultipart)stack.peek()).setPreamble(sb.toString()); 61696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } catch (MessagingException me) { 61796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project throw new Error(me); 61896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 61996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 62096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 62196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void raw(InputStream is) throws IOException { 62296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project throw new UnsupportedOperationException("Not supported"); 62396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 62496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 62596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project} 626