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
17package com.android.emailcommon.mail;
18
19import com.android.emailcommon.internet.MimeBodyPart;
20import com.android.emailcommon.internet.MimeHeader;
21import com.android.emailcommon.internet.MimeMessage;
22import com.android.emailcommon.internet.MimeMultipart;
23import com.android.emailcommon.internet.TextBody;
24import com.android.emailcommon.provider.Account;
25import com.android.emailcommon.utility.AttachmentUtilities;
26
27import android.net.Uri;
28
29import 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
56public 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