1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.emailcommon.mail; 18 19 import com.android.emailcommon.internet.MimeBodyPart; 20 import com.android.emailcommon.internet.MimeHeader; 21 import com.android.emailcommon.internet.MimeMessage; 22 import com.android.emailcommon.internet.MimeMultipart; 23 import com.android.emailcommon.internet.TextBody; 24 import com.android.emailcommon.provider.Account; 25 import com.android.emailcommon.utility.AttachmentUtilities; 26 27 import android.net.Uri; 28 29 import java.util.ArrayList; 30 31 /** 32 * Utility class makes it easier for developer to build mail message objects. 33 * <p> 34 * Typical usage of these helper functions and builder objects are as follows. 35 * <p> 36 * <pre> 37 * String text2 = new TextBuilder("<html>").text("<head></head>") 38 * .text("<body>").cidImg("contetid@domain").text("</body>").build("</html"); 39 * String text2 = new TextBuilder("<html>").text("<head></head>") 40 * .text("<body>").uriImg(contentUri).text("</body>").build("</html"); 41 * Message msg = new MessageBuilder() 42 * .setBody(new MultipartBuilder("multipart/mixed") 43 * .addBodyPart(MessageTestUtils.imagePart("image/jpeg", null, 30, store)) 44 * .addBodyPart(MessageTestUtils.imagePart("application/pdf", cid1, aid1, store)) 45 * .addBodyPart(new MultipartBuilder("multipart/related") 46 * .addBodyPart(MessageTestUtils.textPart("text/html", text2 + text1)) 47 * .addBodyPart(MessageTestUtils.imagePart("image/jpg", cid1, aid1, store)) 48 * .addBodyPart(MessageTestUtils.imagePart("image/gif", cid2, aid2, store)) 49 * .buildBodyPart()) 50 * .addBodyPart(MessageTestUtils.imagePart("application/pdf", cid2, aid2, store)) 51 * .build()) 52 * .build(); 53 * </pre> 54 */ 55 56 public class MessageTestUtils { 57 58 /** 59 * Generate AttachmentProvider content URI from attachment ID and Account. 60 * 61 * @param attachmentId attachment id 62 * @param account Account object 63 * @return AttachmentProvider content URI 64 */ 65 public static Uri contentUri(long attachmentId, Account account) { 66 return AttachmentUtilities.getAttachmentUri(account.mId, attachmentId); 67 } 68 69 /** 70 * Create simple MimeBodyPart. 71 * 72 * @param mimeType MIME type of body part 73 * @param contentId content-id header value (optional - null for no header) 74 * @return MimeBodyPart object which body is null. 75 * @throws MessagingException 76 */ 77 public static BodyPart bodyPart(String mimeType, String contentId) throws MessagingException { 78 final MimeBodyPart bp = new MimeBodyPart(null, mimeType); 79 if (contentId != null) { 80 bp.setHeader(MimeHeader.HEADER_CONTENT_ID, contentId); 81 } 82 return bp; 83 } 84 85 /** 86 * Create MimeBodyPart with TextBody. 87 * 88 * @param mimeType MIME type of text 89 * @param text body text string 90 * @return MimeBodyPart object whose body is TextBody 91 * @throws MessagingException 92 */ 93 public static BodyPart textPart(String mimeType, String text) throws MessagingException { 94 final TextBody textBody = new TextBody(text); 95 final MimeBodyPart textPart = new MimeBodyPart(textBody); 96 textPart.setHeader(MimeHeader.HEADER_CONTENT_TYPE, mimeType); 97 return textPart; 98 } 99 100 /** 101 * Builder class for Multipart. 102 * 103 * This builder object accepts any number of BodyParts and then can produce 104 * Multipart or BodyPart which contains accepted BodyParts. Usually combined with other 105 * builder object and helper method. 106 */ 107 public static class MultipartBuilder { 108 private final String mContentType; 109 private final ArrayList<BodyPart> mParts = new ArrayList<BodyPart>(); 110 111 /** 112 * Create builder object with MIME type and dummy boundary string. 113 * 114 * @param mimeType MIME type of this Multipart 115 */ 116 public MultipartBuilder(String mimeType) { 117 this(mimeType, "this_is_boundary"); 118 } 119 120 /** 121 * Create builder object with MIME type and boundary string. 122 * 123 * @param mimeType MIME type of this Multipart 124 * @param boundary boundary string 125 */ 126 public MultipartBuilder(String mimeType, String boundary) { 127 mContentType = mimeType + "; boundary=" + boundary; 128 } 129 130 /** 131 * Modifier method to add BodyPart to intended Multipart. 132 * 133 * @param bodyPart BodyPart to be added 134 * @return builder object itself 135 */ 136 public MultipartBuilder addBodyPart(final BodyPart bodyPart) { 137 mParts.add(bodyPart); 138 return this; 139 } 140 141 /** 142 * Build method to create Multipart. 143 * 144 * @return intended Multipart object 145 * @throws MessagingException 146 */ 147 public Multipart build() throws MessagingException { 148 final MimeMultipart mp = new MimeMultipart(mContentType); 149 for (BodyPart p : mParts) { 150 mp.addBodyPart(p); 151 } 152 return mp; 153 } 154 155 /** 156 * Build method to create BodyPart that contains this "Multipart" 157 * @return BodyPart whose body is intended Multipart. 158 * @throws MessagingException 159 */ 160 public BodyPart buildBodyPart() throws MessagingException { 161 final BodyPart bp = new MimeBodyPart(); 162 bp.setBody(this.build()); 163 return bp; 164 } 165 } 166 167 /** 168 * Builder class for Message 169 * 170 * This builder object accepts Body and then can produce Message object. 171 * Usually combined with other builder object and helper method. 172 */ 173 public static class MessageBuilder { 174 private Body mBody; 175 176 /** 177 * Create Builder object. 178 */ 179 public MessageBuilder() { 180 } 181 182 /** 183 * Modifier method to set Body. 184 * 185 * @param body Body of intended Message 186 * @return builder object itself 187 */ 188 public MessageBuilder setBody(final Body body) { 189 mBody = body; 190 return this; 191 } 192 193 /** 194 * Build method to create Message. 195 * 196 * @return intended Message object 197 * @throws MessagingException 198 */ 199 public Message build() throws MessagingException { 200 final MimeMessage msg = new MimeMessage(); 201 if (mBody == null) { 202 throw new MessagingException("body is not specified"); 203 } 204 msg.setBody(mBody); 205 return msg; 206 } 207 } 208 209 /** 210 * Builder class for simple HTML String. 211 * This builder object accepts some type of object or and string and then create String object. 212 * Usually combined with other builder object and helper method. 213 */ 214 public static class TextBuilder { 215 final StringBuilder mBuilder = new StringBuilder(); 216 217 /** 218 * Create builder with preamble string 219 * @param preamble 220 */ 221 public TextBuilder(String preamble) { 222 mBuilder.append(preamble); 223 } 224 225 /** 226 * Modifier method to add img tag that has cid: src attribute. 227 * @param contentId content id string 228 * @return builder object itself 229 */ 230 public TextBuilder addCidImg(String contentId) { 231 return addTag("img", "SRC", "cid:" + contentId); 232 } 233 234 /** 235 * Modifier method to add img tag that has content:// src attribute. 236 * @param contentUri content uri object 237 * @return builder object itself 238 */ 239 public TextBuilder addUidImg(Uri contentUri) { 240 return addTag("img", "src", contentUri.toString()); 241 } 242 243 /** 244 * Modifier method to add tag with specified attribute and value. 245 * 246 * @param tag tag name 247 * @param attribute attribute name 248 * @param value attribute value 249 * @return builder object itself 250 */ 251 public TextBuilder addTag(String tag, String attribute, String value) { 252 return addText(String.format("<%s %s=\"%s\">", tag, attribute, value)); 253 } 254 255 /** 256 * Modifier method to add simple string. 257 * @param text string to add 258 * @return builder object itself 259 */ 260 public TextBuilder addText(String text) { 261 mBuilder.append(text); 262 return this; 263 } 264 265 /** 266 * Build method to create intended String 267 * @param epilogue string to add to the end 268 * @return intended String 269 */ 270 public String build(String epilogue) { 271 mBuilder.append(epilogue); 272 return mBuilder.toString(); 273 } 274 } 275 276 } 277