Home | History | Annotate | Download | only in mail
      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.email.mail;
     18 
     19 import com.android.email.mail.internet.BinaryTempFileBody;
     20 import com.android.email.mail.internet.MimeBodyPart;
     21 import com.android.email.mail.internet.MimeHeader;
     22 import com.android.email.mail.internet.MimeMessage;
     23 import com.android.email.mail.internet.MimeMultipart;
     24 import com.android.email.mail.internet.TextBody;
     25 import com.android.email.mail.store.LocalStore;
     26 import com.android.email.provider.AttachmentProvider;
     27 import com.android.email.provider.EmailContent;
     28 
     29 import android.net.Uri;
     30 
     31 import java.io.IOException;
     32 import java.util.ArrayList;
     33 
     34 /**
     35  * Utility class makes it easier for developer to build mail message objects.
     36  * <p>
     37  * Typical usage of these helper functions and builder objects are as follows.
     38  * <p>
     39  * <pre>
     40  * String text2 = new TextBuilder("<html>").text("<head></head>")
     41  *     .text("<body>").cidImg("contetid@domain").text("</body>").build("</html");
     42  * String text2 = new TextBuilder("<html>").text("<head></head>")
     43  *     .text("<body>").uriImg(contentUri).text("</body>").build("</html");
     44  * Message msg = new MessageBuilder()
     45  *     .setBody(new MultipartBuilder("multipart/mixed")
     46  *         .addBodyPart(MessageTestUtils.imagePart("image/jpeg", null, 30, store))
     47  *         .addBodyPart(MessageTestUtils.imagePart("application/pdf", cid1, aid1, store))
     48  *         .addBodyPart(new MultipartBuilder("multipart/related")
     49  *             .addBodyPart(MessageTestUtils.textPart("text/html", text2 + text1))
     50  *             .addBodyPart(MessageTestUtils.imagePart("image/jpg", cid1, aid1, store))
     51  *             .addBodyPart(MessageTestUtils.imagePart("image/gif", cid2, aid2, store))
     52  *             .buildBodyPart())
     53  *         .addBodyPart(MessageTestUtils.imagePart("application/pdf", cid2, aid2, store))
     54  *         .build())
     55  *     .build();
     56  * </pre>
     57  */
     58 
     59 public class MessageTestUtils {
     60 
     61     /**
     62      * Generate AttachmentProvider content URI from attachment ID and Account.
     63      *
     64      * @param attachmentId attachment id
     65      * @param account Account object
     66      * @return AttachmentProvider content URI
     67      */
     68     public static Uri contentUri(long attachmentId, EmailContent.Account account) {
     69         return AttachmentProvider.getAttachmentUri(account.mId, attachmentId);
     70     }
     71 
     72     /**
     73      * Create simple MimeBodyPart.
     74      *
     75      * @param mimeType MIME type of body part
     76      * @param contentId content-id header value (optional - null for no header)
     77      * @return MimeBodyPart object which body is null.
     78      * @throws MessagingException
     79      */
     80     public static BodyPart bodyPart(String mimeType, String contentId) throws MessagingException {
     81         final MimeBodyPart bp = new MimeBodyPart(null, mimeType);
     82         if (contentId != null) {
     83             bp.setHeader(MimeHeader.HEADER_CONTENT_ID, contentId);
     84         }
     85         return bp;
     86     }
     87 
     88     /**
     89      * Create MimeBodyPart with TextBody.
     90      *
     91      * @param mimeType MIME type of text
     92      * @param text body text string
     93      * @return MimeBodyPart object whose body is TextBody
     94      * @throws MessagingException
     95      */
     96     public static BodyPart textPart(String mimeType, String text) throws MessagingException {
     97         final TextBody textBody = new TextBody(text);
     98         final MimeBodyPart textPart = new MimeBodyPart(textBody);
     99         textPart.setHeader(MimeHeader.HEADER_CONTENT_TYPE, mimeType);
    100         return textPart;
    101     }
    102 
    103     /**
    104      * Create attachment BodyPart with content-id.
    105      *
    106      * @param mimeType MIME type of image body
    107      * @param contentId content-id header value (optional - null for no header)
    108      * @param attachmentId attachment id of store
    109      * @param store LocalStore which stores attachment
    110      * @return LocalAttachmentBodyPart with content-id
    111      * @throws MessagingException
    112      * @throws IOException
    113      */
    114     public static BodyPart imagePart(String mimeType, String contentId,
    115             long attachmentId, LocalStore store) throws MessagingException, IOException {
    116         final BinaryTempFileBody imageBody = new BinaryTempFileBody();
    117         final LocalStore.LocalAttachmentBodyPart imagePart =
    118             store.new LocalAttachmentBodyPart(imageBody, attachmentId);
    119         imagePart.setHeader(MimeHeader.HEADER_CONTENT_TYPE, mimeType);
    120         if (contentId != null) {
    121             imagePart.setHeader(MimeHeader.HEADER_CONTENT_ID, contentId);
    122         }
    123         return imagePart;
    124     }
    125 
    126     /**
    127      * Builder class for Multipart.
    128      *
    129      * This builder object accepts any number of BodyParts and then can produce
    130      * Multipart or BodyPart which contains accepted BodyParts. Usually combined with other
    131      * builder object and helper method.
    132      */
    133     public static class MultipartBuilder {
    134         private final String mContentType;
    135         private final ArrayList<BodyPart> mParts = new ArrayList<BodyPart>();
    136 
    137         /**
    138          * Create builder object with MIME type and dummy boundary string.
    139          *
    140          * @param mimeType MIME type of this Multipart
    141          */
    142         public MultipartBuilder(String mimeType) {
    143             this(mimeType, "this_is_boundary");
    144         }
    145 
    146         /**
    147          * Create builder object with MIME type and boundary string.
    148          *
    149          * @param mimeType MIME type of this Multipart
    150          * @param boundary boundary string
    151          */
    152         public MultipartBuilder(String mimeType, String boundary) {
    153             mContentType = mimeType + "; boundary=" + boundary;
    154         }
    155 
    156         /**
    157          * Modifier method to add BodyPart to intended Multipart.
    158          *
    159          * @param bodyPart BodyPart to be added
    160          * @return builder object itself
    161          */
    162         public MultipartBuilder addBodyPart(final BodyPart bodyPart) {
    163             mParts.add(bodyPart);
    164             return this;
    165         }
    166 
    167         /**
    168          * Build method to create Multipart.
    169          *
    170          * @return intended Multipart object
    171          * @throws MessagingException
    172          */
    173         public Multipart build() throws MessagingException {
    174             final MimeMultipart mp = new MimeMultipart(mContentType);
    175             for (BodyPart p : mParts) {
    176                 mp.addBodyPart(p);
    177             }
    178             return mp;
    179         }
    180 
    181         /**
    182          * Build method to create BodyPart that contains this "Multipart"
    183          * @return BodyPart whose body is intended Multipart.
    184          * @throws MessagingException
    185          */
    186         public BodyPart buildBodyPart() throws MessagingException {
    187             final BodyPart bp = new MimeBodyPart();
    188             bp.setBody(this.build());
    189             return bp;
    190         }
    191     }
    192 
    193     /**
    194      * Builder class for Message
    195      *
    196      * This builder object accepts Body and then can produce Message object.
    197      * Usually combined with other builder object and helper method.
    198      */
    199     public static class MessageBuilder {
    200         private Body mBody;
    201 
    202         /**
    203          * Create Builder object.
    204          */
    205         public MessageBuilder() {
    206         }
    207 
    208         /**
    209          * Modifier method to set Body.
    210          *
    211          * @param body Body of intended Message
    212          * @return builder object itself
    213          */
    214         public MessageBuilder setBody(final Body body) {
    215             mBody = body;
    216             return this;
    217         }
    218 
    219         /**
    220          * Build method to create Message.
    221          *
    222          * @return intended Message object
    223          * @throws MessagingException
    224          */
    225         public Message build() throws MessagingException {
    226             final MimeMessage msg = new MimeMessage();
    227             if (mBody == null) {
    228                 throw new MessagingException("body is not specified");
    229             }
    230             msg.setBody(mBody);
    231             return msg;
    232         }
    233     }
    234 
    235     /**
    236      * Builder class for simple HTML String.
    237      * This builder object accepts some type of object or and string and then create String object.
    238      * Usually combined with other builder object and helper method.
    239      */
    240     public static class TextBuilder {
    241         final StringBuilder mBuilder = new StringBuilder();
    242 
    243         /**
    244          * Create builder with preamble string
    245          * @param preamble
    246          */
    247         public TextBuilder(String preamble) {
    248             mBuilder.append(preamble);
    249         }
    250 
    251         /**
    252          * Modifier method to add img tag that has cid: src attribute.
    253          * @param contentId content id string
    254          * @return builder object itself
    255          */
    256         public TextBuilder addCidImg(String contentId) {
    257             return addTag("img", "SRC", "cid:" + contentId);
    258         }
    259 
    260         /**
    261          * Modifier method to add img tag that has content:// src attribute.
    262          * @param contentUri content uri object
    263          * @return builder object itself
    264          */
    265         public TextBuilder addUidImg(Uri contentUri) {
    266             return addTag("img", "src", contentUri.toString());
    267         }
    268 
    269         /**
    270          * Modifier method to add tag with specified attribute and value.
    271          *
    272          * @param tag tag name
    273          * @param attribute attribute name
    274          * @param value attribute value
    275          * @return builder object itself
    276          */
    277         public TextBuilder addTag(String tag, String attribute, String value) {
    278             return addText(String.format("<%s %s=\"%s\">", tag, attribute, value));
    279         }
    280 
    281         /**
    282          * Modifier method to add simple string.
    283          * @param text string to add
    284          * @return builder object itself
    285          */
    286         public TextBuilder addText(String text) {
    287             mBuilder.append(text);
    288             return this;
    289         }
    290 
    291         /**
    292          * Build method to create intended String
    293          * @param epilogue string to add to the end
    294          * @return intended String
    295          */
    296         public String build(String epilogue) {
    297             mBuilder.append(epilogue);
    298             return mBuilder.toString();
    299         }
    300     }
    301 
    302 }
    303