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 020package org.apache.james.mime4j.samples.transform; 021 022import java.io.ByteArrayInputStream; 023import java.io.IOException; 024import java.util.Date; 025import java.util.Random; 026 027import org.apache.james.mime4j.dom.Body; 028import org.apache.james.mime4j.dom.Entity; 029import org.apache.james.mime4j.dom.Message; 030import org.apache.james.mime4j.dom.MessageBuilder; 031import org.apache.james.mime4j.dom.MessageWriter; 032import org.apache.james.mime4j.dom.Multipart; 033import org.apache.james.mime4j.dom.TextBody; 034import org.apache.james.mime4j.dom.field.ParseException; 035import org.apache.james.mime4j.field.address.AddressBuilder; 036import org.apache.james.mime4j.message.BodyPart; 037import org.apache.james.mime4j.message.MessageImpl; 038import org.apache.james.mime4j.message.DefaultMessageBuilder; 039import org.apache.james.mime4j.message.DefaultMessageWriter; 040import org.apache.james.mime4j.message.MultipartImpl; 041import org.apache.james.mime4j.storage.DefaultStorageProvider; 042import org.apache.james.mime4j.storage.StorageBodyFactory; 043import org.apache.james.mime4j.storage.StorageProvider; 044import 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 */ 050public 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}