Source Code Cross Referenced for MailImpl.java in  » Groupware » ivatagroupware » com » ivata » groupware » business » mail » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Groupware » ivatagroupware » com.ivata.groupware.business.mail 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 2001 - 2005 ivata limited.
0003:         * All rights reserved.
0004:         * -----------------------------------------------------------------------------
0005:         * ivata groupware may be redistributed under the GNU General Public
0006:         * License as published by the Free Software Foundation;
0007:         * version 2 of the License.
0008:         *
0009:         * These programs are free software; you can redistribute them and/or
0010:         * modify them under the terms of the GNU General Public License
0011:         * as published by the Free Software Foundation; version 2 of the License.
0012:         *
0013:         * These programs are distributed in the hope that they will be useful,
0014:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
0016:         *
0017:         * See the GNU General Public License in the file LICENSE.txt for more
0018:         * details.
0019:         *
0020:         * If you would like a copy of the GNU General Public License write to
0021:         *
0022:         * Free Software Foundation, Inc.
0023:         * 59 Temple Place - Suite 330
0024:         * Boston, MA 02111-1307, USA.
0025:         *
0026:         *
0027:         * To arrange commercial support and licensing, contact ivata at
0028:         *                  http://www.ivata.com/contact.jsp
0029:         * -----------------------------------------------------------------------------
0030:         * $Log: MailImpl.java,v $
0031:         * Revision 1.12  2005/10/11 18:42:35  colinmacleod
0032:         * Fixed checkstyle issues.
0033:         *
0034:         * Revision 1.11  2005/10/11 18:25:13  colinmacleod
0035:         * Removed bcc and cc from simple send method.
0036:         *
0037:         * Revision 1.10  2005/10/10 16:06:39  colinmacleod
0038:         * Merged in changes from releases 0.11.2 and 0.11.3.
0039:         *
0040:         * Revision 1.9  2005/10/09 09:39:27  colinmacleod
0041:         * Merged changes from ivata groupware v0.11.2 back into main trunk.
0042:         *
0043:         * Revision 1.8  2005/10/02 14:08:59  colinmacleod
0044:         * Added/improved log4j logging.
0045:         *
0046:         * Revision 1.7  2005/09/14 16:16:52  colinmacleod
0047:         * Removed unused local and class variables.
0048:         * Added serialVersionUID.
0049:         *
0050:         * Revision 1.6.2.1  2005/10/08 17:36:37  colinmacleod
0051:         * SettingDateFormatter now requires SecuritySession in constructor.
0052:         *
0053:         * Revision 1.6  2005/04/29 02:48:20  colinmacleod
0054:         * Data bugfixes.
0055:         * Changed primary key back to Integer.
0056:         *
0057:         * Revision 1.5  2005/04/27 15:20:09  colinmacleod
0058:         * Now implements Serializable.
0059:         *
0060:         * Revision 1.4  2005/04/22 10:59:12  colinmacleod
0061:         * Added logging when there is no mail
0062:         * server and reordered this file alphabetically.
0063:         *
0064:         * Revision 1.3  2005/04/10 20:10:08  colinmacleod
0065:         * Added new themes.
0066:         * Changed id type to String.
0067:         * Changed i tag to em and b tag to strong.
0068:         * Improved PicoContainerFactory with NanoContainer scripts.
0069:         *
0070:         * Revision 1.2  2005/04/09 17:20:00  colinmacleod
0071:         * Changed copyright text to GPL v2 explicitly.
0072:         *
0073:         * Revision 1.1.1.1  2005/03/10 17:51:15  colinmacleod
0074:         * Restructured ivata op around Hibernate/PicoContainer.
0075:         * Renamed ivata groupware.
0076:         *
0077:         * Revision 1.6  2004/11/12 15:57:23  colinmacleod
0078:         * Removed dependencies on SSLEXT.
0079:         * Moved Persistence classes to ivata masks.
0080:         *
0081:         * Revision 1.5  2004/11/03 17:15:38  colinmacleod
0082:         * added addUserEmailAddresses method.
0083:         * Improved setUesrAliases to check telecom addresses in the person.
0084:         *
0085:         * Revision 1.4  2004/09/30 15:09:33  colinmacleod
0086:         * Bug fixes
0087:         *
0088:         * Revision 1.3  2004/07/18 21:59:24  colinmacleod
0089:         * Removed Person from User - now you need to use addressbook/persistence
0090:         * manager to find the person (makes the app run faster.)
0091:         *
0092:         * Revision 1.2  2004/07/13 19:48:12  colinmacleod
0093:         * Moved project to POJOs from EJBs.
0094:         * Applied PicoContainer to services layer (replacing session EJBs).
0095:         * Applied Hibernate to persistence layer (replacing entity EJBs).
0096:         *
0097:         * Revision 1.1  2004/03/27 10:31:26  colinmacleod
0098:         * Split off business logic from remote facades to POJOs.
0099:         *
0100:         * Revision 1.6  2004/03/21 21:16:39  colinmacleod
0101:         * Shortened name to ivata op.
0102:         *
0103:         * Revision 1.5  2004/03/21 20:51:51  colinmacleod
0104:         * Change SecurityServer into interface.
0105:         * Added checking of mail server.
0106:         *
0107:         * Revision 1.4  2004/03/10 22:43:13  colinmacleod
0108:         * Added security server exception handling.
0109:         *
0110:         * Revision 1.3  2004/02/10 19:57:26  colinmacleod
0111:         * Changed email address.
0112:         *
0113:         * Revision 1.2  2004/02/01 22:07:32  colinmacleod
0114:         * Added full names to author tags
0115:         *
0116:         * Revision 1.1.1.1  2004/01/27 20:59:56  colinmacleod
0117:         * Moved ivata openportal to SourceForge..
0118:         *
0119:         * Revision 1.6  2003/12/12 13:24:34  jano
0120:         * fixing webmail functionality
0121:         *
0122:         * Revision 1.5  2003/11/03 11:31:06  jano
0123:         * commiting webmail,
0124:         * tryinjg to fix deploying problem
0125:         *
0126:         * Revision 1.4  2003/10/28 13:27:51  jano
0127:         * commiting webmail,
0128:         * still fixing compile and building openGroupware project
0129:         *
0130:         * Revision 1.3  2003/10/15 14:13:00  jano
0131:         * converting to XDoclet
0132:         *
0133:         * Revision 1.2  2003/10/15 14:11:33  colin
0134:         * fixing for XDoclet
0135:         *
0136:         * Revision 1.25  2003/07/15 06:43:40  peter
0137:         * fixed the last fix
0138:         *
0139:         * Revision 1.24  2003/07/15 06:01:59  peter
0140:         * fixed message text bugs and composed attachments size bug
0141:         *
0142:         * Revision 1.23  2003/07/14 15:04:22  jano
0143:         * peter: fixed invisible attachments problem
0144:         *
0145:         * Revision 1.22  2003/07/14 14:52:24  jano
0146:         * fixing bug in mailBean
0147:         *
0148:         * Revision 1.21  2003/07/11 06:31:06  peter
0149:         * fixed text logic in alternative multiparts
0150:         *
0151:         * Revision 1.20  2003/07/07 13:43:32  peter
0152:         * fixed getAttachment for cases with fileName
0153:         *
0154:         * Revision 1.19  2003/06/22 21:28:10  peter
0155:         * re-fixed attachment handling for multipart cases
0156:         *
0157:         * Revision 1.18  2003/06/20 18:31:03  peter
0158:         * added incorrectly composed mail forwards  and self contained attachment like
0159:         * email handling
0160:         *
0161:         * Revision 1.17  2003/06/19 10:06:08  jano
0162:         * add check boxies in registration proces of customer
0163:         *
0164:         * Revision 1.16  2003/06/02 06:30:19  peter
0165:         * create reply and forward message fixed
0166:         *
0167:         * Revision 1.15  2003/05/28 05:41:21  peter
0168:         * added fileName as secondary attachments identifier, when contentId not
0169:         * present
0170:         *
0171:         * Revision 1.14  2003/05/27 17:15:12  peter
0172:         * getAttachment fixed, private getAttachment methnod added
0173:         *
0174:         * Revision 1.13  2003/05/15 08:21:12  peter
0175:         * fixed addMultipart logic - some multipart types weren't included
0176:         *
0177:         * Revision 1.12  2003/05/14 11:22:07  peter
0178:         * fixed bug: getDOFromJavamailMessage was called after folder closed in
0179:         * appendAttachmnets
0180:         *
0181:         * Revision 1.11  2003/05/13 15:24:18  peter
0182:         * attachment compose changes
0183:         *
0184:         * Revision 1.10  2003/05/12 16:31:13  peter
0185:         * attachment compose changes
0186:         *
0187:         * Revision 1.9  2003/04/01 17:58:52  colin
0188:         * removed boolean from InternetAddress constructor (marked as private in my JVM)
0189:         *
0190:         * Revision 1.8  2003/03/25 16:18:30  peter
0191:         * fixed email address validation
0192:         *
0193:         * Revision 1.7  2003/03/25 08:23:29  jano
0194:         * if there is no message in folder -> return null
0195:         * and validate the email addresses
0196:         *
0197:         * Revision 1.6  2003/03/14 10:26:46  jano
0198:         * adding backdoor man functionality
0199:         * backdoor man = briezky
0200:         *
0201:         * Revision 1.5  2003/03/03 16:57:12  colin
0202:         * converted localization to automatic paths
0203:         * added labels
0204:         * added mandatory fieldName attribute
0205:         *
0206:         * Revision 1.4  2003/02/28 10:23:27  peter
0207:         * fixed handling of plain - one part messages in getDOFromJavaMailMessage
0208:         *
0209:         * Revision 1.3  2003/02/27 17:23:09  peter
0210:         * Changed the return type of getAttachment to FileContentDO
0211:         *
0212:         * Revision 1.2  2003/02/25 11:53:33  colin
0213:         * bugfixes and minor restructuring
0214:         *
0215:         * Revision 1.1  2003/02/24 19:09:24  colin
0216:         * moved to business
0217:         *
0218:         * Revision 1.38  2003/02/20 20:26:15  colin
0219:         * improved validation by adding ValidationField and ValidationException
0220:         *
0221:         * Revision 1.37  2003/02/04 17:39:21  colin
0222:         * copyright notice
0223:         *
0224:         * Revision 1.36  2003/01/15 15:43:56  colin
0225:         * re-implemented:
0226:         * forwarding/replying (also to multiple messages)
0227:         * moving messages
0228:         *
0229:         * Revision 1.35  2002/11/20 09:21:23  peter
0230:         * removed duplicated function contents getDOFrom... (Jbuilder bug)
0231:         *
0232:         * Revision 1.34  2002/11/17 20:01:24  colin
0233:         * speed improvements in findMessagesInFolder...
0234:         *
0235:         * Revision 1.33  2002/11/12 09:12:38  colin
0236:         * structural changes. currently mail bean composes and reads messages but
0237:         * attachment & thread handling not active
0238:         *
0239:         * Revision 1.32  2002/10/25 08:31:44  peter
0240:         * mailFolderSent setting name changed to emailFolderSent
0241:         *
0242:         * Revision 1.31  2002/10/23 12:44:37  jano
0243:         * using new method for get System userName
0244:         *
0245:         * Revision 1.30  2002/10/23 09:18:59  jano
0246:         * there is a new method for generating SystemUserName
0247:         *
0248:         * Revision 1.29  2002/10/18 09:18:48  colin
0249:         * check users to make sure they are enabled before sending them mail
0250:         *
0251:         * Revision 1.28  2002/10/14 11:15:46  peter
0252:         * fixed a bug in (precomposed) send method, the cc fields work now
0253:         *
0254:         * Revision 1.27  2002/10/11 10:05:38  jano
0255:         * add PREFIX to user name for difren site
0256:         *
0257:         * Revision 1.26  2002/10/10 14:03:57  peter
0258:         * changes due to demo version
0259:         *
0260:         * Revision 1.25  2002/10/01 05:59:47  peter
0261:         * modifications in (precomposed) send method
0262:         *
0263:         * Revision 1.24  2002/09/17 07:26:24  peter
0264:         * working version
0265:         *
0266:         * Revision 1.23  2002/09/16 16:26:40  peter
0267:         * the attachments stuff works....
0268:         *
0269:         * Revision 1.22  2002/09/13 13:59:17  peter
0270:         * appendMessages and setDO methods tuned...
0271:         * it still doesn't work properly
0272:         *
0273:         * Revision 1.21  2002/09/12 15:55:25  peter
0274:         * tuned createMessage and setDO
0275:         *
0276:         * Revision 1.20  2002/09/12 07:26:19  colin
0277:         * added vacation message and user alias methods
0278:         *
0279:         * Revision 1.19  2002/09/11 15:57:48  peter
0280:         * finished createMessage and setDO, debugging needed yet
0281:         *
0282:         * Revision 1.18  2002/09/11 11:33:12  peter
0283:         * moveMessage works, works on createMessage and setDO
0284:         *
0285:         * Revision 1.17  2002/09/10 15:38:51  peter
0286:         * MailBean: works on methods
0287:         *
0288:         * Revision 1.16  2002/09/10 14:18:51  peter
0289:         * MailBean: works on methods
0290:         *
0291:         * Revision 1.15  2002/09/10 08:20:16  peter
0292:         * MailBean: added moveMessage method
0293:         *
0294:         * Revision 1.14  2002/09/09 16:07:37  peter
0295:         * added and modified methods in mail/MailBean
0296:         *
0297:         * Revision 1.13  2002/09/09 08:27:24  colin
0298:         * changed mail bean from stateful to stateless
0299:         * added new MailSession class
0300:         *
0301:         * Revision 1.12  2002/08/30 09:50:31  colin
0302:         * changed canUser... methods to just can...
0303:         *
0304:         * Revision 1.11  2002/08/29 12:23:06  peter
0305:         * mail display works...
0306:         *
0307:         * Revision 1.10  2002/08/27 15:26:25  peter
0308:         * worked on getDO, should be finished
0309:         *
0310:         * Revision 1.9  2002/08/26 15:30:14  peter
0311:         * MessageDO integration, not finished yet
0312:         *
0313:         * Revision 1.8  2002/08/26 11:15:47  peter
0314:         * added getDo and the basic methods work
0315:         *
0316:         * Revision 1.7  2002/08/23 08:09:37  peter
0317:         * design for MailBean methods, display so far
0318:         *
0319:         * Revision 1.6  2002/08/16 12:35:22  peter
0320:         * fiixed a minor bug in getMessage method
0321:         *
0322:         * Revision 1.5  2002/08/16 11:59:00  peter
0323:         * new mail accessing methods
0324:         *
0325:         * Revision 1.4  2002/08/11 11:37:50  colin
0326:         * added routines to handle server activation and passivisation
0327:         *
0328:         * Revision 1.3  2002/07/26 13:08:06  colin
0329:         * first version with mail server support
0330:         *
0331:         * Revision 1.2  2002/07/15 13:29:27  jano
0332:         * added CreateException
0333:         *
0334:         * Revision 1.1  2002/07/15 07:51:04  colin
0335:         * added new Mail EJB and local interface to settings
0336:         * -----------------------------------------------------------------------------
0337:         */
0338:        package com.ivata.groupware.business.mail;
0339:
0340:        import com.ivata.groupware.admin.security.server.SecurityServer;
0341:        import com.ivata.groupware.admin.security.server.SecurityServerException;
0342:        import com.ivata.groupware.admin.security.server.SecuritySession;
0343:        import com.ivata.groupware.admin.security.user.UserDO;
0344:        import com.ivata.groupware.admin.setting.Settings;
0345:        import com.ivata.groupware.admin.setting.SettingsDataTypeException;
0346:        import com.ivata.groupware.business.addressbook.AddressBook;
0347:        import com.ivata.groupware.business.addressbook.person.PersonDO;
0348:        import com.ivata.groupware.business.addressbook.telecomaddress.TelecomAddressConstants;
0349:        import com.ivata.groupware.business.addressbook.telecomaddress.TelecomAddressDO;
0350:        import com.ivata.groupware.business.drive.file.FileContentDO;
0351:        import com.ivata.groupware.business.drive.file.FileDO;
0352:        import com.ivata.groupware.business.mail.message.MessageDO;
0353:        import com.ivata.groupware.business.mail.message.MessageNotFoundException;
0354:        import com.ivata.groupware.business.mail.server.MailServer;
0355:        import com.ivata.groupware.business.mail.server.NoMailServerException;
0356:        import com.ivata.groupware.business.mail.session.MailSession;
0357:        import com.ivata.groupware.util.SettingDateFormatter;
0358:        import com.ivata.groupware.web.format.EmailAddressFormatter;
0359:        import com.ivata.groupware.web.format.SanitizerFormat;
0360:
0361:        import com.ivata.mask.Mask;
0362:        import com.ivata.mask.MaskFactory;
0363:        import com.ivata.mask.util.SerializedByteArray;
0364:        import com.ivata.mask.util.StringHandling;
0365:        import com.ivata.mask.util.SystemException;
0366:        import com.ivata.mask.validation.ValidationError;
0367:        import com.ivata.mask.validation.ValidationErrors;
0368:        import com.ivata.mask.web.format.CharacterEntityFormat;
0369:        import com.ivata.mask.web.format.FormatConstants;
0370:        import com.ivata.mask.web.format.HTMLFormatter;
0371:        import com.ivata.mask.web.format.LineBreakFormat;
0372:        import com.ivata.mask.web.tag.webgui.list.ListColumnComparator;
0373:
0374:        import org.apache.log4j.Logger;
0375:
0376:        import java.io.ByteArrayOutputStream;
0377:        import java.io.File;
0378:        import java.io.IOException;
0379:        import java.io.InputStream;
0380:        import java.io.Serializable;
0381:
0382:        import java.text.MessageFormat;
0383:
0384:        import java.util.Arrays;
0385:        import java.util.Calendar;
0386:        import java.util.Collection;
0387:        import java.util.Date;
0388:        import java.util.GregorianCalendar;
0389:        import java.util.Iterator;
0390:        import java.util.List;
0391:        import java.util.Set;
0392:        import java.util.TreeMap;
0393:        import java.util.Vector;
0394:
0395:        import javax.activation.DataHandler;
0396:        import javax.activation.DataSource;
0397:        import javax.activation.FileDataSource;
0398:
0399:        import javax.mail.Address;
0400:        import javax.mail.AuthenticationFailedException;
0401:        import javax.mail.Flags;
0402:        import javax.mail.Folder;
0403:        import javax.mail.FolderNotFoundException;
0404:        import javax.mail.Message;
0405:        import javax.mail.MessagingException;
0406:        import javax.mail.NoSuchProviderException;
0407:        import javax.mail.Part;
0408:        import javax.mail.Session;
0409:        import javax.mail.Store;
0410:        import javax.mail.Transport;
0411:        import javax.mail.internet.AddressException;
0412:        import javax.mail.internet.InternetAddress;
0413:        import javax.mail.internet.MimeBodyPart;
0414:        import javax.mail.internet.MimeMessage;
0415:        import javax.mail.internet.MimeMultipart;
0416:        import javax.mail.internet.MimePart;
0417:
0418:        /**
0419:         * <p>This session bean provides an interface to the mail system. Every mail
0420:         * operation for retrieving deleting and sending messages takes place in this
0421:         * class.</p>
0422:         *
0423:         * @since 2002-07-12
0424:         * @author Colin MacLeod
0425:         * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
0426:         * @author Peter Illes
0427:         * @version $Revision: 1.12 $
0428:         */
0429:        public class MailImpl implements  Mail, Serializable {
0430:            /**
0431:             * Serialization version (for <code>Serializable</code> interface).
0432:             */
0433:            private static final long serialVersionUID = 1L;
0434:
0435:            /**
0436:             * <p>Logger for this class.</p>
0437:             */
0438:            private static final Logger logger = Logger
0439:                    .getLogger(MailImpl.class);
0440:            private AddressBook addressBook;
0441:            private SettingDateFormatter dateFormatter = null;
0442:            private MailServer mailServer;
0443:            MaskFactory maskFactory;
0444:
0445:            /**
0446:             * <p>
0447:             * Settings implementation. Used to retrieve the email address host.
0448:             * </p>
0449:             */
0450:            private Settings settings;
0451:
0452:            /**
0453:             * <p>
0454:             * Initialize the mail implementation.
0455:             * </p>
0456:             *
0457:             * @param securityServer A valid security server for the current site. If
0458:             * this is not an instance of {@link com.ivata.groupware.business.mail.server.MailServer}
0459:             * the mail implementation will not be usable.
0460:             * @param persistenceManager This is used to save/access data from the
0461:             * persistence store.
0462:             * @param addressBook This is used to read contacts email details.
0463:             * @param settings Contains user defined settings and preferences.
0464:             * @param dateFormatter Used to format mail dates and times.
0465:             * @param idDispenser
0466:             */
0467:            public MailImpl(SecurityServer securityServer,
0468:                    AddressBook addressBook, Settings settings,
0469:                    MaskFactory maskFactory) {
0470:                assert (securityServer != null);
0471:
0472:                if (securityServer instanceof  MailServer) {
0473:                    this .mailServer = (MailServer) securityServer;
0474:                } else {
0475:                    logger.warn("Security server class ("
0476:                            + securityServer.getClass().getName()
0477:                            + ") is not a mail server class.");
0478:                }
0479:
0480:                this .settings = settings;
0481:                this .addressBook = addressBook;
0482:                this .maskFactory = maskFactory;
0483:            }
0484:
0485:            private void checkDateFormatter(SecuritySession securitySession) {
0486:                if (dateFormatter == null) {
0487:                    dateFormatter = new SettingDateFormatter(securitySession,
0488:                            settings);
0489:                }
0490:            }
0491:
0492:            /**
0493:             * <p>Add a composed message to the drafts folder for later sending.</p>
0494:             *
0495:             * @param mailSession valid mail session to which the user should already be
0496:             *     logged in.
0497:             * @param messageDO data object containing full details of the
0498:             *     message to be added to the drafts.
0499:             * @return new <code>MessageDO</code> with the <code>id</code> set to the
0500:             *     current value in the mail system.
0501:             */
0502:            public MessageDO addMessageToDraftsFolder(
0503:                    final MailSession mailSession, final MessageDO messageDO)
0504:                    throws SystemException {
0505:                if (logger.isDebugEnabled()) {
0506:                    logger
0507:                            .debug("addMessageToDraftsFolder(MailSession mailSession = "
0508:                                    + mailSession
0509:                                    + ", MessageDO messageDO = "
0510:                                    + messageDO + ") - start");
0511:                }
0512:
0513:                checkDateFormatter(mailSession);
0514:
0515:                Store store = mailServer.connectStore(mailSession);
0516:
0517:                try {
0518:                    Session javaMailSession;
0519:
0520:                    try {
0521:                        javaMailSession = mailSession.getJavaMailSession();
0522:                    } catch (java.security.NoSuchProviderException e1) {
0523:                        logger
0524:                                .error(
0525:                                        "addMessageToDraftsFolder(MailSession, MessageDO)",
0526:                                        e1);
0527:
0528:                        throw new SystemException(e1);
0529:                    }
0530:
0531:                    // get the drafts folder in case we want to copy over an older mail
0532:                    Folder draftsFolder = openDraftsFolder(store, mailSession);
0533:
0534:                    MimeMessage newMessage = setDOToJavaMailMessage(
0535:                            javaMailSession, draftsFolder, messageDO);
0536:
0537:                    newMessage.setSentDate(Calendar.getInstance().getTime());
0538:
0539:                    // append the new message to the drafts folder
0540:                    Message[] messages = { newMessage };
0541:
0542:                    draftsFolder.appendMessages(messages);
0543:
0544:                    // note the new id
0545:                    messageDO.setMessageID(((MimeMessage) draftsFolder
0546:                            .getMessage(draftsFolder.getMessageCount()))
0547:                            .getMessageID());
0548:
0549:                    // only now can we delete/expunge the old mail from the drafts
0550:                    // folder
0551:                    draftsFolder.expunge();
0552:                    draftsFolder.close(true);
0553:                } catch (MessagingException e1) {
0554:                    logger.error(
0555:                            "addMessageToDraftsFolder(MailSession, MessageDO)",
0556:                            e1);
0557:
0558:                    throw new SystemException(e1);
0559:                } finally {
0560:                    try {
0561:                        store.close();
0562:                    } catch (MessagingException e) {
0563:                        logger.error(
0564:                                "Messaging exception on closing the store", e);
0565:                    }
0566:                }
0567:
0568:                if (logger.isDebugEnabled()) {
0569:                    logger
0570:                            .debug("addMessageToDraftsFolder(MailSession, MessageDO) - end - return value = "
0571:                                    + messageDO);
0572:                }
0573:
0574:                return messageDO;
0575:            }
0576:
0577:            /**
0578:             * <p>Recursive routine used for building up all attachments in the
0579:             * <code>MessageDO<code> provided.</p>
0580:             *
0581:             * @param messagePart the multipart part or message to process.
0582:             * @param messageDO the data object to add results to.
0583:             * @throws GroupwareException if there is a <code>MailMessagingException</code> or
0584:             *   <code>IOException</code>.
0585:             */
0586:            private void addMultiPart(final Part messagePart,
0587:                    final MessageDO messageDO) throws SystemException {
0588:                if (logger.isDebugEnabled()) {
0589:                    logger.debug("addMultiPart(Part messagePart = "
0590:                            + messagePart + ", MessageDO messageDO = "
0591:                            + messageDO + ") - start");
0592:                }
0593:
0594:                MimeMultipart content;
0595:                MimeBodyPart subPart;
0596:
0597:                List messageTextParts = new Vector();
0598:
0599:                try {
0600:                    content = (MimeMultipart) messagePart.getContent();
0601:
0602:                    //go through all the subParts
0603:                    for (int i = 0; i < content.getCount(); i++) {
0604:                        subPart = (MimeBodyPart) content.getBodyPart(i);
0605:
0606:                        // when multipart/alternative and no text found in parent call,
0607:                        // store the text of the parts to select the best one after the loop
0608:                        if (messagePart.isMimeType("multipart/alternative")
0609:                                && subPart.isMimeType("text/*")
0610:                                && StringHandling.isNullOrEmpty(messageDO
0611:                                        .getText())) {
0612:                            messageTextParts.add(subPart);
0613:                        } else if (messagePart.isMimeType("multipart/*")) {
0614:                            // other multipart types
0615:                            if (StringHandling.isNullOrEmpty(messageDO
0616:                                    .getText())
0617:                                    && (subPart.getDisposition() == null)
0618:                                    && (subPart.getFileName() == null)) {
0619:                                if (subPart.isMimeType("text/*")) {
0620:                                    messageTextParts.add(subPart);
0621:                                } else if (subPart.isMimeType("multipart/*")) {
0622:                                    addMultiPart((Part) subPart, messageDO);
0623:                                } else {
0624:                                    addPart(subPart, messageDO);
0625:                                }
0626:                            } else {
0627:                                if (subPart.isMimeType("multipart/*")) {
0628:                                    addMultiPart((Part) subPart, messageDO);
0629:                                } else {
0630:                                    addPart(subPart, messageDO);
0631:                                }
0632:                            }
0633:                        }
0634:                    }
0635:
0636:                    // looking for best message text
0637:                    if (!messageTextParts.isEmpty()) {
0638:                        String HTML = null;
0639:                        String text = null;
0640:
0641:                        // let's choose the best text
0642:                        for (Iterator i = messageTextParts.iterator(); i
0643:                                .hasNext();) {
0644:                            subPart = (MimeBodyPart) i.next();
0645:
0646:                            if (subPart.isMimeType("text/HTML")) {
0647:                                HTML = (String) subPart.getContent();
0648:                            } else if (subPart.isMimeType("text/plain")) {
0649:                                text = (String) subPart.getContent();
0650:                            }
0651:
0652:                            // TODO: we could use text/enriched too
0653:                        }
0654:
0655:                        if (HTML != null) {
0656:                            messageDO.setText(HTML);
0657:                            messageDO.setFormat(FormatConstants.FORMAT_HTML);
0658:                        } else if (text != null) {
0659:                            messageDO.setText(text);
0660:                            messageDO.setFormat(FormatConstants.FORMAT_TEXT);
0661:                        }
0662:                    }
0663:                } catch (MessagingException e) {
0664:                    logger.error("addMultiPart(Part, MessageDO)", e);
0665:
0666:                    throw new SystemException(e);
0667:                } catch (java.io.IOException e) {
0668:                    logger.error("addMultiPart(Part, MessageDO)", e);
0669:
0670:                    throw new SystemException(e);
0671:                }
0672:
0673:                if (logger.isDebugEnabled()) {
0674:                    logger.debug("addMultiPart(Part, MessageDO) - end");
0675:                }
0676:            }
0677:
0678:            /**
0679:             * <p>Add a part of a multi-part message to the attachments of the message
0680:             * data object.</p>
0681:             *
0682:             * @param part the message part to process.
0683:             * @param messageDO the data object to add results to.
0684:             * @throws GroupwareException if there is a <code>MessagingException</code> or an
0685:             *     <code>IOException</code>.
0686:             */
0687:            private void addPart(final MimePart part, final MessageDO messageDO)
0688:                    throws SystemException {
0689:                if (logger.isDebugEnabled()) {
0690:                    logger.debug("addPart(MimePart part = " + part
0691:                            + ", MessageDO messageDO = " + messageDO
0692:                            + ") - start");
0693:                }
0694:
0695:                FileDO attachment = new FileDO();
0696:
0697:                try {
0698:                    attachment.setMimeType(part.getContentType());
0699:                    attachment.setSize(new Integer(part.getSize()));
0700:
0701:                    String contentId = part.getContentID();
0702:                    String name = part.getFileName();
0703:
0704:                    // return with empty hands if no identifier, the attachment will be
0705:                    // impossible to locate
0706:                    if ((contentId == null) && (name == null)) {
0707:                        if (logger.isDebugEnabled()) {
0708:                            logger.debug("addPart(MimePart, MessageDO) - end");
0709:                        }
0710:
0711:                        if (logger.isDebugEnabled()) {
0712:                            logger.debug("addPart(MimePart, MessageDO) - end");
0713:                        }
0714:
0715:                        return;
0716:                    }
0717:
0718:                    // prefer contentId as identifier and name as the display info
0719:                    attachment.setName((contentId != null) ? contentId : name);
0720:                    attachment.setComment((name != null) ? name : contentId);
0721:                } catch (MessagingException e) {
0722:                    logger.error("addPart(MimePart, MessageDO)", e);
0723:
0724:                    throw new SystemException(e);
0725:                }
0726:
0727:                messageDO.getAttachments().add(attachment);
0728:
0729:                if (logger.isDebugEnabled()) {
0730:                    logger.debug("addPart(MimePart, MessageDO) - end");
0731:                }
0732:            }
0733:
0734:            /**
0735:             * <p>Internal helper to add a message to the sent mail folder. This should
0736:             * be called <em><u>after</u></em> sending the mail.</p>
0737:             */
0738:            private void addToSentFolder(final MailSession mailSession,
0739:                    final MimeMessage message) throws SystemException {
0740:                if (logger.isDebugEnabled()) {
0741:                    logger.debug("addToSentFolder(MailSession mailSession = "
0742:                            + mailSession + ", MimeMessage message = "
0743:                            + message + ") - start");
0744:                }
0745:
0746:                Folder sentFolder;
0747:
0748:                Store store = mailServer.connectStore(mailSession);
0749:
0750:                try {
0751:                    String sentFolderName = settings.getStringSetting(
0752:                            mailSession, "emailFolderSent", mailSession
0753:                                    .getUser());
0754:                    sentFolder = mailServer.getFolder(mailSession, store,
0755:                            sentFolderName);
0756:
0757:                    if (!sentFolder.exists()) {
0758:                        try {
0759:                            if (!sentFolder.create(Folder.HOLDS_MESSAGES)) {
0760:                                throw new SystemException(
0761:                                        "There was no sent folder for you on this server, "
0762:                                                + "and ivata mail could not create one.<br>Please "
0763:                                                + "contact your administrator.");
0764:                            }
0765:                        } catch (MessagingException e1) {
0766:                            logger
0767:                                    .error(
0768:                                            "addToSentFolder(MailSession, MimeMessage)",
0769:                                            e1);
0770:
0771:                            throw new SystemException(e1);
0772:                        }
0773:                    }
0774:
0775:                    Message[] messages = { message };
0776:
0777:                    try {
0778:                        sentFolder.appendMessages(messages);
0779:                    } catch (MessagingException eAppend) {
0780:                        logger.error(
0781:                                "addToSentFolder(MailSession, MimeMessage)",
0782:                                eAppend);
0783:
0784:                        throw new SystemException(
0785:                                "There was an error adding your message to the sent "
0786:                                        + "messages folder: "
0787:                                        + eAppend.getMessage(), eAppend);
0788:                    }
0789:                } catch (MessagingException eNoSent) {
0790:                    logger.error("addToSentFolder(MailSession, MimeMessage)",
0791:                            eNoSent);
0792:
0793:                    throw new SystemException(
0794:                            "Sent folder not available in store. "
0795:                                    + eNoSent.getMessage(), eNoSent);
0796:                } catch (SettingsDataTypeException e) {
0797:                    logger
0798:                            .error("addToSentFolder(MailSession, MimeMessage)",
0799:                                    e);
0800:
0801:                    throw new SystemException(e);
0802:                } finally {
0803:                    try {
0804:                        store.close();
0805:                    } catch (MessagingException e) {
0806:                        logger.error(
0807:                                "Messaging exception on closing the store", e);
0808:                    }
0809:                }
0810:
0811:                if (logger.isDebugEnabled()) {
0812:                    logger
0813:                            .debug("addToSentFolder(MailSession, MimeMessage) - end");
0814:                }
0815:            }
0816:
0817:            /**
0818:             * <p>
0819:             * Add appropriate user addresses given a list of user aliases.
0820:             * </p>
0821:             *
0822:             * @param securitySession valid security session.
0823:             * @param userName name of the user who owns teh aliases.
0824:             * @param userAliases a <code>Collection</code> of <code>String</code>
0825:             *     instances containing the local part of the different email aliases
0826:             *     this user has. If the user has no aliaes, an empty collection should
0827:             *     be provided.
0828:             * @param telecomAddresess a <code>Collection</code> containing all the
0829:             *     user's existing email addresses, as <code>TelecomAddressDO</code>
0830:             *     instances.
0831:             */
0832:            public void addUserAliasEmailAddresses(
0833:                    final SecuritySession securitySession,
0834:                    final String userName, final Collection userAliases,
0835:                    final Collection telecomAddresses,
0836:                    final String emailAddressHost) throws SystemException {
0837:                if (logger.isDebugEnabled()) {
0838:                    logger
0839:                            .debug("addUserAliasEmailAddresses(SecuritySession securitySession = "
0840:                                    + securitySession
0841:                                    + ", String userName = "
0842:                                    + userName
0843:                                    + ", Collection userAliases = "
0844:                                    + userAliases
0845:                                    + ", Collection telecomAddresses = "
0846:                                    + telecomAddresses
0847:                                    + ", String emailAddressHost = "
0848:                                    + emailAddressHost + ") - start");
0849:                }
0850:
0851:                checkDateFormatter(securitySession);
0852:
0853:                Iterator telecomAddressIterator = telecomAddresses.iterator();
0854:                List currentAddresses = new Vector();
0855:
0856:                while (telecomAddressIterator.hasNext()) {
0857:                    TelecomAddressDO this TelecomAddress = (TelecomAddressDO) telecomAddressIterator
0858:                            .next();
0859:
0860:                    if (!StringHandling.isNullOrEmpty(this TelecomAddress
0861:                            .getAddress())
0862:                            && (this TelecomAddress.getType() == TelecomAddressConstants.TYPE_EMAIL)) {
0863:                        currentAddresses.add(this TelecomAddress.getAddress());
0864:                    }
0865:                }
0866:
0867:                // if the person has no email address, give him/her one
0868:                // check there is at least one alias - the following routine will
0869:                // do the rest
0870:                // we make it conditional because you might not always want to have
0871:                // user@host as your email address - this way, you can specify a
0872:                // different one
0873:                if ((currentAddresses.size() == 0) && (userAliases.size() == 0)) {
0874:                    userAliases.add(userName);
0875:                }
0876:
0877:                // go thro' all aliases and create email addreses from them
0878:                Iterator aliasIterator = userAliases.iterator();
0879:
0880:                while (aliasIterator.hasNext()) {
0881:                    String alias = (String) aliasIterator.next();
0882:                    String aliasAddress = alias + "@" + emailAddressHost;
0883:
0884:                    // if it is already there, move on...
0885:                    if (currentAddresses.contains(aliasAddress)) {
0886:                        continue;
0887:                    }
0888:
0889:                    TelecomAddressDO newAddress = new TelecomAddressDO();
0890:                    newAddress.setAddress(aliasAddress);
0891:                    newAddress.setType(TelecomAddressConstants.TYPE_EMAIL);
0892:                    newAddress.setNumber(telecomAddresses.size());
0893:                    telecomAddresses.add(newAddress);
0894:                }
0895:
0896:                if (logger.isDebugEnabled()) {
0897:                    logger
0898:                            .debug("addUserAliasEmailAddresses(SecuritySession, String, Collection, Collection, String) - end");
0899:                }
0900:            }
0901:
0902:            /**
0903:             * <p>Append attachments to a message located in the drafts folder.</p>
0904:             *
0905:             * @param mailSession valid mail session to which the user should already be
0906:             *     logged in.
0907:             * @param id the unique identifier of the message to which we want to append
0908:             *     attachments.
0909:             * @param attachments <code>List</code> of <code>String</code>s -
0910:             *     filenames of files waiting in upload directory.
0911:             * @return <code>null</code> when the operation failed, otherwise the new
0912:             *     message id.
0913:             * @exception MessageNotFoundException if the folder doesn't exist, or there
0914:             *     is no matching mail in this folder.
0915:             *
0916:             * @ejb.interface-method
0917:             *      view-type = "remote"
0918:             */
0919:            public MessageDO appendAttachments(final MailSession mailSession,
0920:                    final String id, final List attachments)
0921:                    throws SystemException {
0922:                if (logger.isDebugEnabled()) {
0923:                    logger.debug("appendAttachments(MailSession mailSession = "
0924:                            + mailSession + ", String id = " + id
0925:                            + ", List attachments = " + attachments
0926:                            + ") - start");
0927:                }
0928:
0929:                checkDateFormatter(mailSession);
0930:
0931:                String newId = null;
0932:                UserDO user = mailSession.getUser();
0933:                Store store = mailServer.connectStore(mailSession);
0934:
0935:                try {
0936:                    String siteHome = settings.getStringSetting(mailSession,
0937:                            "siteHome", user);
0938:                    String uploadDirectory = siteHome
0939:                            + "/users/"
0940:                            + mailSession.authenticator
0941:                                    .getPasswordAuthentication().getUserName()
0942:                            + "/upload/files/";
0943:
0944:                    Session javaMailSession;
0945:
0946:                    try {
0947:                        javaMailSession = mailSession.getJavaMailSession();
0948:                    } catch (SecurityServerException e) {
0949:                        logger.error(
0950:                                "appendAttachments(MailSession, String, List)",
0951:                                e);
0952:
0953:                        throw new SystemException(e);
0954:                    } catch (java.security.NoSuchProviderException e) {
0955:                        logger.error(
0956:                                "appendAttachments(MailSession, String, List)",
0957:                                e);
0958:
0959:                        throw new SystemException(e);
0960:                    }
0961:
0962:                    Folder draftsFolder = openDraftsFolder(store, mailSession);
0963:                    MimeMessage oldMessage = findJavaMailMessageByFolderMessageId(
0964:                            draftsFolder, id);
0965:                    int i;
0966:                    MimeBodyPart newPart;
0967:                    MimeMultipart newMessageContent = new MimeMultipart();
0968:                    MimeMultipart oldMessageContent;
0969:                    MimeMessage newMessage = copyJavaMailMessage(
0970:                            javaMailSession, oldMessage);
0971:
0972:                    // when the message is already multipart/mixed, no probs...
0973:                    if (oldMessage.isMimeType("multipart/mixed")) {
0974:                        oldMessageContent = (MimeMultipart) oldMessage
0975:                                .getContent();
0976:
0977:                        for (i = 0; i < oldMessageContent.getCount(); i++) {
0978:                            newPart = (MimeBodyPart) oldMessageContent
0979:                                    .getBodyPart(i);
0980:                            newMessageContent.addBodyPart(newPart);
0981:                        }
0982:                    } else {
0983:                        // create the first part from the old message, attachments will be appended
0984:                        newPart = new MimeBodyPart();
0985:                        newPart.setContent(oldMessage.getContent(), oldMessage
0986:                                .getContentType());
0987:                        newPart.setHeader("Content-Type", oldMessage
0988:                                .getContentType());
0989:                        newMessageContent.addBodyPart(newPart);
0990:                    }
0991:
0992:                    // add the attachments, passed as fileNames of files in upload dir
0993:                    for (Iterator attachmentsIterator = attachments.iterator(); attachmentsIterator
0994:                            .hasNext();) {
0995:                        File attachment = new File(uploadDirectory,
0996:                                (String) attachmentsIterator.next());
0997:
0998:                        // process the file in upload directory
0999:                        if (attachment.canRead()) {
1000:                            newPart = new MimeBodyPart();
1001:                            newPart.setFileName(attachment.getName());
1002:                            newPart.setDisposition(Part.ATTACHMENT);
1003:
1004:                            DataSource dataSource = new FileDataSource(
1005:                                    attachment);
1006:                            newPart.setDataHandler(new DataHandler(dataSource));
1007:                            newPart.setHeader("Content-Type", dataSource
1008:                                    .getContentType());
1009:                            newPart.setHeader("Content-Transfer-Encoding",
1010:                                    "base64");
1011:                            newMessageContent.addBodyPart(newPart);
1012:                        }
1013:                    }
1014:
1015:                    newMessage.setContent(newMessageContent);
1016:                    newMessage.setHeader("Content-Type", newMessageContent
1017:                            .getContentType());
1018:
1019:                    // first append the new message
1020:                    Message[] messages = { newMessage };
1021:
1022:                    draftsFolder.appendMessages(messages);
1023:
1024:                    // note the new id
1025:                    newId = ((MimeMessage) draftsFolder.getMessage(draftsFolder
1026:                            .getMessageCount())).getMessageID();
1027:
1028:                    // only now is it safe to delete the old message
1029:                    oldMessage.setFlag(Flags.Flag.DELETED, true);
1030:                    draftsFolder.expunge();
1031:
1032:                    // now it's safe to delete the files in upload dir, they're in the new multipart
1033:                    for (Iterator attachmentsIterator = attachments.iterator(); attachmentsIterator
1034:                            .hasNext();) {
1035:                        File attachment = new File(uploadDirectory,
1036:                                (String) attachmentsIterator.next());
1037:
1038:                        if (attachment.canWrite()) {
1039:                            attachment.delete();
1040:                        }
1041:                    }
1042:
1043:                    // MessageDO returnDO = getDOFromJavaMailMessage(newMessage, true);
1044:                    MessageDO returnDO = getDOFromJavaMailMessage(
1045:                            findJavaMailMessageByFolderMessageId(draftsFolder,
1046:                                    newId), true);
1047:                    draftsFolder.close(true);
1048:
1049:                    if (logger.isDebugEnabled()) {
1050:                        logger
1051:                                .debug("appendAttachments(MailSession, String, List) - end - return value = "
1052:                                        + returnDO);
1053:                    }
1054:
1055:                    return returnDO;
1056:                } catch (MessagingException em) {
1057:                    logger.error(
1058:                            "appendAttachments(MailSession, String, List)", em);
1059:
1060:                    throw new SystemException(em);
1061:                } catch (IOException eio) {
1062:                    logger
1063:                            .error(
1064:                                    "appendAttachments(MailSession, String, List)",
1065:                                    eio);
1066:
1067:                    throw new SystemException(eio);
1068:                } finally {
1069:                    try {
1070:                        store.close();
1071:                    } catch (MessagingException e) {
1072:                        logger.error(
1073:                                "Messaging exception on closing the store", e);
1074:                    }
1075:                }
1076:            }
1077:
1078:            /**
1079:             * <p>
1080:             * Check we have a valid mail server.
1081:             * </p>
1082:             *
1083:             * @throws NoMailServerException if there is no mail server.
1084:             */
1085:            private void checkMailServer() throws SystemException {
1086:                if (logger.isDebugEnabled()) {
1087:                    logger.debug("checkMailServer() - start");
1088:                }
1089:
1090:                if (mailServer == null) {
1091:                    logger.warn("No mail server found.");
1092:                    throw new NoMailServerException();
1093:                }
1094:
1095:                if (logger.isDebugEnabled()) {
1096:                    logger.debug("checkMailServer() - end");
1097:                }
1098:            }
1099:
1100:            /**
1101:             * <p>Helper method. Converts recipients from a collection of
1102:             * <code>PersonDO</code>, <code>UserDO</code> or <code>String<code>
1103:             * instances into an array of email addresses.</p>
1104:             * @param securitySession TODO
1105:             * @param addresses a <code>Collection</code> containing all of the email
1106:             *      addresses to convert. These can either be as <code>String<code>
1107:             *      instances or <code>PersonDO<code> instances, where the default
1108:             *      email address for each person is taken.
1109:             *
1110:             * @return array or <code>InternetAddress</code> instances for each of the
1111:             *      input parameters.
1112:             */
1113:            private InternetAddress[] convertAddresses(
1114:                    final SecuritySession securitySession,
1115:                    final Collection addresses) throws SystemException {
1116:                if (logger.isDebugEnabled()) {
1117:                    logger
1118:                            .debug("convertAddresses(SecuritySession securitySession = "
1119:                                    + securitySession
1120:                                    + ", Collection addresses = "
1121:                                    + addresses
1122:                                    + ") - start");
1123:                }
1124:
1125:                InternetAddress[] returnAddresses = new InternetAddress[addresses
1126:                        .size()];
1127:
1128:                // prerequisites check we got given something to convert
1129:                if (addresses == null) {
1130:                    if (logger.isDebugEnabled()) {
1131:                        logger
1132:                                .debug("convertAddresses(SecuritySession, Collection) - end - return value = "
1133:                                        + returnAddresses);
1134:                    }
1135:
1136:                    return returnAddresses;
1137:                }
1138:
1139:                int index = 0;
1140:
1141:                for (Iterator i = addresses.iterator(); i.hasNext();) {
1142:                    Object item = i.next();
1143:                    String addressString = null;
1144:
1145:                    if (PersonDO.class.isInstance(item)) {
1146:                        PersonDO person = (PersonDO) item;
1147:
1148:                        addressString = person.getEmailAddress();
1149:                    } else if (UserDO.class.isInstance(item)) {
1150:                        UserDO user = (UserDO) item;
1151:                        PersonDO person = addressBook.findPersonByUserName(
1152:                                securitySession, user.getName());
1153:
1154:                        // only set the address for users who are not disabled
1155:                        if (user.isEnabled()) {
1156:                            addressString = person.getEmailAddress();
1157:                        }
1158:                    } else {
1159:                        if (!String.class.isInstance(item)) {
1160:                            throw new SystemException(
1161:                                    "Cannot convert item of class '"
1162:                                            + item.getClass()
1163:                                            + "' into an email address.");
1164:                        }
1165:
1166:                        addressString = (String) item;
1167:                    }
1168:
1169:                    // ignore empty addresses
1170:                    if (!StringHandling.isNullOrEmpty(addressString)) {
1171:                        try {
1172:                            returnAddresses[index++] = new InternetAddress(
1173:                                    addressString);
1174:                        } catch (AddressException eAddress) {
1175:                            logger
1176:                                    .error(
1177:                                            "convertAddresses(SecuritySession, Collection)",
1178:                                            eAddress);
1179:
1180:                            throw new SystemException(
1181:                                    "ERROR in MailBean: cannot convert internet address '"
1182:                                            + addressString + "': "
1183:                                            + eAddress.getMessage(), eAddress);
1184:                        }
1185:                    }
1186:                }
1187:
1188:                if (logger.isDebugEnabled()) {
1189:                    logger
1190:                            .debug("convertAddresses(SecuritySession, Collection) - end - return value = "
1191:                                    + returnAddresses);
1192:                }
1193:
1194:                return returnAddresses;
1195:            }
1196:
1197:            /**
1198:             * <p>Copy the fields of an old <code>MimeMessage</code> to a new one.</p>
1199:             *
1200:             * <p><strong>Note:</strong> this method does not copy the content. Both the text
1201:             * and the message attachments (if any) must be set individually.</p>
1202:             *
1203:             * @param javaMailSession valid <em>JavaMail</em> session to which the user
1204:             *     should already be logged in.
1205:             * @param message a valid message filled out with values to copy.
1206:             * @return a valid <em>JavaMail</em> message ready with <code>recipients</code>,
1207:             *     <code>from</code> and <code>subject</code> fields matching
1208:             *     <code>message</code>.
1209:             */
1210:            private MimeMessage copyJavaMailMessage(
1211:                    final Session javaMailSession, final MimeMessage message)
1212:                    throws SystemException {
1213:                if (logger.isDebugEnabled()) {
1214:                    logger
1215:                            .debug("copyJavaMailMessage(Session javaMailSession = "
1216:                                    + javaMailSession
1217:                                    + ", MimeMessage message = "
1218:                                    + message
1219:                                    + ") - start");
1220:                }
1221:
1222:                MimeMessage newMessage = new MimeMessage(javaMailSession);
1223:
1224:                try {
1225:                    newMessage.setRecipients(Message.RecipientType.TO, message
1226:                            .getRecipients(Message.RecipientType.TO));
1227:                    newMessage.setRecipients(Message.RecipientType.CC, message
1228:                            .getRecipients(Message.RecipientType.CC));
1229:                    newMessage.setRecipients(Message.RecipientType.BCC, message
1230:                            .getRecipients(Message.RecipientType.BCC));
1231:                    newMessage.addFrom(message.getFrom());
1232:                    newMessage.setSubject(message.getSubject());
1233:                } catch (MessagingException e) {
1234:                    logger
1235:                            .error("copyJavaMailMessage(Session, MimeMessage)",
1236:                                    e);
1237:
1238:                    throw new SystemException(e);
1239:                }
1240:
1241:                if (logger.isDebugEnabled()) {
1242:                    logger
1243:                            .debug("copyJavaMailMessage(Session, MimeMessage) - end - return value = "
1244:                                    + newMessage);
1245:                }
1246:
1247:                return newMessage;
1248:            }
1249:
1250:            /**
1251:             * <p>Convert a <em>JavaMail</em> message to an <em>ivata groupware</em> dependent
1252:             * value object.</p>
1253:             *
1254:             * @param message a valid <em>JavaMail</em> message to be converted.
1255:             * @param includeContent <code>true</code> if the <code>text</code> and
1256:             *     attachments of the message should also be set, otherwise
1257:             *     <code>false</code>.
1258:             * @return message data object with the values filled out to match
1259:             *     the <em>JavaMail</em> object.
1260:             */
1261:            private MessageDO createDOFromJavaMailMessage(
1262:                    final MimeMessage message, final boolean includeContent)
1263:                    throws SystemException {
1264:                if (logger.isDebugEnabled()) {
1265:                    logger
1266:                            .debug("createDOFromJavaMailMessage(MimeMessage message = "
1267:                                    + message
1268:                                    + ", boolean includeContent = "
1269:                                    + includeContent + ") - start");
1270:                }
1271:
1272:                // right - we got here, so that means we have a message
1273:                MessageDO messageDO = new MessageDO();
1274:
1275:                try {
1276:                    //setting the fields of the MessageDO:
1277:                    if (message.getFolder() != null) {
1278:                        messageDO.setFolderName(message.getFolder().getName());
1279:                    }
1280:
1281:                    if (message.getReceivedDate() != null) {
1282:                        GregorianCalendar receivedDate = new GregorianCalendar();
1283:
1284:                        receivedDate.setTime(message.getReceivedDate());
1285:                        messageDO.setReceived(receivedDate);
1286:                    }
1287:
1288:                    if (message.getRecipients(Message.RecipientType.TO) != null) {
1289:                        messageDO
1290:                                .setRecipients(Arrays
1291:                                        .asList(toStringArray(message
1292:                                                .getRecipients(Message.RecipientType.TO))));
1293:                    }
1294:
1295:                    if (message.getRecipients(Message.RecipientType.CC) != null) {
1296:                        messageDO
1297:                                .setRecipientsCC(Arrays
1298:                                        .asList(toStringArray(message
1299:                                                .getRecipients(Message.RecipientType.CC))));
1300:                    }
1301:
1302:                    if (message.getRecipients(Message.RecipientType.BCC) != null) {
1303:                        messageDO
1304:                                .setRecipientsBCC(Arrays
1305:                                        .asList(toStringArray(message
1306:                                                .getRecipients(Message.RecipientType.BCC))));
1307:                    }
1308:
1309:                    if (message.getFrom() != null) {
1310:                        messageDO.setSenders(Arrays
1311:                                .asList(toStringArray(message.getFrom())));
1312:                    }
1313:
1314:                    if (message.getSentDate() != null) {
1315:                        GregorianCalendar sentDate = new GregorianCalendar();
1316:
1317:                        sentDate.setTime(message.getSentDate());
1318:                        messageDO.setSent(sentDate);
1319:                    }
1320:
1321:                    messageDO.setSize(new Integer(message.getSize()));
1322:                    messageDO.setSubject(message.getSubject());
1323:
1324:                    // message content handling - not always done for efficiency in lists
1325:                    if (includeContent) {
1326:                        // create new, empty List for our attachments
1327:                        messageDO.setAttachments(new Vector());
1328:
1329:                        // if it is a multipart message (has attachments), pass control to
1330:                        // recursive routine to go thro' them all
1331:                        if (message.isMimeType("multipart/*")) {
1332:                            addMultiPart(message, messageDO);
1333:
1334:                            // here are types with textual content
1335:                        } else if (message.isMimeType("text/*")
1336:                                || message.isMimeType("message/*")) {
1337:                            // if it is not multipart, we're just left with text or HTML
1338:                            if (message.isMimeType("text/HTML")) {
1339:                                // simple message with HTML content
1340:                                messageDO
1341:                                        .setFormat(FormatConstants.FORMAT_HTML);
1342:                            } else {
1343:                                // anything else with simple content should have text content
1344:                                messageDO
1345:                                        .setFormat(FormatConstants.FORMAT_TEXT);
1346:                            }
1347:
1348:                            messageDO.setText((String) message.getContent());
1349:
1350:                            // other (not correct?) types, as self-contained attachments...
1351:                        } else {
1352:                            messageDO.setFormat(FormatConstants.FORMAT_TEXT);
1353:                            messageDO.setText("");
1354:                            addPart(message, messageDO);
1355:                        }
1356:                    }
1357:
1358:                    messageDO.setMessageID(message.getMessageID());
1359:                } catch (MessagingException e) {
1360:                    logger
1361:                            .error(
1362:                                    "createDOFromJavaMailMessage(MimeMessage, boolean)",
1363:                                    e);
1364:
1365:                    throw new SystemException(e);
1366:                } catch (IOException e) {
1367:                    logger
1368:                            .error(
1369:                                    "createDOFromJavaMailMessage(MimeMessage, boolean)",
1370:                                    e);
1371:
1372:                    throw new SystemException(e);
1373:                }
1374:
1375:                if (logger.isDebugEnabled()) {
1376:                    logger
1377:                            .debug("createDOFromJavaMailMessage(MimeMessage, boolean) - end - return value = "
1378:                                    + messageDO);
1379:                }
1380:
1381:                return messageDO;
1382:            }
1383:
1384:            /**
1385:             * <p>Create a new mail folder.</p>
1386:             *
1387:             * @param mailSession valid mail session to which the user should already be
1388:             *     logged in.
1389:             * @param folderName the full path name of the folder to create.
1390:             *
1391:             * @ejb.interface-method
1392:             *      view-type = "remote"
1393:             */
1394:            public void createFolder(final MailSession mailSession,
1395:                    final String folderName) throws SystemException {
1396:                if (logger.isDebugEnabled()) {
1397:                    logger.debug("createFolder(MailSession mailSession = "
1398:                            + mailSession + ", String folderName = "
1399:                            + folderName + ") - start");
1400:                }
1401:
1402:                assert (mailSession != null);
1403:                checkDateFormatter(mailSession);
1404:
1405:                Store store = mailServer.connectStore(mailSession);
1406:
1407:                try {
1408:                    if (folderName == null) {
1409:                        throw new SystemException(
1410:                                "ERROR in MailBean.createFolder: folderName is null");
1411:                    }
1412:
1413:                    Folder folder = mailServer.getFolder(mailSession, store,
1414:                            folderName);
1415:
1416:                    if (!folder.create(Folder.HOLDS_MESSAGES)) {
1417:                        throw new SystemException(
1418:                                "ERROR in MailBean.createFolder: could not create folder '"
1419:                                        + folderName + "'");
1420:                    }
1421:                } catch (MessagingException e) {
1422:                    logger.error("createFolder(MailSession, String)", e);
1423:
1424:                    throw new SystemException(e);
1425:                } finally {
1426:                    try {
1427:                        store.close();
1428:                    } catch (MessagingException e) {
1429:                        logger.error(
1430:                                "Messaging exception on closing the store", e);
1431:                    }
1432:                }
1433:
1434:                if (logger.isDebugEnabled()) {
1435:                    logger.debug("createFolder(MailSession, String) - end");
1436:                }
1437:            }
1438:
1439:            /**
1440:             * <p>Helper method for <code>createThreadMethod</code>.</p>
1441:             *
1442:             * <p>Create a new message in the drafts folder from an existing one,
1443:             * resulting in a forwarded message.</p>
1444:             *
1445:             * @param mailSession valid mail session to which the user should already be
1446:             *     logged in.
1447:             * @param folderName the name of the folder to copy existing messages from.
1448:             * @param messageIds the unique identifier of the messages to be extended.
1449:             *     Can be <code>null</code> if a new message is requeested. When
1450:             *     forwarding, multiple address identifiers may be specified otherwise
1451:             *     (if editing a draft message or replying) only one message identifier
1452:             *     should be set in the list.
1453:             * @param thread set to one of the constants in {@link MailConstants
1454:             *     MailConstants}.
1455:             * @return populated message data object matching the required
1456:             *     message, and with the <code>id</code> set to the message in the
1457:             *     drafts folder.
1458:             */
1459:            private MimeMessage createForwardedMessage(
1460:                    final MailSession mailSession, final Folder folder,
1461:                    final List messageIds) throws SystemException {
1462:                if (logger.isDebugEnabled()) {
1463:                    logger
1464:                            .debug("createForwardedMessage(MailSession mailSession = "
1465:                                    + mailSession
1466:                                    + ", Folder folder = "
1467:                                    + folder
1468:                                    + ", List messageIds = "
1469:                                    + messageIds + ") - start");
1470:                }
1471:
1472:                checkDateFormatter(mailSession);
1473:
1474:                try {
1475:                    Session javaMailSession;
1476:
1477:                    try {
1478:                        javaMailSession = mailSession.getJavaMailSession();
1479:                    } catch (java.security.NoSuchProviderException e1) {
1480:                        logger
1481:                                .error(
1482:                                        "createForwardedMessage(MailSession, Folder, List)",
1483:                                        e1);
1484:
1485:                        throw new SystemException(e1);
1486:                    }
1487:
1488:                    UserDO user = mailSession.getUser();
1489:
1490:                    // if this is HTML, we'll need to store multipart data
1491:                    MessageTextParts messageTextParts = null;
1492:
1493:                    int format = FormatConstants.FORMAT_TEXT;
1494:
1495:                    for (Iterator i = messageIds.iterator(); i.hasNext();) {
1496:                        String id = (String) i.next();
1497:                        MimeMessage oldMessage = findJavaMailMessageByFolderMessageId(
1498:                                folder, id);
1499:
1500:                        // is this multipart?
1501:                        if (oldMessage.isMimeType("multipart/*")) {
1502:                            // try to find an HTML subpart
1503:                            messageTextParts = getMultiPartText(oldMessage);
1504:
1505:                            if (messageTextParts.HTMLPart != null) {
1506:                                format = FormatConstants.FORMAT_HTML;
1507:
1508:                                // no need to check any further...
1509:                                break;
1510:                            }
1511:                        }
1512:                    }
1513:
1514:                    // text header/prefix depends on the format
1515:                    String messageHeader;
1516:
1517:                    if (format == FormatConstants.FORMAT_HTML) {
1518:                        messageHeader = settings.getStringSetting(mailSession,
1519:                                "emailHeaderForwardHTML", user);
1520:                    } else {
1521:                        messageHeader = settings.getStringSetting(mailSession,
1522:                                "emailHeaderForwardText", user);
1523:                    }
1524:
1525:                    MimeMessage newMessage = new MimeMessage(javaMailSession);
1526:                    StringBuffer subject = new StringBuffer();
1527:                    String subjectPrefix = settings.getStringSetting(
1528:                            mailSession, "emailSubjectForwardPrefix", user);
1529:                    String subjectSeperator = settings.getStringSetting(
1530:                            mailSession, "emailSubjectForwardSeperator", user);
1531:
1532:                    subject.append(subjectPrefix);
1533:
1534:                    StringBuffer messageText = new StringBuffer();
1535:
1536:                    // we'll format the reply text, if it is text & this is HTML
1537:                    CharacterEntityFormat characterEntities = new CharacterEntityFormat();
1538:
1539:                    // go thro' all of the old ids again, this time to add the content
1540:                    int index = 0;
1541:
1542:                    for (Iterator i = messageIds.iterator(); i.hasNext(); ++index) {
1543:                        String id = (String) i.next();
1544:                        MimeMessage oldMessage = findJavaMailMessageByFolderMessageId(
1545:                                folder, id);
1546:
1547:                        // prepend Re: or Fwd: unless the previous subject already starts like this
1548:                        String oldSubject = StringHandling.getNotNull(
1549:                                oldMessage.getSubject(), getNullString());
1550:
1551:                        // if there is a fwd: prefix check this message doesn't start with
1552:                        // that
1553:                        if ((subjectPrefix != null)
1554:                                && (oldSubject.startsWith(subjectPrefix))) {
1555:                            oldSubject = oldSubject.substring(subjectPrefix
1556:                                    .length());
1557:                        }
1558:
1559:                        // if there is more than one forwarded message, append separator
1560:                        // between the subjects
1561:                        if ((index > 0) && !oldSubject.equals("")) {
1562:                            subject.append(subjectSeperator);
1563:                        }
1564:
1565:                        subject.append(oldSubject);
1566:
1567:                        // locate the multipart in the new message, for multiparts
1568:                        String oldMessageText = null;
1569:                        int oldFormat = FormatConstants.FORMAT_TEXT;
1570:
1571:                        if (oldMessage.isMimeType("multipart/*")) {
1572:                            // if there is an HTML text, use that
1573:                            if (messageTextParts.HTMLPart != null) {
1574:                                oldMessageText = (String) messageTextParts.HTMLPart
1575:                                        .getContent();
1576:                                oldFormat = FormatConstants.FORMAT_HTML;
1577:                            } else if (messageTextParts.textPart != null) {
1578:                                oldMessageText = (String) messageTextParts.textPart
1579:                                        .getContent();
1580:                            }
1581:                        } else {
1582:                            oldMessageText = (String) oldMessage.getContent();
1583:                        }
1584:
1585:                        // if we have to build the text with a prefix/header, do that
1586:                        if ((oldMessageText != null) && (messageHeader != null)) {
1587:                            messageText.append(formatMessageHeader(
1588:                                    messageHeader, oldMessage));
1589:                        }
1590:
1591:                        if (oldMessageText != null) {
1592:                            // we have to watch it if the old format wasn't HTML before
1593:                            if ((format == FormatConstants.FORMAT_HTML)
1594:                                    && !(oldFormat == FormatConstants.FORMAT_HTML)) {
1595:                                messageText.append("<pre>\n");
1596:                                oldMessageText = characterEntities
1597:                                        .format(oldMessageText);
1598:                            }
1599:
1600:                            messageText.append(oldMessageText);
1601:
1602:                            if ((format == FormatConstants.FORMAT_HTML)
1603:                                    && !(oldFormat == FormatConstants.FORMAT_HTML)) {
1604:                                messageText.append("\n</pre>\n");
1605:                            }
1606:                        }
1607:                    }
1608:
1609:                    if (format == FormatConstants.FORMAT_HTML) {
1610:                        // we want to work with copies of the original texts,
1611:                        // create a new HTML content multipart
1612:                        MimeMultipart newTextContent = createHTMLContent(messageText
1613:                                .toString());
1614:
1615:                        // set the multipart/alternative as the content of the base part
1616:                        newMessage.setContent(newTextContent);
1617:                        newMessage.setHeader("Content-Type", newTextContent
1618:                                .getContentType());
1619:
1620:                        // plain text replies and forwards are easier
1621:                    } else {
1622:                        newMessage.setContent(messageText.toString(),
1623:                                "text/plain");
1624:                    }
1625:
1626:                    if (logger.isDebugEnabled()) {
1627:                        logger
1628:                                .debug("createForwardedMessage(MailSession, Folder, List) - end - return value = "
1629:                                        + newMessage);
1630:                    }
1631:
1632:                    return newMessage;
1633:                } catch (MessagingException e) {
1634:                    logger
1635:                            .error(
1636:                                    "createForwardedMessage(MailSession, Folder, List)",
1637:                                    e);
1638:
1639:                    throw new SystemException(e);
1640:                } catch (IOException e) {
1641:                    logger
1642:                            .error(
1643:                                    "createForwardedMessage(MailSession, Folder, List)",
1644:                                    e);
1645:
1646:                    throw new SystemException(e);
1647:                }
1648:            }
1649:
1650:            /**
1651:             * <p>Create text content of a message, if the text is <code>HTML</code>
1652:             * format. This actually creates an alternative multipart type, and loads
1653:             * both the <code>HTML</code> content and the equivalent plain text.</p>
1654:             *
1655:             * @param hTMLText the new HTML text of the body content
1656:             * @exception MessagingException thrown by <code>MimeBodyPart.setContent</code>
1657:             * @return the newx content of the alternative multipart message content.
1658:             */
1659:            private MimeMultipart createHTMLContent(final String hTMLText)
1660:                    throws MessagingException {
1661:                if (logger.isDebugEnabled()) {
1662:                    logger.debug("createHTMLContent(String hTMLText = "
1663:                            + hTMLText + ") - start");
1664:                }
1665:
1666:                // HTML desired, the base part will be multipart/alternative
1667:                MimeMultipart newTextContent = new MimeMultipart("alternative");
1668:
1669:                // the richer format the last, so plain text first
1670:                MimeBodyPart mimePart = new MimeBodyPart();
1671:                SanitizerFormat sanitizer = new SanitizerFormat();
1672:
1673:                sanitizer.setSourceName("user input");
1674:                sanitizer.setTextOnly(true);
1675:                mimePart.setContent(sanitizer.format(hTMLText), "text/plain");
1676:                mimePart.setHeader("Content-Type", "text/plain");
1677:                newTextContent.addBodyPart(mimePart);
1678:
1679:                // TODO: this is not efficient - it parses the HTML tree twice :-(
1680:                // replace with HTMLParser calls directly
1681:                // the HTML part now
1682:                mimePart = new MimeBodyPart();
1683:                sanitizer.setTextOnly(false);
1684:                mimePart.setContent(sanitizer.format(hTMLText), "text/HTML");
1685:                mimePart.setHeader("Content-Type", "text/HTML");
1686:                newTextContent.addBodyPart(mimePart);
1687:
1688:                if (logger.isDebugEnabled()) {
1689:                    logger
1690:                            .debug("createHTMLContent(String) - end - return value = "
1691:                                    + newTextContent);
1692:                }
1693:
1694:                return newTextContent;
1695:            }
1696:
1697:            /**
1698:             * <p>Helper method for <code>createThreadMethod</code>.</p>
1699:             *
1700:             * <p>Create a new message in the drafts folder from an existing one,
1701:             * resulting in a message which replies to the original one.</p>
1702:             *
1703:             * @param mailSession valid mail session to which the user should already be
1704:             *     logged in.
1705:             * @param folderName the name of the folder to copy existing messages from.
1706:             * @param messageIds the unique identifier of the messages to be extended.
1707:             *     Can be <code>null</code> if a new message is requeested. When
1708:             *     forwarding, multiple address identifiers may be specified otherwise
1709:             *     (if editing a draft message or replying) only one message identifier
1710:             *     should be set in the list.
1711:             * @param thread set to one of the congstants in {@link MailConstants
1712:             *     MailConstants}.
1713:             * @return populated message data object matching the required
1714:             *     message, and with the <code>id</code> set to the message in the
1715:             *     drafts folder.
1716:             */
1717:            private MimeMessage createReplyMessage(
1718:                    final MailSession mailSession, final Folder folder,
1719:                    final String id, final Integer thread)
1720:                    throws SystemException {
1721:                if (logger.isDebugEnabled()) {
1722:                    logger
1723:                            .debug("createReplyMessage(MailSession mailSession = "
1724:                                    + mailSession
1725:                                    + ", Folder folder = "
1726:                                    + folder
1727:                                    + ", String id = "
1728:                                    + id
1729:                                    + ", Integer thread = "
1730:                                    + thread
1731:                                    + ") - start");
1732:                }
1733:
1734:                try {
1735:                    UserDO user = mailSession.getUser();
1736:                    MimeMessage oldMessage = this 
1737:                            .findJavaMailMessageByFolderMessageId(folder, id);
1738:
1739:                    // if this is HTML, we'll need to store multipart data
1740:                    MessageTextParts messageTextParts = null;
1741:
1742:                    // we will build the subject up using a prefix (possibly)
1743:                    StringBuffer subject = new StringBuffer();
1744:                    String subjectPrefix = null;
1745:
1746:                    // there may also be a text prefix (= header)
1747:                    StringBuffer messageText = new StringBuffer();
1748:                    String oldMessageText = null;
1749:                    String messageHeader = null;
1750:
1751:                    // we'll format the reply text
1752:                    HTMLFormatter formatter = new HTMLFormatter();
1753:
1754:                    // mail API methods for reply, replyall
1755:                    MimeMessage newMessage = (MimeMessage) oldMessage
1756:                            .reply(MailConstants.THREAD_REPLY_ALL
1757:                                    .equals(thread));
1758:
1759:                    // emailReplyIndent means '> '  (without the quotes)
1760:                    // note: HTML formatting might remove this below!!
1761:                    LineBreakFormat lineBreaks = new LineBreakFormat();
1762:
1763:                    lineBreaks.setPrepend(settings.getStringSetting(
1764:                            mailSession, "emailReplyIndent", user));
1765:                    formatter.add(lineBreaks);
1766:
1767:                    // first the subject prefix
1768:                    subjectPrefix = settings.getStringSetting(mailSession,
1769:                            "emailSubjectReplyPrefix", user);
1770:
1771:                    // for the reply we want to make a new multipart, if
1772:                    // this is an HTML mail
1773:                    if (oldMessage.isMimeType("multipart/*")) {
1774:                        messageHeader = settings.getStringSetting(mailSession,
1775:                                "emailHeaderReplyHTML", user);
1776:                        messageTextParts = getMultiPartText(oldMessage);
1777:                    } else {
1778:                        messageHeader = settings.getStringSetting(mailSession,
1779:                                "emailHeaderReplyText", user);
1780:                    }
1781:
1782:                    // prepend Re: unless the previous subject already starts like this
1783:                    String oldSubject = StringHandling.getNotNull(oldMessage
1784:                            .getSubject(), getNullString());
1785:
1786:                    if ((subjectPrefix != null)
1787:                            && (!oldSubject.startsWith(subjectPrefix))) {
1788:                        subject.append(subjectPrefix);
1789:                    }
1790:
1791:                    subject.append(oldSubject);
1792:                    newMessage.setSubject(subject.toString());
1793:
1794:                    // locate the multipart in the new message, for multiparts
1795:                    int format = FormatConstants.FORMAT_TEXT;
1796:
1797:                    if (oldMessage.isMimeType("multipart/*")) {
1798:                        // if there is an HTML text, use that
1799:                        if (messageTextParts.HTMLPart != null) {
1800:                            oldMessageText = (String) messageTextParts.HTMLPart
1801:                                    .getContent();
1802:                            format = FormatConstants.FORMAT_HTML;
1803:                        } else if (messageTextParts.textPart != null) {
1804:                            oldMessageText = (String) messageTextParts.textPart
1805:                                    .getContent();
1806:                        }
1807:                    } else {
1808:                        oldMessageText = (String) oldMessage.getContent();
1809:                    }
1810:
1811:                    // if we have to build the text with a prefix/header, do that
1812:                    if ((oldMessageText != null) && (messageHeader != null)) {
1813:                        messageText.append(formatMessageHeader(messageHeader,
1814:                                oldMessage));
1815:                    }
1816:
1817:                    if (oldMessageText != null) {
1818:                        messageText.append(oldMessageText);
1819:                    }
1820:
1821:                    if (format == FormatConstants.FORMAT_HTML) {
1822:                        // we want to work with copies of the original texts,
1823:                        // create a new HTML content multipart
1824:                        MimeMultipart newTextContent = createHTMLContent(messageText
1825:                                .toString());
1826:
1827:                        // set the multipart/alternative as the content of the base part
1828:                        newMessage.setContent(newTextContent);
1829:                        newMessage.setHeader("Content-Type", newTextContent
1830:                                .getContentType());
1831:
1832:                        // plain text replies and forwards are easier
1833:                    } else {
1834:                        newMessage.setContent(messageText.toString(),
1835:                                "text/plain");
1836:                    }
1837:
1838:                    if (logger.isDebugEnabled()) {
1839:                        logger
1840:                                .debug("createReplyMessage(MailSession, Folder, String, Integer) - end - return value = "
1841:                                        + newMessage);
1842:                    }
1843:
1844:                    return newMessage;
1845:                } catch (MessagingException e) {
1846:                    logger
1847:                            .error(
1848:                                    "createReplyMessage(MailSession, Folder, String, Integer)",
1849:                                    e);
1850:
1851:                    throw new SystemException(e);
1852:                } catch (IOException e) {
1853:                    logger
1854:                            .error(
1855:                                    "createReplyMessage(MailSession, Folder, String, Integer)",
1856:                                    e);
1857:
1858:                    throw new SystemException(e);
1859:                }
1860:            }
1861:
1862:            /**
1863:             * <p>Create a new message in the drafts folder from an existing one,
1864:             * based on a 'thread'. The thread indicates that the message is a:<br/>
1865:             * <ul>
1866:             *   <li>reply to all recipients of a previous message</li>
1867:             *   <li>reply to one recipient of a previous message</li>
1868:             *   <li>previous message(s) forwarded to new recipients</li>
1869:             *   <li>an existing (draft) message being altered for resending</li>
1870:             * </ul></p>
1871:             *
1872:             * <p>This new message in the drafts folder can then be used to store
1873:             * attachments or for reviewing before sending.</p>
1874:             *
1875:             * @param mailSession valid mail session to which the user should already be
1876:             *     logged in.
1877:             * @param folderName the name of the folder to copy existing messages from.
1878:             * @param messageIds the unique identifier of the messages to be extended.
1879:             *     Can be <code>null</code> if a new message is requeested. When
1880:             *     forwarding, multiple address identifiers may be specified otherwise
1881:             *     (if editing a draft message or replying) only one message identifier
1882:             *     should be set in the list.
1883:             * @param thread set to one of the constants in {@link MailConstants
1884:             *     MailConstants}.
1885:             * @return populated message data object matching the required
1886:             *     message, and with the <code>id</code> set to the message in the
1887:             *     drafts folder.
1888:             *
1889:             * @ejb.interface-method
1890:             *      view-type = "remote"
1891:             */
1892:            public MessageDO createThreadMessage(final MailSession mailSession,
1893:                    final String folderName, final List messageIds,
1894:                    final Integer thread) throws SystemException {
1895:                if (logger.isDebugEnabled()) {
1896:                    logger
1897:                            .debug("createThreadMessage(MailSession mailSession = "
1898:                                    + mailSession
1899:                                    + ", String folderName = "
1900:                                    + folderName
1901:                                    + ", List messageIds = "
1902:                                    + messageIds
1903:                                    + ", Integer thread = "
1904:                                    + thread + ") - start");
1905:                }
1906:
1907:                checkDateFormatter(mailSession);
1908:
1909:                MimeMessage newMessage = null;
1910:                MessageDO messageDO = null;
1911:                Store store = mailServer.connectStore(mailSession);
1912:
1913:                try {
1914:                    // check if everything's set to create based on thread
1915:                    if ((folderName == null) || (messageIds == null)
1916:                            || (messageIds.size() == 0) || (thread == null)) {
1917:                        throw new SystemException(
1918:                                "ERROR in MailBean.createThreadMessage: these parameters cannot be empty:"
1919:                                        + " folderName (specified: '"
1920:                                        + folderName
1921:                                        + "') messageIds (specified: '"
1922:                                        + messageIds
1923:                                        + "') thread (specified: '" + thread
1924:                                        + "').");
1925:                    }
1926:
1927:                    // prerequisite - check this is a forward thread if there are > 1 messages
1928:                    if ((messageIds.size() > 1)
1929:                            && !MailConstants.THREAD_FORWARD.equals(thread)) {
1930:                        throw new SystemException(
1931:                                "ERROR in MailBean: too many messages ("
1932:                                        + messageIds.size()
1933:                                        + ") in thread. Only 'forward' can have multiple messages.");
1934:                    }
1935:
1936:                    // create a new message appropriate to the thread type requested
1937:                    Folder folder = mailServer.getFolder(mailSession, store,
1938:                            folderName);
1939:
1940:                    folder.open(Folder.READ_ONLY);
1941:
1942:                    if (MailConstants.THREAD_FORWARD.equals(thread)) {
1943:                        newMessage = createForwardedMessage(mailSession,
1944:                                folder, messageIds);
1945:                    } else {
1946:                        String messageId = (String) messageIds.get(0);
1947:
1948:                        if (MailConstants.THREAD_DRAFT.equals(thread)) {
1949:                            MimeMessage oldMessage = this 
1950:                                    .findJavaMailMessageByFolderMessageId(
1951:                                            folder, messageId);
1952:                            newMessage = new MimeMessage(oldMessage);
1953:                        } else {
1954:                            newMessage = createReplyMessage(mailSession,
1955:                                    folder, messageId, thread);
1956:                        }
1957:                    }
1958:
1959:                    // now we should have the new message, let's put it to the drafts folder
1960:                    Folder draftsFolder = openDraftsFolder(store, mailSession);
1961:
1962:                    messageDO = getDOFromJavaMailMessage(newMessage, true);
1963:
1964:                    Message[] messages = { newMessage };
1965:
1966:                    draftsFolder.appendMessages(messages);
1967:                    messageDO.setFolderName(draftsFolder.getName());
1968:                    draftsFolder.close(true);
1969:                    folder.close(false);
1970:                } catch (MessagingException e) {
1971:                    logger
1972:                            .error(
1973:                                    "createThreadMessage(MailSession, String, List, Integer)",
1974:                                    e);
1975:
1976:                    throw new SystemException(e);
1977:                } finally {
1978:                    try {
1979:                        store.close();
1980:                    } catch (MessagingException e) {
1981:                        logger.error(
1982:                                "Messaging exception on closing the store", e);
1983:                    }
1984:                }
1985:
1986:                if (logger.isDebugEnabled()) {
1987:                    logger
1988:                            .debug("createThreadMessage(MailSession, String, List, Integer) - end - return value = "
1989:                                    + messageDO);
1990:                }
1991:
1992:                return messageDO;
1993:            }
1994:
1995:            /**
1996:             * <p>Delete a list of messages from the trash folder.</p>
1997:             *
1998:             * @param mailSession valid mail session to which the user should already be
1999:             *     logged in.
2000:             * @param ids the unique identifiers (<code>String</code> instances) of the
2001:             *     messages to be removed.
2002:             * @exception MessageNotFoundException if the folder doesn't exist, or there
2003:             *     is no matching mail in this folder.
2004:             *
2005:             * @ejb.interface-method
2006:             *      view-type = "remote"
2007:             */
2008:            public void deleteMessagesFromTrash(final MailSession mailSession,
2009:                    final List ids) throws SystemException {
2010:                if (logger.isDebugEnabled()) {
2011:                    logger
2012:                            .debug("deleteMessagesFromTrash(MailSession mailSession = "
2013:                                    + mailSession
2014:                                    + ", List ids = "
2015:                                    + ids
2016:                                    + ") - start");
2017:                }
2018:
2019:                checkDateFormatter(mailSession);
2020:
2021:                Store store = mailServer.connectStore(mailSession);
2022:
2023:                try {
2024:                    UserDO user = mailSession.getUser();
2025:                    Folder trashFolder = mailServer.getFolder(mailSession,
2026:                            store, settings.getStringSetting(mailSession,
2027:                                    "emailFolderTrash", user));
2028:
2029:                    trashFolder.open(Folder.READ_WRITE);
2030:
2031:                    // now mark all the original messages as deleted
2032:                    for (Iterator i = ids.iterator(); i.hasNext();) {
2033:                        String id = (String) i.next();
2034:                        MimeMessage message = findJavaMailMessageByFolderMessageId(
2035:                                trashFolder, id);
2036:
2037:                        message.setFlag(Flags.Flag.DELETED, true);
2038:                    }
2039:
2040:                    trashFolder.expunge();
2041:                    trashFolder.close(true);
2042:                } catch (MessagingException e) {
2043:                    logger.error("deleteMessagesFromTrash(MailSession, List)",
2044:                            e);
2045:
2046:                    throw new SystemException(e);
2047:                } finally {
2048:                    try {
2049:                        store.close();
2050:                    } catch (MessagingException e) {
2051:                        logger.error(
2052:                                "Messaging exception on closing the store", e);
2053:                    }
2054:                }
2055:
2056:                if (logger.isDebugEnabled()) {
2057:                    logger
2058:                            .debug("deleteMessagesFromTrash(MailSession, List) - end");
2059:                }
2060:            }
2061:
2062:            /**
2063:             * <p>Check whether or not a given folder pathname exists.</p>
2064:             *
2065:             * @param mailSession valid mail session to which the user should already be
2066:             *     logged in.
2067:             * @param folderName the full path name of the folder to check.
2068:             * @return <code>true</code> if the folder exists, otherwise <code>false</code>.
2069:             *
2070:             * @ejb.interface-method
2071:             *      view-type = "remote"
2072:             */
2073:            public boolean doesFolderExist(final MailSession mailSession,
2074:                    final String folderName) throws SystemException {
2075:                if (logger.isDebugEnabled()) {
2076:                    logger.debug("doesFolderExist(MailSession mailSession = "
2077:                            + mailSession + ", String folderName = "
2078:                            + folderName + ") - start");
2079:                }
2080:
2081:                assert (mailSession != null);
2082:                checkDateFormatter(mailSession);
2083:
2084:                boolean folderExists = false;
2085:
2086:                Store store = mailServer.connectStore(mailSession);
2087:
2088:                try {
2089:                    if (folderName == null) {
2090:                        throw new SystemException(
2091:                                "ERROR in MailBean.doesFolderExist: folderName is null");
2092:                    }
2093:
2094:                    Folder folder = mailServer.getFolder(mailSession, store,
2095:                            folderName);
2096:
2097:                    folderExists = folder.exists();
2098:                } catch (MessagingException e) {
2099:                    logger.error("doesFolderExist(MailSession, String)", e);
2100:
2101:                    throw new SystemException(e);
2102:                } finally {
2103:                    try {
2104:                        store.close();
2105:                    } catch (MessagingException e) {
2106:                        logger.error(
2107:                                "Messaging exception on closing the store", e);
2108:                    }
2109:                }
2110:
2111:                if (logger.isDebugEnabled()) {
2112:                    logger
2113:                            .debug("doesFolderExist(MailSession, String) - end - return value = "
2114:                                    + folderExists);
2115:                }
2116:
2117:                return folderExists;
2118:            }
2119:
2120:            /**
2121:             * <p>Locate the message in the folder given with the specified unique
2122:             * identifier.</p>
2123:             *
2124:             * @param folder folder to search for the message in.
2125:             * @param id the unique identifier of the message.
2126:             * @return the message in this folder with the id required, or
2127:             *     <code>null</code> if no such message exists.
2128:             * @exception MessageNotFoundException if the folder doesn't exist, or there
2129:             *     is no matching mail in this folder.
2130:             */
2131:            private MimeMessage findJavaMailMessageByFolderMessageId(
2132:                    final Folder folder, final String id)
2133:                    throws SystemException {
2134:                if (logger.isDebugEnabled()) {
2135:                    logger
2136:                            .debug("findJavaMailMessageByFolderMessageId(Folder folder = "
2137:                                    + folder
2138:                                    + ", String id = "
2139:                                    + id
2140:                                    + ") - start");
2141:                }
2142:
2143:                MimeMessage message = null;
2144:
2145:                // folder name used for errors only
2146:                String folderName = (folder == null) ? "[none]" : folder
2147:                        .getName();
2148:
2149:                try {
2150:                    // prerequisites, the id cannot be null, and folder must exist and be open
2151:                    if (StringHandling.isNullOrEmpty(id)) {
2152:                        throw new MessageNotFoundException(folderName, id,
2153:                                "you must specify a valid message id");
2154:                    } else if (folder == null) {
2155:                        throw new MessageNotFoundException(folderName, id,
2156:                                "you must specify a valid folder");
2157:                    } else if (!folder.exists()) {
2158:                        throw new MessageNotFoundException(folderName, id,
2159:                                folderName + " does not exist");
2160:                    } else if (!folder.isOpen()) {
2161:                        throw new MessageNotFoundException(folderName, id,
2162:                                folderName + " is not open");
2163:                    }
2164:
2165:                    // go thro' each one and compare ids - it's slow but it works
2166:                    // TODO: - examine ways to cache the mail folders
2167:                    for (int messageNumber = 1; messageNumber <= folder
2168:                            .getMessageCount(); ++messageNumber) {
2169:                        MimeMessage messageTest = (MimeMessage) folder
2170:                                .getMessage(messageNumber);
2171:
2172:                        if (id.equals(messageTest.getMessageID())) {
2173:                            message = messageTest;
2174:
2175:                            break;
2176:                        }
2177:                    }
2178:                } catch (FolderNotFoundException e) {
2179:                    logger
2180:                            .error(
2181:                                    "findJavaMailMessageByFolderMessageId(Folder, String)",
2182:                                    e);
2183:
2184:                    throw new MessageNotFoundException(folderName, id,
2185:                            "FolderNotFoundException looking for " + folderName
2186:                                    + ": " + e.getMessage(), e);
2187:                } catch (MessagingException e) {
2188:                    logger
2189:                            .error(
2190:                                    "findJavaMailMessageByFolderMessageId(Folder, String)",
2191:                                    e);
2192:
2193:                    throw new SystemException(e);
2194:                }
2195:
2196:                if (logger.isDebugEnabled()) {
2197:                    logger
2198:                            .debug("findJavaMailMessageByFolderMessageId(Folder, String) - end - return value = "
2199:                                    + message);
2200:                }
2201:
2202:                return message;
2203:            }
2204:
2205:            /**
2206:             * <p>This method retrieves the requested message and sets all the
2207:             * attributes of a MessageDO object for use on client side.</p>
2208:             *
2209:             * @param mailSession valid mail session to which the user should already be
2210:             *     logged in.
2211:             * @param folderName the name of the folder the message is located in.
2212:             * @param id the unique identifier of the message.
2213:             * @return a MessageDO instance filled up with the messages attributes,
2214:             *     except the contents of the attachments.
2215:             * @exception MessageNotFoundException if the folder doesn't exist, or there
2216:             *     is no matching mail in this folder.
2217:             *
2218:             * @ejb.interface-method
2219:             *      view-type = "remote"
2220:             */
2221:            public MessageDO findMessageByFolderMessageId(
2222:                    final MailSession mailSession, final String folderName,
2223:                    final String id) throws SystemException {
2224:                if (logger.isDebugEnabled()) {
2225:                    logger
2226:                            .debug("findMessageByFolderMessageId(MailSession mailSession = "
2227:                                    + mailSession
2228:                                    + ", String folderName = "
2229:                                    + folderName
2230:                                    + ", String id = "
2231:                                    + id
2232:                                    + ") - start");
2233:                }
2234:
2235:                checkDateFormatter(mailSession);
2236:
2237:                MessageDO messageDO = null;
2238:
2239:                Store store = mailServer.connectStore(mailSession);
2240:
2241:                try {
2242:                    if (folderName == null) {
2243:                        logger
2244:                                .error("MailBean.findMessageByFolderMessageId(): "
2245:                                        + "folderName is null.");
2246:
2247:                        return null;
2248:                    }
2249:
2250:                    // right, we now have to find the message using the folder name and the message number
2251:                    Folder folder = mailServer.getFolder(mailSession, store,
2252:                            folderName);
2253:
2254:                    // now open the folder
2255:                    folder.open(Folder.READ_ONLY);
2256:
2257:                    MimeMessage message = findJavaMailMessageByFolderMessageId(
2258:                            folder, id);
2259:
2260:                    // if some other program download the message -> we didn't find it so return null
2261:                    if (message != null) {
2262:                        messageDO = getDOFromJavaMailMessage(message, true);
2263:                    }
2264:
2265:                    folder.close(false);
2266:                } catch (MessagingException e) {
2267:                    logger
2268:                            .error(
2269:                                    "findMessageByFolderMessageId(MailSession, String, String)",
2270:                                    e);
2271:
2272:                    throw new SystemException(e);
2273:                } finally {
2274:                    try {
2275:                        store.close();
2276:                    } catch (MessagingException e) {
2277:                        logger.error(
2278:                                "Messaging exception on closing the store", e);
2279:                    }
2280:                }
2281:
2282:                if (logger.isDebugEnabled()) {
2283:                    logger
2284:                            .debug("findMessageByFolderMessageId(MailSession, String, String) - end - return value = "
2285:                                    + messageDO);
2286:                }
2287:
2288:                return messageDO;
2289:            }
2290:
2291:            /**
2292:             * <p>Used in the main folder index page, this method returns the contents
2293:             * of a folder as a <code>List</code> of
2294:             * <code>MessageDO</code> instances.</p>
2295:             *
2296:             * <p><strong>Note:</strong> for efficiency reasons, this method does not fill the
2297:             * text, format or attachment values of the returned <code>MessageDO</code>
2298:             * instance. For that, you must call
2299:             * {@link #findMessageByFolderMessageId findMessageByFolderMessageId}.</p>
2300:             *
2301:             * @param mailSession valid mail session to which the user should already be
2302:             *     logged in.
2303:             * @param folderName the name of the folder to list.
2304:             * @param sortBy the field to sort the returned list by. Set to one of the
2305:             *     <code>SORT_...</code> constants in {@link MailConstants MailConstants}.
2306:             * @param sortAscending if <code>true</code> then the messages are sorted in
2307:             *     ascending order, otherwise (<code>false</code>) they are descending.
2308:             * @return <code>List</code> of
2309:             *     <code>MessageDO</code> instances.
2310:             *
2311:             * @ejb.interface-method
2312:             *      view-type = "remote"
2313:             */
2314:            public List findMessagesInFolder(final MailSession mailSession,
2315:                    final String folderName, final Integer sortBy,
2316:                    final boolean sortAscending) throws SystemException {
2317:                if (logger.isDebugEnabled()) {
2318:                    logger
2319:                            .debug("findMessagesInFolder(MailSession mailSession = "
2320:                                    + mailSession
2321:                                    + ", String folderName = "
2322:                                    + folderName
2323:                                    + ", Integer sortBy = "
2324:                                    + sortBy
2325:                                    + ", boolean sortAscending = "
2326:                                    + sortAscending + ") - start");
2327:                }
2328:
2329:                checkDateFormatter(mailSession);
2330:
2331:                UserDO user = mailSession.getUser();
2332:                MessageDO messageDO;
2333:                Message[] messages;
2334:                int i;
2335:
2336:                // make a tree map to sort the items
2337:                ListColumnComparator comparator = new ListColumnComparator(
2338:                        sortAscending);
2339:                TreeMap map = new TreeMap(comparator);
2340:
2341:                // some types must be sorted numerically, rather than alphanumerically
2342:                comparator.setSortNumerically(MailConstants.SORT_RECEIVED
2343:                        .equals(sortBy)
2344:                        || MailConstants.SORT_SENT.equals(sortBy)
2345:                        || MailConstants.SORT_SIZE.equals(sortBy));
2346:
2347:                Store store = mailServer.connectStore(mailSession);
2348:
2349:                try {
2350:                    Folder folderProcessed = mailServer.getFolder(mailSession,
2351:                            store, folderName);
2352:
2353:                    // go thro and sort the contents
2354:                    String sentKey;
2355:                    StringBuffer key = new StringBuffer(32);
2356:                    GregorianCalendar received;
2357:                    GregorianCalendar sent;
2358:
2359:                    // first go thro' and make sure there is an ivata message id for each
2360:                    // message - only necessary for incoming mails where message id
2361:                    // might not be unique
2362:                    String inboxFolderName = settings.getStringSetting(
2363:                            mailSession, "emailFolderInbox", user);
2364:
2365:                    if (folderName.equalsIgnoreCase(inboxFolderName)) {
2366:                        folderProcessed.open(Folder.READ_WRITE);
2367:                        messages = folderProcessed.getMessages();
2368:
2369:                        int length = messages.length;
2370:
2371:                        for (i = 0; i < length; i++) {
2372:                            MimeMessage message = (MimeMessage) messages[i];
2373:
2374:                            // check there is an ivata message id in the message id string
2375:                            String messageId = message.getMessageID();
2376:
2377:                            if ((messageId == null)
2378:                                    || (messageId.indexOf("ivata-") == -1)) {
2379:                                // create a new message dependent value object
2380:                                MessageDO newMessage = createDOFromJavaMailMessage(
2381:                                        message, true);
2382:                                Integer newId = newMessage.getId();
2383:
2384:                                if (messageId == null) {
2385:                                    messageId = "";
2386:                                }
2387:
2388:                                messageId += ("ivata-" + newId);
2389:
2390:                                MimeMessage ivataMessage = new MimeMessage(
2391:                                        message);
2392:
2393:                                ivataMessage.setHeader("Message-ID", messageId);
2394:                                message.setFlag(Flags.Flag.DELETED, true);
2395:
2396:                                Message[] ivataMessages = { ivataMessage };
2397:
2398:                                folderProcessed.appendMessages(ivataMessages);
2399:                            }
2400:                        }
2401:
2402:                        // close the folder to save changes and re-open read only
2403:                        folderProcessed.close(true);
2404:                    }
2405:
2406:                    // now we can be sure-ish that message ids are unique -
2407:                    // the only way they can't be unique is if this is not the inbox
2408:                    // and JavaMail doesn't create a unique id when we make a new mail
2409:                    folderProcessed.open(Folder.READ_ONLY);
2410:                    messages = folderProcessed.getMessages();
2411:
2412:                    for (i = 0; i < messages.length; i++) {
2413:                        MimeMessage message = (MimeMessage) messages[i];
2414:
2415:                        messageDO = getDOFromJavaMailMessage(message, false);
2416:                        sent = messageDO.getSent();
2417:                        sentKey = ((sent == null) ? "" : new Long(sent
2418:                                .getTime().getTime()).toString());
2419:                        key.delete(0, key.capacity());
2420:
2421:                        // which field sorts is determined by the value of sortBy...
2422:                        if (MailConstants.SORT_FOLDER.equals(sortBy)) {
2423:                            key.append(StringHandling.getNotNull(messageDO
2424:                                    .getFolderName()));
2425:                        } else if (MailConstants.SORT_ID.equals(sortBy)) {
2426:                            key.append(StringHandling.getNotNull(messageDO
2427:                                    .getMessageID()));
2428:                        } else if (MailConstants.SORT_RECEIVED.equals(sortBy)) {
2429:                            received = messageDO.getReceived();
2430:                            key.append(((received == null) ? "" : new Long(
2431:                                    received.getTime().getTime()).toString()));
2432:                        } else if (MailConstants.SORT_RECIPIENTS.equals(sortBy)) {
2433:                            key.append(StringHandling.getNotNull(messageDO
2434:                                    .getRecipients()));
2435:                        } else if (MailConstants.SORT_RECIPIENTS_BCC
2436:                                .equals(sortBy)) {
2437:                            key.append(StringHandling.getNotNull(messageDO
2438:                                    .getRecipientsBCC()));
2439:                        } else if (MailConstants.SORT_RECIPIENTS_CC
2440:                                .equals(sortBy)) {
2441:                            key.append(StringHandling.getNotNull(messageDO
2442:                                    .getRecipientsCC()));
2443:                        } else if (MailConstants.SORT_SENDERS.equals(sortBy)) {
2444:                            key.append(StringHandling.getNotNull(messageDO
2445:                                    .getSenders()));
2446:                        } else if (MailConstants.SORT_SIZE.equals(sortBy)) {
2447:                            key.append(StringHandling.getNotNull(messageDO
2448:                                    .getSize()));
2449:                        } else if (!MailConstants.SORT_SENT.equals(sortBy)) {
2450:                            // default is subject - note sent date is appended below
2451:                            key.append(StringHandling.getNotNull(messageDO
2452:                                    .getSubject()));
2453:                        }
2454:
2455:                        // append the sent date to the key for secondary sorting
2456:                        key.append(sentKey);
2457:                        map.put(key.toString(), messageDO);
2458:                    }
2459:                } catch (NoSuchProviderException e) {
2460:                    logger
2461:                            .error(
2462:                                    "findMessagesInFolder(MailSession, String, Integer, boolean)",
2463:                                    e);
2464:
2465:                    throw new SystemException(e);
2466:                } catch (MessagingException e) {
2467:                    logger
2468:                            .error(
2469:                                    "findMessagesInFolder(MailSession, String, Integer, boolean)",
2470:                                    e);
2471:
2472:                    throw new SystemException(e);
2473:                } catch (SettingsDataTypeException e) {
2474:                    logger
2475:                            .error(
2476:                                    "findMessagesInFolder(MailSession, String, Integer, boolean)",
2477:                                    e);
2478:
2479:                    throw new SystemException(e);
2480:                } finally {
2481:                    try {
2482:                        store.close();
2483:                    } catch (MessagingException e) {
2484:                        logger.error(
2485:                                "Messaging exception on closing the store", e);
2486:                    }
2487:                }
2488:
2489:                List returnList = new Vector(map.values());
2490:
2491:                if (logger.isDebugEnabled()) {
2492:                    logger
2493:                            .debug("findMessagesInFolder(MailSession, String, Integer, boolean) - end - return value = "
2494:                                    + returnList);
2495:                }
2496:
2497:                return returnList;
2498:            }
2499:
2500:            /**
2501:             * <p>Format a header for a reply, or a forwarded message.</p>
2502:             *
2503:             * @param messageHeader the header to format.
2504:             * @param oldMessage the old message to read data from
2505:             * @return formatted message header.
2506:             */
2507:            private String formatMessageHeader(final String messageHeader,
2508:                    final MimeMessage oldMessage) throws SystemException {
2509:                if (logger.isDebugEnabled()) {
2510:                    logger.debug("formatMessageHeader(String messageHeader = "
2511:                            + messageHeader + ", MimeMessage oldMessage = "
2512:                            + oldMessage + ") - start");
2513:                }
2514:
2515:                Date date;
2516:                String oldSentDate;
2517:                String oldSubject;
2518:
2519:                try {
2520:                    date = oldMessage.getSentDate();
2521:                    oldSubject = StringHandling.getNotNull(oldMessage
2522:                            .getSubject(), getNullString());
2523:                } catch (MessagingException e) {
2524:                    logger.error("formatMessageHeader(String, MimeMessage)", e);
2525:
2526:                    throw new SystemException(e);
2527:                }
2528:
2529:                if (date == null) {
2530:                    oldSentDate = "";
2531:                } else {
2532:                    oldSentDate = dateFormatter.format(date);
2533:                }
2534:
2535:                EmailAddressFormatter emailFormatter = new EmailAddressFormatter();
2536:
2537:                try {
2538:                    // the same four arguments are used in the same order
2539:                    // for both reply & forward headers in resource files
2540:                    String oldSenders = StringHandling.getNotNull(
2541:                            emailFormatter.format(oldMessage.getFrom()),
2542:                            getNullString());
2543:                    String oldRecipients = StringHandling
2544:                            .getNotNull(
2545:                                    emailFormatter
2546:                                            .format(oldMessage
2547:                                                    .getRecipients(MimeMessage.RecipientType.TO)),
2548:                                    getNullString());
2549:                    Object[] arguments = { oldSenders, oldRecipients,
2550:                            oldSubject, oldSentDate };
2551:
2552:                    String returnString = MessageFormat.format(messageHeader,
2553:                            arguments);
2554:
2555:                    if (logger.isDebugEnabled()) {
2556:                        logger
2557:                                .debug("formatMessageHeader(String, MimeMessage) - end - return value = "
2558:                                        + returnString);
2559:                    }
2560:
2561:                    return returnString;
2562:                } catch (MessagingException e) {
2563:                    logger.error("formatMessageHeader(String, MimeMessage)", e);
2564:
2565:                    throw new SystemException(e);
2566:                }
2567:            }
2568:
2569:            /**
2570:             * <p>Retrieve an attachment's content and it's MimeType. This method is
2571:             * used to by the download servlet.</p>
2572:             *
2573:             * @param mailSession valid mail session to which the user should already be
2574:             *     logged in.
2575:             * @param folderName the name of the folder the message is located in.
2576:             * @param messageId the unique identifier of the message.
2577:             * @param attachmentId the unique identifier of the attachment.
2578:             * @return attachment data object containing attachment content
2579:             *     and mime type.
2580:             * @exception MessageNotFoundException if the folder doesn't exist, or there
2581:             *     is no matching mail in this folder.
2582:             *
2583:             * @ejb.interface-method
2584:             *      view-type = "remote"
2585:             */
2586:            public final FileContentDO getAttachment(
2587:                    final MailSession mailSession, final String folderName,
2588:                    final String messageId, final String attachmentId)
2589:                    throws SystemException {
2590:                if (logger.isDebugEnabled()) {
2591:                    logger.debug("getAttachment(MailSession mailSession = "
2592:                            + mailSession + ", String folderName = "
2593:                            + folderName + ", String messageId = " + messageId
2594:                            + ", String attachmentId = " + attachmentId
2595:                            + ") - start");
2596:                }
2597:
2598:                checkDateFormatter(mailSession);
2599:
2600:                FileContentDO attachmentDO = null;
2601:
2602:                Store store = mailServer.connectStore(mailSession);
2603:
2604:                try {
2605:                    // right, we now have to find the message using the folder name and the message number
2606:                    Folder folder = mailServer.getFolder(mailSession, store,
2607:                            folderName);
2608:
2609:                    // now open the folder
2610:                    folder.open(Folder.READ_ONLY);
2611:
2612:                    Message message = findJavaMailMessageByFolderMessageId(
2613:                            folder, messageId);
2614:                    InputStream inStream = null;
2615:                    String mimeType = null;
2616:
2617:                    // prerequisites - the message must be multipart, otherwise it can
2618:                    // be only a self-contained attachment
2619:                    if (message.isMimeType("multipart/*")) {
2620:                        MimeMultipart multiMessage = (MimeMultipart) message
2621:                                .getContent();
2622:                        MimeBodyPart subPart = getAttachment(multiMessage,
2623:                                attachmentId);
2624:                        inStream = subPart.getInputStream();
2625:                        mimeType = subPart.getContentType();
2626:                    } else {
2627:                        String withOutAngels = attachmentId.substring(1,
2628:                                attachmentId.length() - 1);
2629:
2630:                        if (((message.getFileName() != null) && attachmentId
2631:                                .equals(message.getFileName()))
2632:                                || ((message.getFileName() != null) && withOutAngels
2633:                                        .equals(message.getFileName()))) {
2634:                            inStream = message.getInputStream();
2635:                            mimeType = message.getContentType();
2636:                        }
2637:                    }
2638:
2639:                    if ((inStream != null) && (mimeType != null)) {
2640:                        int oneByte;
2641:
2642:                        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
2643:
2644:                        while ((oneByte = inStream.read()) != -1) {
2645:                            outStream.write(oneByte);
2646:                        }
2647:
2648:                        attachmentDO = new FileContentDO(
2649:                                new SerializedByteArray(outStream.toByteArray()),
2650:                                mimeType);
2651:                    }
2652:
2653:                    folder.close(false);
2654:                } catch (MessagingException e) {
2655:                    logger
2656:                            .error(
2657:                                    "getAttachment(MailSession, String, String, String)",
2658:                                    e);
2659:
2660:                    throw new SystemException(e);
2661:                } catch (IOException e) {
2662:                    logger
2663:                            .error(
2664:                                    "getAttachment(MailSession, String, String, String)",
2665:                                    e);
2666:
2667:                    throw new SystemException(e);
2668:                } finally {
2669:                    try {
2670:                        store.close();
2671:                    } catch (MessagingException e) {
2672:                        logger.error(
2673:                                "Messaging exception on closing the store", e);
2674:                    }
2675:                }
2676:
2677:                if (logger.isDebugEnabled()) {
2678:                    logger
2679:                            .debug("getAttachment(MailSession, String, String, String) - end - return value = "
2680:                                    + attachmentDO);
2681:                }
2682:
2683:                return attachmentDO;
2684:            }
2685:
2686:            /**
2687:             * <p>This method goes through multiparts recursively looking for a part
2688:             * with the given content id
2689:             * @param multiPart the <code>MimeMultipart</code> to search
2690:             * @param attachmentId the id of the wanted part
2691:             * @return <code>MimeBodyPart</code> with the wanted id or <code>null</code>
2692:             * when there wasn't such part in the given multipart
2693:             * @throws MessagingException
2694:             * @throws IOException
2695:             */
2696:            private MimeBodyPart getAttachment(final MimeMultipart multiPart,
2697:                    final String attachmentId) throws MessagingException,
2698:                    IOException {
2699:                if (logger.isDebugEnabled()) {
2700:                    logger.debug("getAttachment(MimeMultipart multiPart = "
2701:                            + multiPart + ", String attachmentId = "
2702:                            + attachmentId + ") - start");
2703:                }
2704:
2705:                MimeBodyPart attachment = (MimeBodyPart) multiPart
2706:                        .getBodyPart(attachmentId);
2707:
2708:                // if the attachment was not found in this level, it's more embedded...
2709:                if (attachment == null) {
2710:                    MimeBodyPart embeddedPart;
2711:
2712:                    for (int i = 0; i < multiPart.getCount(); i++) {
2713:                        embeddedPart = (MimeBodyPart) multiPart.getBodyPart(i);
2714:
2715:                        // go deeper to multiparts
2716:                        if (embeddedPart.isMimeType("multipart/*")) {
2717:                            // done when something returned from recursive call
2718:                            if ((attachment = getAttachment(
2719:                                    (MimeMultipart) embeddedPart.getContent(),
2720:                                    attachmentId)) != null) {
2721:                                break;
2722:                            }
2723:                        } else if ((embeddedPart.getFileName() != null)
2724:                                && (attachmentId.indexOf(embeddedPart
2725:                                        .getFileName()) != -1)) {
2726:                            attachment = embeddedPart;
2727:
2728:                            break;
2729:                        }
2730:                    }
2731:                }
2732:
2733:                if (logger.isDebugEnabled()) {
2734:                    logger
2735:                            .debug("getAttachment(MimeMultipart, String) - end - return value = "
2736:                                    + attachment);
2737:                }
2738:
2739:                return attachment;
2740:            }
2741:
2742:            /**
2743:             * <p>Convert a <em>JavaMail</em> message to an <em>ivata groupware</em> dependent
2744:             * value object.</p>
2745:             *
2746:             * @param message a valid <em>JavaMail</em> message to be converted.
2747:             * @param includeContent <code>true</code> if the <code>text</code> and
2748:             *     attachments of the message should also be set, otherwise
2749:             *     <code>false</code>.
2750:             * @return message data object with the values filled out to match
2751:             *     the <em>JavaMail</em> object.
2752:             */
2753:            private MessageDO getDOFromJavaMailMessage(
2754:                    final MimeMessage message, final boolean includeContent)
2755:                    throws SystemException {
2756:                if (logger.isDebugEnabled()) {
2757:                    logger
2758:                            .debug("getDOFromJavaMailMessage(MimeMessage message = "
2759:                                    + message
2760:                                    + ", boolean includeContent = "
2761:                                    + includeContent + ") - start");
2762:                }
2763:
2764:                // TODO: this is almost the same as the createDO... method just now
2765:                // right - we got here, so that means we have a message
2766:                MessageDO messageDO = new MessageDO();
2767:
2768:                try {
2769:                    //setting the fields of the MessageDO:
2770:                    if (message.getFolder() != null) {
2771:                        messageDO.setFolderName(message.getFolder().getName());
2772:                    }
2773:
2774:                    if (message.getReceivedDate() != null) {
2775:                        GregorianCalendar receivedDate = new GregorianCalendar();
2776:
2777:                        receivedDate.setTime(message.getReceivedDate());
2778:                        messageDO.setReceived(receivedDate);
2779:                    }
2780:
2781:                    if (message.getRecipients(Message.RecipientType.TO) != null) {
2782:                        messageDO
2783:                                .setRecipients(Arrays
2784:                                        .asList(toStringArray(message
2785:                                                .getRecipients(Message.RecipientType.TO))));
2786:                    }
2787:
2788:                    if (message.getRecipients(Message.RecipientType.CC) != null) {
2789:                        messageDO
2790:                                .setRecipientsCC(Arrays
2791:                                        .asList(toStringArray(message
2792:                                                .getRecipients(Message.RecipientType.CC))));
2793:                    }
2794:
2795:                    if (message.getRecipients(Message.RecipientType.BCC) != null) {
2796:                        messageDO
2797:                                .setRecipientsBCC(Arrays
2798:                                        .asList(toStringArray(message
2799:                                                .getRecipients(Message.RecipientType.BCC))));
2800:                    }
2801:
2802:                    if (message.getFrom() != null) {
2803:                        messageDO.setSenders(Arrays
2804:                                .asList(toStringArray(message.getFrom())));
2805:                    }
2806:
2807:                    if (message.getSentDate() != null) {
2808:                        GregorianCalendar sentDate = new GregorianCalendar();
2809:
2810:                        sentDate.setTime(message.getSentDate());
2811:                        messageDO.setSent(sentDate);
2812:                    }
2813:
2814:                    messageDO.setSize(new Integer(message.getSize()));
2815:                    messageDO.setSubject(message.getSubject());
2816:
2817:                    // message content handling - not always done for efficiency in lists
2818:                    if (includeContent) {
2819:                        // create new, empty List for our attachments
2820:                        messageDO.setAttachments(new Vector());
2821:
2822:                        // if it is a multipart message (has attachments), pass control to
2823:                        // recursive routine to go thro' them all
2824:                        if (message.isMimeType("multipart/*")) {
2825:                            addMultiPart(message, messageDO);
2826:
2827:                            // here are types with textual content
2828:                        } else if (message.isMimeType("text/*")
2829:                                || message.isMimeType("message/*")) {
2830:                            // if it is not multipart, we're just left with text or HTML
2831:                            if (message.isMimeType("text/HTML")) {
2832:                                // simple message with HTML content
2833:                                messageDO
2834:                                        .setFormat(FormatConstants.FORMAT_HTML);
2835:                            } else {
2836:                                // anything else with simple content should have text content
2837:                                messageDO
2838:                                        .setFormat(FormatConstants.FORMAT_TEXT);
2839:                            }
2840:
2841:                            messageDO.setText((String) message.getContent());
2842:
2843:                            // other (not correct?) types, as self-contained attachments...
2844:                        } else {
2845:                            messageDO.setFormat(FormatConstants.FORMAT_TEXT);
2846:                            messageDO.setText("");
2847:                            addPart(message, messageDO);
2848:                        }
2849:                    }
2850:
2851:                    messageDO.setMessageID(message.getMessageID());
2852:                } catch (MessagingException e) {
2853:                    logger
2854:                            .error(
2855:                                    "getDOFromJavaMailMessage(MimeMessage, boolean)",
2856:                                    e);
2857:
2858:                    throw new SystemException(e);
2859:                } catch (IOException e) {
2860:                    logger
2861:                            .error(
2862:                                    "getDOFromJavaMailMessage(MimeMessage, boolean)",
2863:                                    e);
2864:
2865:                    throw new SystemException(e);
2866:                }
2867:
2868:                if (logger.isDebugEnabled()) {
2869:                    logger
2870:                            .debug("getDOFromJavaMailMessage(MimeMessage, boolean) - end - return value = "
2871:                                    + messageDO);
2872:                }
2873:
2874:                return messageDO;
2875:            }
2876:
2877:            /**
2878:             * <p>Helper for <code>createThreadMessage</code>. This method processes a
2879:             * <em>Multipart</em> message or part and returns just the body parts
2880:             * representing text in either plain-text and/or <code>HTML</code> format.</p>
2881:             *
2882:             * @param message or part to be processed.
2883:             * @return the text of the message or part, it's plain text or <code>HTML</code>.
2884:             */
2885:            private MessageTextParts getMultiPartText(final Part message)
2886:                    throws SystemException {
2887:                if (logger.isDebugEnabled()) {
2888:                    logger.debug("getMultiPartText(Part message = " + message
2889:                            + ") - start");
2890:                }
2891:
2892:                MessageTextParts messageTextParts = new MessageTextParts();
2893:                MimeMultipart content;
2894:                MimeBodyPart subPart;
2895:                int i;
2896:
2897:                try {
2898:                    content = (MimeMultipart) message.getContent();
2899:
2900:                    //go through all the subParts
2901:                    for (i = 0; i < content.getCount(); i++) {
2902:                        subPart = (MimeBodyPart) content.getBodyPart(i);
2903:
2904:                        //when multipart/alternative, we are close to find what we want...
2905:                        if (message.isMimeType("multipart/alternative")) {
2906:                            if (subPart.isMimeType("text/plain")
2907:                                    && (messageTextParts.textPart == null)) {
2908:                                messageTextParts.textPart = subPart;
2909:                            } else if (subPart.isMimeType("text/HTML")
2910:                                    && (messageTextParts.HTMLPart == null)) {
2911:                                messageTextParts.HTMLPart = subPart;
2912:
2913:                                // usually the HTML part will come after the plain text
2914:                                // if the plain text is set, we're all finished
2915:                                if (messageTextParts.textPart != null) {
2916:                                    break;
2917:                                }
2918:                            }
2919:                        } else {
2920:                            // if this is not alternative multipart, recurse to get the text
2921:                            if (subPart.isMimeType("multipart/*")) {
2922:                                messageTextParts = getMultiPartText((Part) subPart);
2923:
2924:                                // when we are on a text subpart and text not set yet, this
2925:                                // should be it...
2926:                            } else if (subPart.isMimeType("text/plain")
2927:                                    && (messageTextParts.textPart == null)) {
2928:                                messageTextParts.textPart = subPart;
2929:                            } else if (subPart.isMimeType("text/HTML")
2930:                                    && (messageTextParts.HTMLPart == null)) {
2931:                                messageTextParts.HTMLPart = subPart;
2932:
2933:                                break;
2934:                            }
2935:                        }
2936:                    }
2937:                } catch (MessagingException e) {
2938:                    logger.error("getMultiPartText(Part)", e);
2939:
2940:                    throw new SystemException(e);
2941:                } catch (java.io.IOException e) {
2942:                    logger.error("getMultiPartText(Part)", e);
2943:
2944:                    throw new SystemException(e);
2945:                }
2946:
2947:                if (logger.isDebugEnabled()) {
2948:                    logger
2949:                            .debug("getMultiPartText(Part) - end - return value = "
2950:                                    + messageTextParts);
2951:                }
2952:
2953:                return messageTextParts;
2954:            }
2955:
2956:            /**
2957:             * <p>Generic string to use when some message text/subject is null.</p>
2958:             *
2959:             * @return replacement text to use when a message element is null.
2960:             */
2961:            private String getNullString() {
2962:                if (logger.isDebugEnabled()) {
2963:                    logger.debug("getNullString() - start");
2964:                }
2965:
2966:                // TODO: i18n
2967:                if (logger.isDebugEnabled()) {
2968:                    logger
2969:                            .debug("getNullString() - end - return value = [none]");
2970:                }
2971:
2972:                return "[none]";
2973:            }
2974:
2975:            /**
2976:             * <p>Retrieve all of the email aliases for the user provided, on the curent
2977:             * email server. The aliases returned each one containing just the 'user' (or
2978:             * 'local') part of the email address, before the '@' sign.</p>
2979:             *
2980:             * @param userName the name of the user for whom to retrieve the email aliases.
2981:             * @return a <code>Collection</code> of <code>String</code> instances containing
2982:             *     the local part of the different email aliases this user has. If the user
2983:             *     has no aliaes, an empty collection is returned.
2984:             */
2985:            public List getUserAliases(final SecuritySession securitySession,
2986:                    final String userName) throws SystemException {
2987:                if (logger.isDebugEnabled()) {
2988:                    logger
2989:                            .debug("getUserAliases(SecuritySession securitySession = "
2990:                                    + securitySession
2991:                                    + ", String userName = "
2992:                                    + userName + ") - start");
2993:                }
2994:
2995:                checkMailServer();
2996:                checkDateFormatter(securitySession);
2997:
2998:                List aliases = null;
2999:                aliases = mailServer.getUserAliases(securitySession, userName);
3000:
3001:                if (logger.isDebugEnabled()) {
3002:                    logger
3003:                            .debug("getUserAliases(SecuritySession, String) - end - return value = "
3004:                                    + aliases);
3005:                }
3006:
3007:                return aliases;
3008:            }
3009:
3010:            /**
3011:             * <p>Get the vacation message for the user provided.</p>
3012:             *
3013:             * <p>The vacation message is a text the user can set, which will be sent
3014:             * to all emails received at this address while the user is not present.</p>
3015:             *
3016:             * @param userName the name of the user for whom to get the vacation message.
3017:             * @return the vacation message text for this user. If the user has no
3018:             *     vacation message set, <code>null</code> is returned.
3019:             */
3020:            public final String getVacationMessage(
3021:                    final SecuritySession securitySession, final String userName)
3022:                    throws SystemException {
3023:                if (logger.isDebugEnabled()) {
3024:                    logger
3025:                            .debug("getVacationMessage(SecuritySession securitySession = "
3026:                                    + securitySession
3027:                                    + ", String userName = "
3028:                                    + userName + ") - start");
3029:                }
3030:
3031:                checkMailServer();
3032:                checkDateFormatter(securitySession);
3033:
3034:                String vacationMessage = null;
3035:                vacationMessage = mailServer.getVacationMessage(
3036:                        securitySession, userName);
3037:
3038:                if (logger.isDebugEnabled()) {
3039:                    logger
3040:                            .debug("getVacationMessage(SecuritySession, String) - end - return value = "
3041:                                    + vacationMessage);
3042:                }
3043:
3044:                return vacationMessage;
3045:            }
3046:
3047:            /**
3048:             * <p>Get the time the specified mail folder was last modified as a
3049:             * <code>long</code>. This can then be saved and compared to subsequent
3050:             * calls of this method to see if the folder has changed.</p>
3051:             *
3052:             * @param userName the name of the user for whom to locate the folder.
3053:             * @param folderName the name of the folder to locate.
3054:             * @return operating system specific timestamp indicating when the
3055:             * folder was last changed.
3056:             *
3057:             * @ejb.interface-method
3058:             *      view-type = "remote"
3059:             */
3060:            public final boolean hasNewMessages(
3061:                    final SecuritySession securitySession,
3062:                    final String userName, final String folderName)
3063:                    throws SystemException {
3064:                if (logger.isDebugEnabled()) {
3065:                    logger
3066:                            .debug("hasNewMessages(SecuritySession securitySession = "
3067:                                    + securitySession
3068:                                    + ", String userName = "
3069:                                    + userName
3070:                                    + ", String folderName = "
3071:                                    + folderName + ") - start");
3072:                }
3073:
3074:                checkMailServer();
3075:
3076:                if (userName == null) {
3077:                    throw new SystemException(
3078:                            "ERROR in MailBean.getFolderModified: userName is null.");
3079:                }
3080:
3081:                if (folderName == null) {
3082:                    throw new SystemException(
3083:                            "ERROR in MailBean.getFolderModified: folderName is null.");
3084:                }
3085:
3086:                boolean returnboolean = mailServer.hasNewMessages(
3087:                        securitySession, userName, folderName);
3088:
3089:                if (logger.isDebugEnabled()) {
3090:                    logger
3091:                            .debug("hasNewMessages(SecuritySession, String, String) - end - return value = "
3092:                                    + returnboolean);
3093:                }
3094:
3095:                return returnboolean;
3096:            }
3097:
3098:            /**
3099:             * <p>Login to the mail system. This method should be called before any other,
3100:             * to establish the mail session and store.</p>
3101:             *
3102:             * @param userName this user name is used to log into the remote system.
3103:             * @param password the clear-text password to log into the remote system.
3104:             * @throws GroupwareException if the person cannot log in.
3105:             * @return the mail session (class <code>Session</code>) in a
3106:             *    <code>SessionSerializer</code>.
3107:             *
3108:             * @ejb.interface-method
3109:             *      view-type = "local"
3110:             */
3111:            public MailSession login(final UserDO user, final String password)
3112:                    throws SystemException {
3113:                if (logger.isDebugEnabled()) {
3114:                    logger.debug("login(UserDO user = " + user
3115:                            + ", String password = " + password + ") - start");
3116:                }
3117:
3118:                checkMailServer();
3119:
3120:                MailSession returnMailSession = (MailSession) mailServer.login(
3121:                        user, password);
3122:
3123:                if (logger.isDebugEnabled()) {
3124:                    logger
3125:                            .debug("login(UserDO, String) - end - return value = "
3126:                                    + returnMailSession);
3127:                }
3128:
3129:                return returnMailSession;
3130:            }
3131:
3132:            /**
3133:             * <p>Move a list of messages from one folder to another.</p>
3134:             *
3135:             * @param mailSession valid mail session to which the user should already be
3136:             *     logged in.
3137:             * @param folderName the name of the folder the messages are currently located in.
3138:             * @param ids the unique identifiers (<code>String</code> instances) of the
3139:             *     messages to be moved.
3140:             * @param targetFolderName the name of the the folder the message will be moved
3141:             *     to.
3142:             * @exception MessageNotFoundException if the folder doesn't exist, or there
3143:             *     is no matching mail in this folder.
3144:             *
3145:             * @ejb.interface-method
3146:             *      view-type = "remote"
3147:             */
3148:            public void moveMessages(final MailSession mailSession,
3149:                    final String folderName, final List ids,
3150:                    final String targetFolderName) throws SystemException {
3151:                if (logger.isDebugEnabled()) {
3152:                    logger.debug("moveMessages(MailSession mailSession = "
3153:                            + mailSession + ", String folderName = "
3154:                            + folderName + ", List ids = " + ids
3155:                            + ", String targetFolderName = " + targetFolderName
3156:                            + ") - start");
3157:                }
3158:
3159:                Store store = mailServer.connectStore(mailSession);
3160:                checkDateFormatter(mailSession);
3161:
3162:                try {
3163:                    Folder folder = mailServer.getFolder(mailSession, store,
3164:                            folderName);
3165:
3166:                    folder.open(Folder.READ_WRITE);
3167:
3168:                    Folder targetFolder = mailServer.getFolder(mailSession,
3169:                            store, targetFolderName);
3170:
3171:                    if (!targetFolder.exists()) {
3172:                        targetFolder.create(Folder.HOLDS_MESSAGES);
3173:                    }
3174:
3175:                    targetFolder.open(Folder.READ_WRITE);
3176:
3177:                    List messages = new Vector();
3178:
3179:                    for (Iterator i = ids.iterator(); i.hasNext();) {
3180:                        String id = (String) i.next();
3181:                        MimeMessage message = findJavaMailMessageByFolderMessageId(
3182:                                folder, id);
3183:
3184:                        if (message == null) {
3185:                            logger
3186:                                    .error("MailBean.moveMessage:I couldn't find a message with id"
3187:                                            + id
3188:                                            + " in folder '"
3189:                                            + folder.getName() + "'");
3190:                        } else {
3191:                            messages.add(message);
3192:                        }
3193:                    }
3194:
3195:                    if (!messages.isEmpty()) {
3196:                        Message[] messageArray = {};
3197:
3198:                        messageArray = (Message[]) messages
3199:                                .toArray(messageArray);
3200:                        targetFolder.appendMessages(messageArray);
3201:                        targetFolder.close(false);
3202:
3203:                        // now mark all the original messages as deleted
3204:                        for (Iterator i = messages.iterator(); i.hasNext();) {
3205:                            Message message = (Message) i.next();
3206:
3207:                            message.setFlag(Flags.Flag.DELETED, true);
3208:                        }
3209:                    }
3210:
3211:                    folder.expunge();
3212:                    folder.close(true);
3213:                } catch (NoSuchProviderException e) {
3214:                    logger.error(
3215:                            "moveMessages(MailSession, String, List, String)",
3216:                            e);
3217:
3218:                    throw new SystemException(e);
3219:                } catch (MessagingException e) {
3220:                    logger.error(
3221:                            "moveMessages(MailSession, String, List, String)",
3222:                            e);
3223:
3224:                    throw new SystemException(e);
3225:                } finally {
3226:                    try {
3227:                        store.close();
3228:                    } catch (MessagingException e) {
3229:                        logger.error(
3230:                                "Messaging exception on closing the store", e);
3231:                    }
3232:                }
3233:
3234:                if (logger.isDebugEnabled()) {
3235:                    logger
3236:                            .debug("moveMessages(MailSession, String, List, String) - end");
3237:                }
3238:            }
3239:
3240:            /**
3241:             * <p>Helper method to get the name of the drafts folder from the settings,
3242:             * and then open the folder in read-write mode.</p>
3243:             *
3244:             * @param store connected store.
3245:             * @param javaMailSession valid <em>JavaMail</em> session to which the user
3246:             *     should already be logged in.
3247:             * @return opened drafts folder.
3248:             * @exception NoSuchProviderException thrown by
3249:             *      <code>Session.getStore</code> if there is no <em>IMAP</em> store
3250:             *      available.
3251:             * @exception MessagingException throw by <code>JavaMail</code> if there is
3252:             *      problem locating or opening the drafts folder.
3253:             * @exception SettingsDataTypeException if there is a problem accessing the
3254:             *      setting "emailFolderDrafts".
3255:             */
3256:            private Folder openDraftsFolder(final Store store,
3257:                    final MailSession mailSession) throws SystemException {
3258:                if (logger.isDebugEnabled()) {
3259:                    logger.debug("openDraftsFolder(Store store = " + store
3260:                            + ", MailSession mailSession = " + mailSession
3261:                            + ") - start");
3262:                }
3263:
3264:                assert (store != null);
3265:                assert (store.isConnected());
3266:                assert (mailSession != null);
3267:                checkDateFormatter(mailSession);
3268:
3269:                UserDO user = mailSession.getUser();
3270:
3271:                try {
3272:                    // first get the name of the drafts folder from the settings
3273:                    String draftsFolderName = settings.getStringSetting(
3274:                            mailSession, "emailFolderDrafts", user);
3275:                    Folder draftsFolder = mailServer.getFolder(mailSession,
3276:                            store, draftsFolderName);
3277:
3278:                    if (!(draftsFolder.exists() || draftsFolder
3279:                            .create(Folder.HOLDS_MESSAGES))) {
3280:                        throw new SystemException(
3281:                                "ERROR in MailBean.openDraftsFolder: Cannot create drafts folder.");
3282:                    }
3283:
3284:                    draftsFolder.open(Folder.READ_WRITE);
3285:
3286:                    if (logger.isDebugEnabled()) {
3287:                        logger
3288:                                .debug("openDraftsFolder(Store, MailSession) - end - return value = "
3289:                                        + draftsFolder);
3290:                    }
3291:
3292:                    return draftsFolder;
3293:                } catch (MessagingException e) {
3294:                    logger.error("openDraftsFolder(Store, MailSession)", e);
3295:
3296:                    throw new SystemException(e);
3297:                }
3298:            }
3299:
3300:            /**
3301:             * <p>Helper. This method calculates which of an old message's attachments
3302:             * are still required and sets the content of the new message on this
3303:             * basis.</p>
3304:             *
3305:             * <p>This method contains functionality from <code>setDO...</code> which
3306:             * has been split off to avoid a long <code>if...else</code>.</p>
3307:             *
3308:             * @param messageDO data object containing the latest changes from
3309:             *     client-side.
3310:             * @param newBasePart the new base part of the message with content
3311:             *     pre-prepared.
3312:             * @param oldMessage previous message retained from drafts folder.
3313:             * @param newMessage new message being constructed from the draft message and
3314:             *     messageDO changes.
3315:             */
3316:            private void retainAttachments(final MessageDO messageDO,
3317:                    final MimeBodyPart newBasePart,
3318:                    final MimeMessage oldMessage, final MimeMessage newMessage)
3319:                    throws SystemException {
3320:                if (logger.isDebugEnabled()) {
3321:                    logger.debug("retainAttachments(MessageDO messageDO = "
3322:                            + messageDO + ", MimeBodyPart newBasePart = "
3323:                            + newBasePart + ", MimeMessage oldMessage = "
3324:                            + oldMessage + ", MimeMessage newMessage = "
3325:                            + newMessage + ") - start");
3326:                }
3327:
3328:                try {
3329:                    MimeMultipart newMasterContent = new MimeMultipart();
3330:                    MimeMultipart oldContent = (MimeMultipart) oldMessage
3331:                            .getContent();
3332:
3333:                    // iterate through all the BodyParts (from 1 as it should be the base part)
3334:                    for (int j = 1; j < oldContent.getCount(); j++) {
3335:                        MimeBodyPart mimePart = new MimeBodyPart();
3336:
3337:                        mimePart = (MimeBodyPart) oldContent.getBodyPart(j);
3338:
3339:                        // if there are no attachments to remove, no need to find out if this one has to die
3340:                        if (messageDO.getAttachments() != null) {
3341:                            // look if this BodyPart is in the list of attachments to delete
3342:                            for (Iterator i = messageDO.getAttachments()
3343:                                    .iterator(); i.hasNext();) {
3344:                                String id = ((FileDO) i.next()).getName();
3345:
3346:                                // if it's an embedded message, try with messageId
3347:                                if ((mimePart.isMimeType("message/*") && (((MimeMessage) mimePart
3348:                                        .getContent()).getMessageID()
3349:                                        .equals(id)))
3350:                                        || ((mimePart.getFileName() != null) && mimePart
3351:                                                .getFileName().equals(id))
3352:                                        || ((mimePart.getContentID() != null) && mimePart
3353:                                                .getContentID().equals(id))) {
3354:                                    newMasterContent.addBodyPart(mimePart);
3355:                                }
3356:                            }
3357:                        }
3358:                    }
3359:
3360:                    // if there's at least one attachment left, it's worth to let it be multipart/mixed
3361:                    // and put the new base as the first part in this multipart
3362:                    if (newMasterContent.getCount() > 0) {
3363:                        newMasterContent.addBodyPart(newBasePart, 0);
3364:                        newMessage.setContent(newMasterContent);
3365:
3366:                        //if there are no attachments, only the base part will be there
3367:                    } else {
3368:                        if (messageDO.getFormat() == FormatConstants.FORMAT_HTML) {
3369:                            newMessage.setContent((MimeMultipart) newBasePart
3370:                                    .getContent());
3371:                            newMessage.setHeader("Content-Type", newBasePart
3372:                                    .getContentType());
3373:                        } else {
3374:                            newMessage.setText(messageDO.getText());
3375:                        }
3376:                    }
3377:                } catch (MessagingException e) {
3378:                    logger
3379:                            .error(
3380:                                    "retainAttachments(MessageDO, MimeBodyPart, MimeMessage, MimeMessage)",
3381:                                    e);
3382:
3383:                    throw new SystemException(e);
3384:                } catch (IOException e) {
3385:                    logger
3386:                            .error(
3387:                                    "retainAttachments(MessageDO, MimeBodyPart, MimeMessage, MimeMessage)",
3388:                                    e);
3389:
3390:                    throw new SystemException(e);
3391:                }
3392:
3393:                if (logger.isDebugEnabled()) {
3394:                    logger
3395:                            .debug("retainAttachments(MessageDO, MimeBodyPart, MimeMessage, MimeMessage) - end");
3396:                }
3397:            }
3398:
3399:            /**
3400:             * <p>Send a mime email message that is already composed. If <code>id</code>
3401:             * has been set in <code>messageDO</code> it is assumed to point to a
3402:             * message in the drafts folder. Attachments are copied from the message
3403:             * who match the contents of <code>getAttachmentIds</code>. (All other
3404:             * attachments are discarded.)</p>
3405:             *
3406:             * @param mailSession valid mail session to which the user should already be
3407:             *     logged in.
3408:             * @param messageDO data object containing full details of the
3409:             *     message to be sent.
3410:             *
3411:             * @ejb.interface-method
3412:             *      view-type = "remote"
3413:             */
3414:            public void send(final MailSession mailSession,
3415:                    final MessageDO messageDO) throws SystemException {
3416:                if (logger.isDebugEnabled()) {
3417:                    logger.debug("send(MailSession mailSession = "
3418:                            + mailSession + ", MessageDO messageDO = "
3419:                            + messageDO + ") - start");
3420:                }
3421:
3422:                checkDateFormatter(mailSession);
3423:
3424:                Store store = mailServer.connectStore(mailSession);
3425:
3426:                try {
3427:                    // if mail is disabled, just get out
3428:                    if (!settings.getBooleanSetting(mailSession, "emailEnable",
3429:                            null).booleanValue()) {
3430:                        if (logger.isDebugEnabled()) {
3431:                            logger.debug("send(MailSession, MessageDO) - end");
3432:                        }
3433:
3434:                        if (logger.isDebugEnabled()) {
3435:                            logger.debug("send(MailSession, MessageDO) - end");
3436:                        }
3437:
3438:                        return;
3439:                    }
3440:
3441:                    Session javaMailSession;
3442:
3443:                    try {
3444:                        javaMailSession = mailSession.getJavaMailSession();
3445:                    } catch (SecurityServerException e1) {
3446:                        logger.error("send(MailSession, MessageDO)", e1);
3447:
3448:                        throw new SystemException(e1);
3449:                    } catch (java.security.NoSuchProviderException e1) {
3450:                        logger.error("send(MailSession, MessageDO)", e1);
3451:
3452:                        throw new SystemException(e1);
3453:                    }
3454:
3455:                    // get the drafts folder in case we want to copy over an older mail
3456:                    Folder draftsFolder = openDraftsFolder(store, mailSession);
3457:                    MimeMessage newMessage = setDOToJavaMailMessage(
3458:                            javaMailSession, draftsFolder, messageDO);
3459:
3460:                    newMessage.setSentDate(Calendar.getInstance().getTime());
3461:
3462:                    // this bit actually sends the message
3463:                    Transport.send(newMessage);
3464:
3465:                    // add the message to the sent folder
3466:                    addToSentFolder(mailSession, newMessage);
3467:
3468:                    // only now can we delete/expunge the old mail from the drafts folder
3469:                    draftsFolder.expunge();
3470:                    draftsFolder.close(true);
3471:                } catch (MessagingException e) {
3472:                    logger.error("send(MailSession, MessageDO)", e);
3473:
3474:                    throw new SystemException(e);
3475:                } catch (SettingsDataTypeException e) {
3476:                    logger.error("send(MailSession, MessageDO)", e);
3477:
3478:                    throw new SystemException(e);
3479:                } finally {
3480:                    try {
3481:                        store.close();
3482:                    } catch (MessagingException e) {
3483:                        logger.error(
3484:                                "Messaging exception on closing the store", e);
3485:                    }
3486:                }
3487:
3488:                if (logger.isDebugEnabled()) {
3489:                    logger.debug("send(MailSession, MessageDO) - end");
3490:                }
3491:            }
3492:
3493:            /**
3494:             * <p>Send an mime email message without using a data object.</p>
3495:             *
3496:             * @param mailSession valid mail session to which the user should already be
3497:             *     logged in.
3498:             * @param fromAddress the address of the person sending the mail. This must
3499:             *    be formatted according to <a
3500:             *    href='http://www.faqs.org/rfcs/rfc822.HTML'>RFC822</a>.
3501:             * @param to recipients, a <code>Collection</code> containing instances of
3502:             *    <code>String</code> or <code>UserDO</code> or
3503:             *    <code>PersonDO</code>. A mixture of these types is allowed. If the
3504:             *    type of an instance is <code>String</code>, then it must be formatted
3505:             *    according to <a href='http://www.faqs.org/rfcs/rfc822.HTML'>RFC822</a>.
3506:             *    Otherwise, if the type is <code>PersonDO</code>, the method
3507:             *    <code>getEmailAddress</code> must return a valid address string for
3508:             *    this person.
3509:             * @param subject clear-text email subject field.
3510:             * @param content any valid email content type, as defined by
3511:             *    <code>MimeMessage</code>.
3512:             * @param contentType mime type for the <code>content</code> field, as
3513:             *    defined by <code>MimeMessage</code>.
3514:             * @param addToSentFolder if set to <code>true</code> then the mail is added
3515:             *    to the sent folder of the current email session.
3516:             * @ejb.interface-method
3517:             *      view-type = "both"
3518:             */
3519:            public void send(final MailSession mailSession,
3520:                    final String fromAddress, final Collection to,
3521:                    final String subject, Object content, String contentType,
3522:                    boolean addToSentFolder) throws SystemException {
3523:                if (logger.isDebugEnabled()) {
3524:                    logger.debug("send(MailSession mailSession = "
3525:                            + mailSession + ", String fromAddress = "
3526:                            + fromAddress + ", Collection to = " + to
3527:                            + ", String subject = " + subject
3528:                            + ", Object content = " + content
3529:                            + ", String contentType = " + contentType
3530:                            + ", boolean addToSentFolder = " + addToSentFolder
3531:                            + ") - start");
3532:                }
3533:
3534:                checkDateFormatter(mailSession);
3535:
3536:                try {
3537:                    try {
3538:                        // if mail is disabled, just get out
3539:                        if (!settings.getBooleanSetting(mailSession,
3540:                                "emailEnable", null).booleanValue()) {
3541:                            if (logger.isDebugEnabled()) {
3542:                                logger
3543:                                        .debug("send(MailSession, String, Collection, Collection, Collection, String, Object, String, boolean) - end");
3544:                            }
3545:
3546:                            if (logger.isDebugEnabled()) {
3547:                                logger
3548:                                        .debug("send(MailSession, String, Collection, Collection, Collection, String, Object, String, boolean) - end");
3549:                            }
3550:
3551:                            return;
3552:                        }
3553:                    } catch (SettingsDataTypeException e) {
3554:                        logger
3555:                                .error(
3556:                                        "send(MailSession, String, Collection, Collection, Collection, String, Object, String, boolean)",
3557:                                        e);
3558:
3559:                        throw new SystemException(e);
3560:                    }
3561:
3562:                    // see if we have a mail session
3563:                    Session javaMailSession;
3564:
3565:                    try {
3566:                        javaMailSession = mailSession.getJavaMailSession();
3567:                    } catch (AuthenticationFailedException e) {
3568:                        logger
3569:                                .error(
3570:                                        "send(MailSession, String, Collection, Collection, Collection, String, Object, String, boolean)",
3571:                                        e);
3572:
3573:                        throw new SystemException(
3574:                                "User is no longer authorized to use this server: "
3575:                                        + e.getMessage(), e);
3576:                    } catch (MessagingException e) {
3577:                        logger
3578:                                .error(
3579:                                        "send(MailSession, String, Collection, Collection, Collection, String, Object, String, boolean)",
3580:                                        e);
3581:
3582:                        throw new SystemException(e);
3583:                    } catch (SecurityServerException e) {
3584:                        logger
3585:                                .error(
3586:                                        "send(MailSession, String, Collection, Collection, Collection, String, Object, String, boolean)",
3587:                                        e);
3588:
3589:                        throw new SystemException(e);
3590:                    } catch (java.security.NoSuchProviderException e) {
3591:                        logger
3592:                                .error(
3593:                                        "send(MailSession, String, Collection, Collection, Collection, String, Object, String, boolean)",
3594:                                        e);
3595:
3596:                        throw new SystemException(e);
3597:                    }
3598:
3599:                    Store store = javaMailSession.getStore("imap");
3600:
3601:                    if (store == null) {
3602:                        throw new SystemException(
3603:                                "ERROR in MailBean: could not access the mail store");
3604:                    }
3605:
3606:                    MimeMessage message = new MimeMessage(javaMailSession);
3607:
3608:                    try {
3609:                        message.setFrom(new InternetAddress(fromAddress));
3610:                        message.setSubject(subject);
3611:                        message.setRecipients(MimeMessage.RecipientType.TO,
3612:                                convertAddresses(null, to));
3613:                        message.setContent(content, contentType);
3614:                        message.setSentDate(Calendar.getInstance().getTime());
3615:                    } catch (MessagingException e) {
3616:                        logger
3617:                                .error(
3618:                                        "send(MailSession, String, Collection, Collection, Collection, String, Object, String, boolean)",
3619:                                        e);
3620:
3621:                        throw new SystemException("Please check your input: "
3622:                                + e.getMessage(), e);
3623:                    }
3624:
3625:                    // send it
3626:                    try {
3627:                        Transport.send(message);
3628:                    } catch (MessagingException e) {
3629:                        logger
3630:                                .error(
3631:                                        "send(MailSession, String, Collection, Collection, Collection, String, Object, String, boolean)",
3632:                                        e);
3633:
3634:                        throw new SystemException(
3635:                                "The message could not be sent: "
3636:                                        + e.getMessage(), e);
3637:                    }
3638:
3639:                    // add the message to the sent items folder
3640:                    if (addToSentFolder) {
3641:                        addToSentFolder(mailSession, message);
3642:                    }
3643:                } catch (NoSuchProviderException e) {
3644:                    logger
3645:                            .error(
3646:                                    "send(MailSession, String, Collection, Collection, Collection, String, Object, String, boolean)",
3647:                                    e);
3648:
3649:                    throw new SystemException(e);
3650:                }
3651:
3652:                if (logger.isDebugEnabled()) {
3653:                    logger
3654:                            .debug("send(MailSession, String, Collection, Collection, Collection, String, Object, String, boolean) - end");
3655:                }
3656:            }
3657:
3658:            /**
3659:             * <p>Convert an <em>ivata groupware</em> message data object into a
3660:             * new <em>JavaMail</em> message that's ready to be sent.</p>
3661:             *
3662:             * <p><strong>Note:</strong> this method will look for an existing message (in the
3663:             * drafts folder) to use for the attachments. This is only done if the
3664:             * <code>MessageDO</code> has a valid <code>id</code>, and the drafts folder
3665:             * provided is not <code>null</code>. The previous mail is marked for
3666:             * deletion in the drafts folder, and this can be confirmed by expunging that
3667:             * folder and calling <code>close</code> with <code>true</code>. This is
3668:             * not done internally as it may depend on further actions (such as adding
3669:             * another mail successfully to the folder).</p>
3670:             *
3671:             * @param javaMailSession valid <em>JavaMail</em> session to which the user
3672:             *     should already be logged in.
3673:             * @param draftsFolder the opened drafts to retrieve a previous message from.
3674:             *     The previous message is identified by the <code>id</code> attribute
3675:             *     of the <code>messageDO</code>. If this parameter is <code>null</code>
3676:             *     then no previous mail is considered.
3677:             * @param messageDO a valid message data object with the values
3678:             *     filled out to match the <em>JavaMail</em> object which will be sent.
3679:             * @return a valid <em>JavaMail</em> message ready to be sent.
3680:             * @exception MessageNotFoundException if the folder doesn't exist, or there
3681:             *     is no matching mail in this folder.
3682:             */
3683:            private MimeMessage setDOToJavaMailMessage(
3684:                    final Session javaMailSession, final Folder draftsFolder,
3685:                    final MessageDO messageDO) throws SystemException {
3686:                if (logger.isDebugEnabled()) {
3687:                    logger
3688:                            .debug("setDOToJavaMailMessage(Session javaMailSession = "
3689:                                    + javaMailSession
3690:                                    + ", Folder draftsFolder = "
3691:                                    + draftsFolder
3692:                                    + ", MessageDO messageDO = "
3693:                                    + messageDO
3694:                                    + ") - start");
3695:                }
3696:
3697:                MimeMessage newMessage = new MimeMessage(javaMailSession);
3698:
3699:                try {
3700:                    newMessage.addFrom(convertAddresses(null, messageDO
3701:                            .getSenders()));
3702:                    newMessage.setSubject(messageDO.getSubject());
3703:                    newMessage.setRecipients(MimeMessage.RecipientType.TO,
3704:                            convertAddresses(null, messageDO.getRecipients()));
3705:
3706:                    if (messageDO.getRecipientsCC() != null) {
3707:                        newMessage.setRecipients(MimeMessage.RecipientType.CC,
3708:                                convertAddresses(null, messageDO
3709:                                        .getRecipientsCC()));
3710:                    }
3711:
3712:                    if (messageDO.getRecipientsBCC() != null) {
3713:                        newMessage.setRecipients(MimeMessage.RecipientType.BCC,
3714:                                convertAddresses(null, messageDO
3715:                                        .getRecipientsBCC()));
3716:                    }
3717:
3718:                    newMessage.setSentDate(Calendar.getInstance().getTime());
3719:
3720:                    // first try to identify any existing message we might be copying
3721:                    MimeMessage oldMessage = null;
3722:
3723:                    if ((messageDO.getMessageID() != null)
3724:                            && (draftsFolder != null)) {
3725:                        oldMessage = findJavaMailMessageByFolderMessageId(
3726:                                draftsFolder, messageDO.getMessageID());
3727:                    }
3728:
3729:                    MimeBodyPart newBasePart = new MimeBodyPart();
3730:
3731:                    // new base part is needed if the format is HTML or if there were
3732:                    // previous attachments we want to retain
3733:                    if (messageDO.getFormat() == FormatConstants.FORMAT_TEXT) {
3734:                        newBasePart.setText(messageDO.getText());
3735:                    } else {
3736:                        // HTML desired, the base part will be multipart/alternative
3737:                        MimeMultipart newTextContent = createHTMLContent(messageDO
3738:                                .getText());
3739:
3740:                        // set the multipart/alternative as the content of the base part
3741:                        newBasePart.setContent(newTextContent);
3742:                        newBasePart.setHeader("Content-Type", newTextContent
3743:                                .getContentType());
3744:                    }
3745:
3746:                    // if the message has no id, or if it had no attachments, then this
3747:                    // is a fresh new message -
3748:                    // no need to copy the contents of another message from the
3749:                    // drafts folder
3750:                    if ((oldMessage == null)
3751:                            || !oldMessage.isMimeType("multipart/mixed")
3752:                            || (messageDO.getAttachments() == null)) {
3753:                        // no attachments - simply decide whether we have HTML or just text
3754:                        if (messageDO.getFormat() == FormatConstants.FORMAT_HTML) {
3755:                            newMessage.setContent((MimeMultipart) newBasePart
3756:                                    .getContent());
3757:                            newMessage.setHeader("Content-Type", newBasePart
3758:                                    .getContentType());
3759:                        } else {
3760:                            newMessage.setText(messageDO.getText());
3761:                        }
3762:                    } else {
3763:                        // the old message had attachments - we need to examine which
3764:                        // of them are still required
3765:                        retainAttachments(messageDO, newBasePart, oldMessage,
3766:                                newMessage);
3767:
3768:                        // mark the old message for deletion
3769:                        oldMessage.setFlag(Flags.Flag.DELETED, true);
3770:                    }
3771:                } catch (StackOverflowError e) {
3772:                    logger
3773:                            .error(
3774:                                    "setDOToJavaMailMessage(Session, Folder, MessageDO)",
3775:                                    e);
3776:
3777:                    e.printStackTrace();
3778:                } catch (MessagingException e) {
3779:                    logger
3780:                            .error(
3781:                                    "setDOToJavaMailMessage(Session, Folder, MessageDO)",
3782:                                    e);
3783:
3784:                    throw new SystemException(e);
3785:                } catch (IOException e) {
3786:                    logger
3787:                            .error(
3788:                                    "setDOToJavaMailMessage(Session, Folder, MessageDO)",
3789:                                    e);
3790:
3791:                    throw new SystemException(e);
3792:                }
3793:
3794:                if (logger.isDebugEnabled()) {
3795:                    logger
3796:                            .debug("setDOToJavaMailMessage(Session, Folder, MessageDO) - end - return value = "
3797:                                    + newMessage);
3798:                }
3799:
3800:                return newMessage;
3801:            }
3802:
3803:            /**
3804:             * <p>Set all of the email aliases for the user provided, on the curent
3805:             * email server. Each alias in the collection should contain just the 'user'
3806:             * (or 'local') part of the email address, before the '@' sign.</p>
3807:             *
3808:             * @param userName the name of the user for whom to retrieve the email aliases.
3809:             * @param userAliases a <code>Collection</code> of <code>String</code>
3810:             *     instances containing the local part of the different email aliases
3811:             *     this user has. If the user has no aliaes, an empty collection should
3812:             *     be provided.
3813:             */
3814:            public final void setUserAliases(
3815:                    final SecuritySession securitySession,
3816:                    final String userName, final Collection userAliases)
3817:                    throws SystemException {
3818:                if (logger.isDebugEnabled()) {
3819:                    logger
3820:                            .debug("setUserAliases(SecuritySession securitySession = "
3821:                                    + securitySession
3822:                                    + ", String userName = "
3823:                                    + userName
3824:                                    + ", Collection userAliases = "
3825:                                    + userAliases + ") - start");
3826:                }
3827:
3828:                checkMailServer();
3829:                checkDateFormatter(securitySession);
3830:
3831:                // for the aliases which have been removed, remove the email addresses
3832:                List currentUserAliases = mailServer.getUserAliases(
3833:                        securitySession, userName);
3834:                PersonDO person = addressBook.findPersonByUserName(
3835:                        securitySession, userName);
3836:                UserDO user = person.getUser();
3837:                Set telecomAddresses = person.getTelecomAddresses();
3838:
3839:                String emailAddressHost = settings.getStringSetting(
3840:                        securitySession, "emailAddressHost", user);
3841:
3842:                // now go thro' the current aliases and see which ones have been removed
3843:                // to remove the associated email addresses, if any
3844:                Iterator currentUserAliasesIterator = currentUserAliases
3845:                        .iterator();
3846:                List removedEmailAddresses = new Vector();
3847:                List removedEmailTelecomAddresses = new Vector();
3848:                List currentEmailAddresses = new Vector();
3849:
3850:                while (currentUserAliasesIterator.hasNext()) {
3851:                    String alias = (String) currentUserAliasesIterator.next();
3852:
3853:                    if (!userAliases.contains(alias)) {
3854:                        removedEmailAddresses.add(alias + "@"
3855:                                + emailAddressHost);
3856:                    }
3857:                }
3858:
3859:                Iterator telecomAddressIterator = telecomAddresses.iterator();
3860:
3861:                while (telecomAddressIterator.hasNext()) {
3862:                    TelecomAddressDO this TelecomAddress = (TelecomAddressDO) telecomAddressIterator
3863:                            .next();
3864:
3865:                    if (this TelecomAddress.getType() == TelecomAddressConstants.TYPE_EMAIL) {
3866:                        if (removedEmailAddresses.contains(this TelecomAddress
3867:                                .getAddress())) {
3868:                            removedEmailTelecomAddresses
3869:                                    .add(this TelecomAddress);
3870:                        } else {
3871:                            currentEmailAddresses.add(this TelecomAddress
3872:                                    .getAddress());
3873:                        }
3874:                    }
3875:                }
3876:
3877:                int sizeBefore = telecomAddresses.size();
3878:
3879:                if (user.getId() != null) {
3880:                    addUserAliasEmailAddresses(securitySession, userName,
3881:                            userAliases, telecomAddresses, emailAddressHost);
3882:                }
3883:
3884:                int sizeAfter = telecomAddresses.size();
3885:
3886:                // if some email telecom addresses were removed or added, update the
3887:                // person
3888:                if ((removedEmailTelecomAddresses.size() > 0)
3889:                        || (sizeAfter != sizeBefore)) {
3890:                    Iterator removedEmailTelecomAddressesIterator = removedEmailTelecomAddresses
3891:                            .iterator();
3892:
3893:                    while (removedEmailTelecomAddressesIterator.hasNext()) {
3894:                        telecomAddresses
3895:                                .remove(removedEmailTelecomAddressesIterator
3896:                                        .next());
3897:                    }
3898:
3899:                    addressBook.amendPerson(securitySession, person);
3900:                }
3901:
3902:                // remove the user name itself from the aliases - if it is included
3903:                userAliases.remove(userName);
3904:
3905:                mailServer.setUserAliases(securitySession, userName,
3906:                        userAliases);
3907:
3908:                if (logger.isDebugEnabled()) {
3909:                    logger
3910:                            .debug("setUserAliases(SecuritySession, String, Collection) - end");
3911:                }
3912:            }
3913:
3914:            /**
3915:             * <p>Set the vacation message for the user provided.</p>
3916:             *
3917:             * <p>The vacation message is a text the user can set, which will be sent
3918:             * to all emails received at this address while the user is not present.</p>
3919:             *
3920:             * @param userName the name of the user for whom to get the vacation message.
3921:             * @param vacationMessage vacation message text for this user. If the user
3922:             *     has no vacation message set, set to <code>null</code>.
3923:             */
3924:            public final void setVacationMessage(
3925:                    final SecuritySession securitySession,
3926:                    final String userName, final String vacationMessage)
3927:                    throws SystemException {
3928:                if (logger.isDebugEnabled()) {
3929:                    logger
3930:                            .debug("setVacationMessage(SecuritySession securitySession = "
3931:                                    + securitySession
3932:                                    + ", String userName = "
3933:                                    + userName
3934:                                    + ", String vacationMessage = "
3935:                                    + vacationMessage + ") - start");
3936:                }
3937:
3938:                checkMailServer();
3939:                checkDateFormatter(securitySession);
3940:                mailServer.setVacationMessage(securitySession, userName, null);
3941:
3942:                if (logger.isDebugEnabled()) {
3943:                    logger
3944:                            .debug("setVacationMessage(SecuritySession, String, String) - end");
3945:                }
3946:            }
3947:
3948:            /**
3949:             * <p>Helper method to convert an array of <code>Address</code> instances to
3950:             * strings.</p>
3951:             *
3952:             * @param addresses non-<code>null</code> array of <code>Address</code>
3953:             *     instances to be converted to strings.
3954:             * @return array of strings representing the <code>Address.toString</code>
3955:             *     values.
3956:             */
3957:            private String[] toStringArray(final Address[] addresses) {
3958:                if (logger.isDebugEnabled()) {
3959:                    logger.debug("toStringArray(Address[] addresses = "
3960:                            + addresses + ") - start");
3961:                }
3962:
3963:                int i;
3964:                String[] retArray = new String[addresses.length];
3965:
3966:                for (i = 0; i < addresses.length; i++) {
3967:                    retArray[i] = addresses[i].toString();
3968:                }
3969:
3970:                if (logger.isDebugEnabled()) {
3971:                    logger
3972:                            .debug("toStringArray(Address[]) - end - return value = "
3973:                                    + retArray);
3974:                }
3975:
3976:                return retArray;
3977:            }
3978:
3979:            /**
3980:             * <p>Confirm all of the elements of the message are present and valid,
3981:             * before the message is sent.</p>
3982:             *
3983:             * @param messageDO data object to check for consistency and
3984:             *     completeness.
3985:             * @return a collection of validation errors if any of the
3986:             *     mandatory fields are missing, or if fields contain invalid values.
3987:             *
3988:             * @ejb.interface-method
3989:             *      view-type = "remote"
3990:             */
3991:            public ValidationErrors validate(
3992:                    final SecuritySession securitySession,
3993:                    final MessageDO messageDO) {
3994:                if (logger.isDebugEnabled()) {
3995:                    logger.debug("validate(SecuritySession securitySession = "
3996:                            + securitySession + ", MessageDO messageDO = "
3997:                            + messageDO + ") - start");
3998:                }
3999:
4000:                checkDateFormatter(securitySession);
4001:
4002:                ValidationErrors errors = new ValidationErrors();
4003:                Mask mask = maskFactory.getMask(MessageDO.class);
4004:
4005:                // recipients is mandatory
4006:                if ((messageDO.getRecipients() == null)
4007:                        || (messageDO.getRecipients().size() == 0)) {
4008:                    errors.add(new ValidationError("compose", Mail.BUNDLE_PATH,
4009:                            mask.getField("recipients"), "errors.required"));
4010:                }
4011:
4012:                // senders is mandatory
4013:                if ((messageDO.getSenders() == null)
4014:                        || (messageDO.getSenders().size() == 0)) {
4015:                    errors.add(new ValidationError("compose", Mail.BUNDLE_PATH,
4016:                            mask.getField("senders"), "errors.required"));
4017:                }
4018:
4019:                // subject is mandatory for now - see todo above
4020:                if ((messageDO == null)
4021:                        || StringHandling.isNullOrEmpty(messageDO.getSubject())) {
4022:                    errors.add(new ValidationError("compose", Mail.BUNDLE_PATH,
4023:                            mask.getField("subject"), "errors.required"));
4024:                }
4025:
4026:                // text is mandatory for now - see todo above
4027:                if ((messageDO == null)
4028:                        || StringHandling.isNullOrEmpty(messageDO.getText())) {
4029:                    errors.add(new ValidationError("compose", Mail.BUNDLE_PATH,
4030:                            mask.getField("text"), "errors.required"));
4031:                }
4032:
4033:                // validate email adresses
4034:                if (messageDO.getRecipients() != null) {
4035:                    for (Iterator i = messageDO.getRecipients().iterator(); i
4036:                            .hasNext();) {
4037:                        String currentRecipient = "";
4038:                        currentRecipient = (String) i.next();
4039:
4040:                        try {
4041:                            InternetAddress.parse(currentRecipient, true);
4042:                        } catch (AddressException e) {
4043:                            logger.error(
4044:                                    "validate(SecuritySession, MessageDO)", e);
4045:
4046:                            errors
4047:                                    .add(new ValidationError(
4048:                                            "",
4049:                                            Mail.BUNDLE_PATH,
4050:                                            mask.getField("to"),
4051:                                            "errors.mail.wrongEmailAddress",
4052:                                            Arrays
4053:                                                    .asList(new String[] { currentRecipient })));
4054:                        } catch (Exception e) {
4055:                            logger.error("Exception (" + e.getClass().getName()
4056:                                    + ") trying to parse internet address '"
4057:                                    + currentRecipient + "'", e);
4058:                            errors
4059:                                    .add(new ValidationError(
4060:                                            "",
4061:                                            Mail.BUNDLE_PATH,
4062:                                            mask.getField("bcc"),
4063:                                            "errors.mail.wrongEmailAddress",
4064:                                            Arrays
4065:                                                    .asList(new String[] { currentRecipient })));
4066:                        }
4067:                    }
4068:                }
4069:
4070:                if (messageDO.getRecipientsCC() != null) {
4071:                    for (Iterator i = messageDO.getRecipientsCC().iterator(); i
4072:                            .hasNext();) {
4073:                        String currentRecipientCC = "";
4074:                        currentRecipientCC = (String) i.next();
4075:
4076:                        try {
4077:                            InternetAddress.parse(currentRecipientCC, true);
4078:                        } catch (AddressException e) {
4079:                            logger.error(
4080:                                    "validate(SecuritySession, MessageDO)", e);
4081:
4082:                            errors
4083:                                    .add(new ValidationError(
4084:                                            "",
4085:                                            Mail.BUNDLE_PATH,
4086:                                            mask.getField("cc"),
4087:                                            "errors.mail.wrongEmailAddress",
4088:                                            Arrays
4089:                                                    .asList(new String[] { currentRecipientCC })));
4090:                        } catch (Exception e) {
4091:                            logger.error("Exception (" + e.getClass().getName()
4092:                                    + ") trying to parse internet address '"
4093:                                    + currentRecipientCC + "'", e);
4094:                            errors
4095:                                    .add(new ValidationError(
4096:                                            "",
4097:                                            Mail.BUNDLE_PATH,
4098:                                            mask.getField("bcc"),
4099:                                            "errors.mail.wrongEmailAddress",
4100:                                            Arrays
4101:                                                    .asList(new String[] { currentRecipientCC })));
4102:                        }
4103:                    }
4104:                }
4105:
4106:                if (messageDO.getRecipientsBCC() != null) {
4107:                    for (Iterator i = messageDO.getRecipientsBCC().iterator(); i
4108:                            .hasNext();) {
4109:                        String currentRecipientBCC = "";
4110:                        currentRecipientBCC = (String) i.next();
4111:
4112:                        try {
4113:                            InternetAddress.parse(currentRecipientBCC, true);
4114:                        } catch (AddressException e) {
4115:                            logger.error(
4116:                                    "validate(SecuritySession, MessageDO)", e);
4117:
4118:                            errors
4119:                                    .add(new ValidationError(
4120:                                            "",
4121:                                            Mail.BUNDLE_PATH,
4122:                                            mask.getField("bcc"),
4123:                                            "errors.mail.wrongEmailAddress",
4124:                                            Arrays
4125:                                                    .asList(new String[] { currentRecipientBCC })));
4126:                        } catch (Exception e) {
4127:                            logger.error("Exception (" + e.getClass().getName()
4128:                                    + ") trying to parse internet address '"
4129:                                    + currentRecipientBCC + "'", e);
4130:                            errors
4131:                                    .add(new ValidationError(
4132:                                            "",
4133:                                            Mail.BUNDLE_PATH,
4134:                                            mask.getField("bcc"),
4135:                                            "errors.mail.wrongEmailAddress",
4136:                                            Arrays
4137:                                                    .asList(new String[] { currentRecipientBCC })));
4138:                        }
4139:                    }
4140:                }
4141:
4142:                if (logger.isDebugEnabled()) {
4143:                    logger
4144:                            .debug("validate(SecuritySession, MessageDO) - end - return value = "
4145:                                    + errors);
4146:                }
4147:
4148:                return errors;
4149:            }
4150:
4151:            /**
4152:             * <p>Used to return both the HTML & plain text parts of  a message in
4153:             * <code>createThreadMessage</code>.</p>
4154:             */
4155:            private class MessageTextParts {
4156:                public MimeBodyPart HTMLPart = null;
4157:                public MimeBodyPart textPart = null;
4158:            }
4159:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.