001 package org.rakeshv.mail;
002
003 import java.io.PrintWriter;
004 import java.io.FileWriter;
005 import java.io.IOException;
006 import java.util.Date;
007 import java.util.Iterator;
008 import java.util.List;
009
010 import javax.mail.BodyPart;
011 import javax.mail.Folder;
012 import javax.mail.Message;
013 import javax.mail.MessagingException;
014 import javax.mail.Multipart;
015 import javax.mail.Session;
016 import javax.mail.internet.InternetAddress;
017 import javax.mail.internet.MimeBodyPart;
018 import javax.mail.internet.MimeMessage;
019 import javax.mail.internet.MimeMultipart;
020 import javax.servlet.http.HttpServletRequest;
021
022 import org.rakeshv.xml.addressbook.AddressBook;
023 import org.rakeshv.xml.addressbook.Person;
024 import org.rakeshv.xml.addressbook.Group;
025 import org.rakeshv.xml.addressbook.Member;
026
027 /**
028 * This class handles <code>multipart/form-data encoded form
029 * posts</code> from the <code>write.jsp</code> page that is used
030 * to compose email messages. This class parses out the message
031 * attributes, as well as all the attachments added to the message
032 * from the <code>HttpServletRequest</code>.
033 *
034 * <p>Copyright 2003, Rakesh Vidyadharan</p>
035 *
036 * @author Rakesh Vidyadharan 5<sup><small>th</small></sup> January
037 * 2003.
038 *
039 * $Id: SendHandler.java,v 1.5 2004/05/26 11:42:38 rakesh Exp $
040 */
041 public class SendHandler extends Object
042 {
043 /**
044 * The web session for the user using the webmail service.
045 */
046 private Session session = null;
047
048 /**
049 * The <code>Folder</code> which the user is viewing at present.
050 * This is used to determine if the new message being created is
051 * a reply to an existing message or not.
052 */
053 private Folder folder = null;
054
055 /**
056 * The {@link org.rakeshv.xml.addressbook.AddressBook} object for
057 * the current user.
058 */
059 private AddressBook addressBook = null;
060
061 /**
062 * The {@link WriteFormParser} class that is used to parse out the
063 * form parts and elements from the <code>HttpRequest</code>.
064 */
065 private WriteFormParser formParser = null;
066
067 /**
068 * The <code>Message</code> object that is to be created with all
069 * the attributes and parts specified in the form post.
070 */
071 private Message message = null;
072
073 /**
074 * Default constructor. Does nothing.
075 */
076 protected SendHandler() {}
077
078 /**
079 * Creates an instance of the handler, and sets the instance fields
080 * to the passed in values.
081 *
082 * @param folder - The mail folder that the user is currently
083 * viewing. See {@link #folder}.
084 * @param addressBook - The user's address book. See
085 * {@link #addressBook}.
086 * @param formParser - The parsed contents of the
087 * form. The {@link WriteFormParser#parseFormData()} method
088 * must have been invoked prior to initialising this class.
089 * @param session - The web session. See {@link #session}.
090 */
091 public SendHandler( Folder folder, AddressBook addressBook,
092 WriteFormParser formParser, Session session )
093 {
094 this.folder = folder;
095 this.addressBook = addressBook;
096 this.formParser = formParser;
097 this.session = session;
098 }
099
100 /**
101 * Creates the appropriate type of message. Fetches all the
102 * attachments and properties for the new message from the
103 * {@link WriteFormParser} and creates the new <code>Message</code>.
104 * If no attachments were specified in the <code>form post</code>,
105 * a "text/plain" message is created, otherwise a "multipart/mixed"
106 * message is created.
107 *
108 * @see #createMessage( Message )
109 *
110 * @return Message - The new message with all the message attributes
111 * including attachments set.
112 * @throws MessagingException - If any exceptions are encountered
113 * while creating the new message.
114 * @throws IOException - If errors are encountered while setting
115 * the body of the message.
116 */
117 public Message createMessage() throws MessagingException, IOException
118 {
119 int replyNumber = 0;
120 if ( formParser.getReply() != null && ! formParser.getReply().equals( "" ) )
121 {
122 try
123 {
124 replyNumber = Integer.parseInt( formParser.getReply() );
125 }
126 catch ( NumberFormatException nfe )
127 {
128 // Nothing to be done
129 }
130 }
131
132 if ( replyNumber > 0 )
133 {
134 message = folder.getMessage( replyNumber ).reply( false );
135 }
136 else
137 {
138 message = new MimeMessage( session );
139 }
140
141 setMessageAttributes();
142 setMessageBody();
143 return message;
144 }
145
146 /**
147 * Creates the appropriate type of message for forwarded mail.
148 * Fetches all the attachments and properties for the new message
149 * from the {@link WriteFormParser} and creates the new
150 * <code>Message</code>. This method also attaches any attachments
151 * that were originally part of the specified message to the new
152 * message being composed.
153 *
154 * @param currentMessage - The {@link
155 * WebMailBean#currentMessage} that is being forwarded.
156 * @return Message - The new message with all the message attributes
157 * including attachments set.
158 * @throws MessagingException - If any exceptions are encountered
159 * while creating the new message.
160 * @throws IOException - If errors are encountered while setting
161 * the body of the message.
162 */
163 public Message createMessage( Message currentMessage )
164 throws MessagingException, IOException
165 {
166 message = currentMessage.reply( false );
167 setMessageAttributes();
168 setForwardBody( currentMessage );
169 return message;
170 }
171
172 /**
173 * Set the common attributes for the {@link #message}. The common
174 * attributes set are <code>from, to, cc, bcc, subject</code>.
175 * The attributes are fetched from the <code>HttpServetRequest</code>
176 * and added to the new message. Simply calls the appropriate
177 * <code>methods</code> for setting the attributes.
178 *
179 * @see #setFrom()
180 * @see #setTo()
181 * @see #setCc()
182 * @see #setBcc()
183 * @see #setSubject()
184 *
185 * @throws MessagingException - If any exceptions are encountered
186 * while creating the new message.
187 */
188 private void setMessageAttributes()
189 throws MessagingException
190 {
191 setFrom();
192 setTo();
193 setCc();
194 setBcc();
195 setSubject();
196 setDate();
197 }
198
199 /**
200 * Set the <code>from</code> attribute of the new message.
201 *
202 * @throws MessagingException - If any exceptions are encountered
203 * while creating the new message.
204 */
205 private void setFrom()
206 throws MessagingException
207 {
208 message.setFrom( new InternetAddress( formParser.getFrom() ) );
209 }
210
211 /**
212 * Set the <code>to</code> attribute of the new message.
213 *
214 * @throws MessagingException - If any exceptions are encountered
215 * while creating the new message.
216 */
217 private void setTo()
218 throws MessagingException
219 {
220 String to = formParser.getTo();
221
222 StringBuffer toBuffer = new StringBuffer();
223 if ( formParser.getPersons() != null )
224 {
225 for ( Iterator iterator = formParser.getPersons().iterator(); iterator.hasNext(); )
226 {
227 String entry = (String) iterator.next();
228
229 if ( ! entry.equals( "" ) )
230 {
231 Person person = (Person) addressBook.getPersons().get( entry );
232 toBuffer.append( person.getMail() ).append( "," );
233 }
234 }
235 }
236 if ( formParser.getGroups() != null )
237 {
238 for ( Iterator iterator = formParser.getGroups().iterator(); iterator.hasNext(); )
239 {
240 String entry = (String) iterator.next();
241
242 if ( ! entry.equals( "" ) )
243 {
244 Group group = (Group) addressBook.getGroups().get( entry );
245 List list = group.getMembers();
246 for ( Iterator iter = list.iterator(); iter.hasNext(); )
247 {
248 Member member = (Member) iter.next();
249 toBuffer.append( member.getMail() ).append( "," );
250 }
251 }
252 }
253 }
254 if ( to != null )
255 {
256 message.setRecipients( Message.RecipientType.TO,
257 InternetAddress.parse( to ) );
258
259 if ( toBuffer.length() > 1 )
260 {
261 message.addRecipients( Message.RecipientType.TO,
262 InternetAddress.parse( toBuffer.substring( 0, toBuffer.length() - 1 ) ) );
263 }
264 }
265 else if ( toBuffer.length() > 1 )
266 {
267 message.addRecipients(
268 Message.RecipientType.TO,
269 InternetAddress.parse(
270 toBuffer.substring( 0, toBuffer.length() - 1 )
271 )
272 );
273 }
274 }
275
276 /**
277 * Set the <code>cc</code> attribute for the message.
278 *
279 * @throws MessagingException - If any exceptions are encountered
280 * while creating the new message.
281 */
282 private void setCc()
283 throws MessagingException
284 {
285 String cc = formParser.getCc();
286
287 if ( cc != null )
288 {
289 message.setRecipients(
290 Message.RecipientType.CC,
291 InternetAddress.parse( cc )
292 );
293 }
294 }
295
296 /**
297 * Set the <code>bcc</code> attribute for the message.
298 *
299 * @throws MessagingException - If any exceptions are encountered
300 * while creating the new message.
301 */
302 private void setBcc()
303 throws MessagingException
304 {
305 String bcc = formParser.getBcc();
306 if ( bcc != null )
307 {
308 message.setRecipients(
309 Message.RecipientType.BCC,
310 InternetAddress.parse( bcc )
311 );
312 }
313 }
314
315 /**
316 * Set the <code>subject</code> attribute for the message.
317 *
318 * @throws MessagingException - If any exceptions are encountered
319 * while creating the new message.
320 */
321 private void setSubject()
322 throws MessagingException
323 {
324 message.setSubject( formParser.getSubject() );
325 }
326
327 /**
328 * Set the <code>date</code> attribute for the message.
329 *
330 * @throws MessagingException - If any exceptions are encountered
331 * while creating the new message.
332 */
333 private void setDate()
334 throws MessagingException
335 {
336 message.setSentDate( new Date() );
337 }
338
339 /**
340 * Sets the various body parts for the {@link #message}. If no
341 * attachments were included in the form post, or if no attachments
342 * were associated with the message to which this new message is a
343 * reply to, then a plain-text message will be created. Otherwise,
344 * a message with multiple body parts will be created.
345 *
346 * @see #setBodyWithAttachments
347 *
348 * @throws MessagingException - If errors are encountered while
349 * setting the message body.
350 * @throws IOException - If errors are encountered while fetching
351 * the content from the existing message.
352 */
353 private void setMessageBody() throws MessagingException, IOException
354 {
355 if ( formParser.getAttachments() != null && ! formParser.getAttachments().isEmpty() )
356 {
357 setBodyWithAttachments();
358 }
359 else
360 {
361 message.setText( formParser.getBody() );
362 }
363 }
364
365 /**
366 * Set the body parts for the forwarded message. If the original
367 * message was a multipart message, then add all the original parts
368 * of the message to the new message. Also add any additional
369 * attachments added to the current new message.
370 *
371 * @param originalMessage - The message which is being
372 * forwarded.
373 * @throws MessagingException - If errors are encountered while
374 * adding the body to the reply message.
375 * @throws IOException - If errors are encountered while fetching
376 * the content from the existing message.
377 */
378 private void setForwardBody( Message originalMessage )
379 throws MessagingException, IOException
380 {
381 Multipart multipart = new MimeMultipart();
382
383 if ( message.isMimeType( "multipart/*" ) || ! formParser.getAttachments().isEmpty() )
384 {
385 // Add the new message body as the first part
386 BodyPart bodyPart = new MimeBodyPart();
387 bodyPart.setText( formParser.getBody() );
388 multipart.addBodyPart( bodyPart );
389
390 // Add any new attachments added to this message
391 if ( ! formParser.getAttachments().isEmpty() )
392 {
393 for ( Iterator iterator = formParser.getAttachments().iterator(); iterator.hasNext(); )
394 {
395 multipart.addBodyPart( (BodyPart) iterator.next() );
396 }
397 }
398
399 Multipart oldPart = (Multipart) originalMessage.getContent();
400 int count = oldPart.getCount();
401 // Add any old attachments to the new message
402 for ( int i = 1; i < count; ++i )
403 {
404 multipart.addBodyPart( oldPart.getBodyPart( i ) );
405 }
406
407 message.setContent( multipart );
408 }
409 else
410 {
411 message.setText( formParser.getBody() );
412 }
413 }
414
415 /**
416 * Set the body parts for the reply. If the original message was
417 * a multipart message, then add all the original parts of the
418 * message to the new message.
419 *
420 * @throws MessagingException - If errors are encountered while
421 * setting the body of the new message.
422 */
423 private void setBodyWithAttachments() throws MessagingException, IOException
424 {
425 Multipart multipart = new MimeMultipart();
426
427 // Add the new message body as the first part
428 BodyPart bodyPart = new MimeBodyPart();
429 bodyPart.setText( formParser.getBody() );
430 multipart.addBodyPart( bodyPart );
431
432 // Add the other attachments extracted from the form
433 for ( Iterator iterator = formParser.getAttachments().iterator(); iterator.hasNext(); )
434 {
435 multipart.addBodyPart( (BodyPart) iterator.next() );
436 }
437
438 message.setContent( multipart );
439 }
440 }