001 /****************************************************************
002 * Licensed to the Apache Software Foundation (ASF) under one *
003 * or more contributor license agreements. See the NOTICE file *
004 * distributed with this work for additional information *
005 * regarding copyright ownership. The ASF licenses this file *
006 * to you under the Apache License, Version 2.0 (the *
007 * "License"); you may not use this file except in compliance *
008 * with the License. You may obtain a copy of the License at *
009 * *
010 * http://www.apache.org/licenses/LICENSE-2.0 *
011 * *
012 * Unless required by applicable law or agreed to in writing, *
013 * software distributed under the License is distributed on an *
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015 * KIND, either express or implied. See the License for the *
016 * specific language governing permissions and limitations *
017 * under the License. *
018 ****************************************************************/
019
020 package org.apache.james.mime4j.samples.transform;
021
022 import java.io.ByteArrayInputStream;
023 import java.io.IOException;
024 import java.util.Date;
025 import java.util.Random;
026
027 import org.apache.james.mime4j.dom.Body;
028 import org.apache.james.mime4j.dom.Entity;
029 import org.apache.james.mime4j.dom.Message;
030 import org.apache.james.mime4j.dom.MessageBuilder;
031 import org.apache.james.mime4j.dom.MessageWriter;
032 import org.apache.james.mime4j.dom.Multipart;
033 import org.apache.james.mime4j.dom.TextBody;
034 import org.apache.james.mime4j.dom.field.ParseException;
035 import org.apache.james.mime4j.field.address.AddressBuilder;
036 import org.apache.james.mime4j.message.BodyPart;
037 import org.apache.james.mime4j.message.MessageImpl;
038 import org.apache.james.mime4j.message.DefaultMessageBuilder;
039 import org.apache.james.mime4j.message.DefaultMessageWriter;
040 import org.apache.james.mime4j.message.MultipartImpl;
041 import org.apache.james.mime4j.storage.DefaultStorageProvider;
042 import org.apache.james.mime4j.storage.StorageBodyFactory;
043 import org.apache.james.mime4j.storage.StorageProvider;
044 import org.apache.james.mime4j.storage.TempFileStorageProvider;
045
046 /**
047 * This code should illustrate how to transform a message into another message
048 * without modifying the original.
049 */
050 public class TransformMessage {
051
052 // Host name used in message identifiers.
053 private static final String HOSTNAME = "localhost";
054
055 public static void main(String[] args) throws Exception {
056 // Explicitly set a strategy for storing body parts. Usually not
057 // necessary; for most applications the default setting is appropriate.
058 StorageProvider storageProvider = new TempFileStorageProvider();
059 DefaultStorageProvider.setInstance(storageProvider);
060
061 // Create a template message. It would be possible to load a message
062 // from an input stream but for this example a message object is created
063 // from scratch for demonstration purposes.
064 Message template = createTemplate();
065
066 // Create a new message by transforming the template.
067 Message transformed = transform(template);
068
069 MessageWriter writer = new DefaultMessageWriter();
070
071 // Print transformed message.
072 System.out.println("\n\nTransformed message:\n--------------------\n");
073 writer.writeMessage(transformed, System.out);
074
075 // Messages should be disposed of when they are no longer needed.
076 // Disposing of a message also disposes of all child elements (e.g. body
077 // parts) of the message.
078 transformed.dispose();
079
080 // Print original message to illustrate that it was not affected by the
081 // transformation.
082 System.out.println("\n\nOriginal template:\n------------------\n");
083 writer.writeMessage(template, System.out);
084
085 // Original message is no longer needed.
086 template.dispose();
087
088 // At this point all temporary files have been deleted because all
089 // messages and body parts have been disposed of properly.
090 }
091
092 /**
093 * Copies the given message and makes some arbitrary changes to the copy.
094 * @throws ParseException on bad arguments
095 */
096 private static Message transform(Message original) throws IOException, ParseException {
097 // Create a copy of the template. The copy can be modified without
098 // affecting the original.
099 MessageBuilder builder = new DefaultMessageBuilder();
100 Message message = builder.newMessage(original);
101
102 // In this example we know we have a multipart message. Use
103 // Message#isMultipart() if uncertain.
104 Multipart multipart = (Multipart) message.getBody();
105
106 // Insert a new text/plain body part after every body part of the
107 // template.
108 final int count = multipart.getCount();
109 for (int i = 0; i < count; i++) {
110 String text = "Text inserted after part " + (i + 1);
111 BodyPart bodyPart = createTextPart(text);
112 multipart.addBodyPart(bodyPart, 2 * i + 1);
113 }
114
115 // For no particular reason remove the second binary body part (now
116 // at index four).
117 Entity removed = multipart.removeBodyPart(4);
118
119 // The removed body part no longer has a parent entity it belongs to so
120 // it should be disposed of.
121 removed.dispose();
122
123 // Set some headers on the transformed message
124 message.createMessageId(HOSTNAME);
125 message.setSubject("Transformed message");
126 message.setDate(new Date());
127 message.setFrom(AddressBuilder.DEFAULT.parseMailbox("John Doe <jdoe@machine.example>"));
128
129 return message;
130 }
131
132 /**
133 * Creates a multipart/mixed message that consists of three parts (one text,
134 * two binary).
135 */
136 private static Message createTemplate() throws IOException {
137 Multipart multipart = new MultipartImpl("mixed");
138
139 BodyPart part1 = createTextPart("This is the first part of the template..");
140 multipart.addBodyPart(part1);
141
142 BodyPart part2 = createRandomBinaryPart(200);
143 multipart.addBodyPart(part2);
144
145 BodyPart part3 = createRandomBinaryPart(300);
146 multipart.addBodyPart(part3);
147
148 MessageImpl message = new MessageImpl();
149 message.setMultipart(multipart);
150
151 message.setSubject("Template message");
152
153 return message;
154 }
155
156 /**
157 * Creates a text part from the specified string.
158 */
159 private static BodyPart createTextPart(String text) {
160 TextBody body = new StorageBodyFactory().textBody(text, "UTF-8");
161
162 BodyPart bodyPart = new BodyPart();
163 bodyPart.setText(body);
164 bodyPart.setContentTransferEncoding("quoted-printable");
165
166 return bodyPart;
167 }
168
169 /**
170 * Creates a binary part with random content.
171 */
172 private static BodyPart createRandomBinaryPart(int numberOfBytes)
173 throws IOException {
174 byte[] data = new byte[numberOfBytes];
175 new Random().nextBytes(data);
176
177 Body body = new StorageBodyFactory()
178 .binaryBody(new ByteArrayInputStream(data));
179
180 BodyPart bodyPart = new BodyPart();
181 bodyPart.setBody(body, "application/octet-stream");
182 bodyPart.setContentTransferEncoding("base64");
183
184 return bodyPart;
185 }
186
187 }