Source Code Cross Referenced for James.java in  » Net » james-2.3.1 » org » apache » james » 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 » Net » james 2.3.1 » org.apache.james 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /****************************************************************
002:         * Licensed to the Apache Software Foundation (ASF) under one   *
003:         * or more contributor license agreements.  See the NOTICE file *
004:         * distributed with this work for additional information        *
005:         * regarding copyright ownership.  The ASF licenses this file   *
006:         * to you under the Apache License, Version 2.0 (the            *
007:         * "License"); you may not use this file except in compliance   *
008:         * with the License.  You may obtain a copy of the License at   *
009:         *                                                              *
010:         *   http://www.apache.org/licenses/LICENSE-2.0                 *
011:         *                                                              *
012:         * Unless required by applicable law or agreed to in writing,   *
013:         * software distributed under the License is distributed on an  *
014:         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
015:         * KIND, either express or implied.  See the License for the    *
016:         * specific language governing permissions and limitations      *
017:         * under the License.                                           *
018:         ****************************************************************/package org.apache.james;
019:
020:        import org.apache.avalon.cornerstone.services.store.Store;
021:        import org.apache.avalon.framework.activity.Initializable;
022:        import org.apache.avalon.framework.configuration.Configurable;
023:        import org.apache.avalon.framework.configuration.Configuration;
024:        import org.apache.avalon.framework.configuration.ConfigurationException;
025:        import org.apache.avalon.framework.configuration.DefaultConfiguration;
026:        import org.apache.avalon.framework.container.ContainerUtil;
027:        import org.apache.avalon.framework.context.Context;
028:        import org.apache.avalon.framework.context.Contextualizable;
029:        import org.apache.avalon.framework.context.DefaultContext;
030:        import org.apache.avalon.framework.logger.AbstractLogEnabled;
031:        import org.apache.avalon.framework.logger.Logger;
032:        import org.apache.avalon.framework.service.DefaultServiceManager;
033:        import org.apache.avalon.framework.service.ServiceException;
034:        import org.apache.avalon.framework.service.ServiceManager;
035:        import org.apache.avalon.framework.service.Serviceable;
036:        import org.apache.commons.collections.ReferenceMap;
037:
038:        import org.apache.james.context.AvalonContextUtilities;
039:        import org.apache.james.core.MailHeaders;
040:        import org.apache.james.core.MailImpl;
041:        import org.apache.james.core.MailetConfigImpl;
042:        import org.apache.james.services.DNSServer;
043:        import org.apache.james.services.MailRepository;
044:        import org.apache.james.services.MailServer;
045:        import org.apache.james.services.SpoolRepository;
046:        import org.apache.james.services.UsersRepository;
047:        import org.apache.james.services.UsersStore;
048:        import org.apache.james.transport.mailets.LocalDelivery;
049:        import org.apache.james.userrepository.DefaultJamesUser;
050:        import org.apache.mailet.Mail;
051:        import org.apache.mailet.MailAddress;
052:        import org.apache.mailet.Mailet;
053:        import org.apache.mailet.MailetContext;
054:        import org.apache.mailet.RFC2822Headers;
055:
056:        import javax.mail.Address;
057:        import javax.mail.Message;
058:        import javax.mail.MessagingException;
059:        import javax.mail.internet.InternetAddress;
060:        import javax.mail.internet.MimeMessage;
061:        import java.io.ByteArrayInputStream;
062:        import java.io.InputStream;
063:        import java.io.SequenceInputStream;
064:        import java.net.InetAddress;
065:        import java.net.UnknownHostException;
066:        import java.util.Collection;
067:        import java.util.Date;
068:        import java.util.Enumeration;
069:        import java.util.HashSet;
070:        import java.util.Hashtable;
071:        import java.util.Iterator;
072:        import java.util.Locale;
073:        import java.util.Map;
074:        import java.util.Vector;
075:
076:        /**
077:         * Core class for JAMES. Provides three primary services:
078:         * <br> 1) Instantiates resources, such as user repository, and protocol
079:         * handlers
080:         * <br> 2) Handles interactions between components
081:         * <br> 3) Provides container services for Mailets
082:         *
083:         *
084:         * @version This is $Revision: 494012 $
085:
086:         */
087:        public class James extends AbstractLogEnabled implements 
088:                Contextualizable, Serviceable, Configurable, JamesMBean,
089:                Initializable, MailServer, MailetContext {
090:
091:            /**
092:             * The software name and version
093:             */
094:            private final static String SOFTWARE_NAME_VERSION = Constants.SOFTWARE_NAME
095:                    + " " + Constants.SOFTWARE_VERSION;
096:
097:            /**
098:             * The component manager used both internally by James and by Mailets.
099:             */
100:            private DefaultServiceManager compMgr; //Components shared
101:
102:            /**
103:             * TODO: Investigate what this is supposed to do.  Looks like it
104:             *       was supposed to be the Mailet context.
105:             */
106:            private DefaultContext context;
107:
108:            /**
109:             * The top level configuration object for this server.
110:             */
111:            private Configuration conf;
112:
113:            /**
114:             * The logger used by the Mailet API.
115:             */
116:            private Logger mailetLogger = null;
117:
118:            /**
119:             * The mail store containing the inbox repository and the spool.
120:             */
121:            private Store store;
122:
123:            /**
124:             * The store containing the local user repository.
125:             */
126:            private UsersStore usersStore;
127:
128:            /**
129:             * The spool used for processing mail handled by this server.
130:             */
131:            private SpoolRepository spool;
132:
133:            /**
134:             * The root URL used to get mailboxes from the repository
135:             */
136:            private String inboxRootURL;
137:
138:            /**
139:             * The user repository for this mail server.  Contains all the users with inboxes
140:             * on this server.
141:             */
142:            private UsersRepository localusers;
143:
144:            /**
145:             * The collection of domain/server names for which this instance of James
146:             * will receive and process mail.
147:             */
148:            private Collection serverNames;
149:
150:            /**
151:             * Whether to ignore case when looking up user names on this server
152:             */
153:            private boolean ignoreCase;
154:
155:            /**
156:             * The number of mails generated.  Access needs to be synchronized for
157:             * thread safety and to ensure that all threads see the latest value.
158:             */
159:            private static long count;
160:
161:            /**
162:             * The address of the postmaster for this server
163:             */
164:            private MailAddress postmaster;
165:
166:            /**
167:             * A map used to store mailboxes and reduce the cost of lookup of individual
168:             * mailboxes.
169:             */
170:            private Map mailboxes; //Not to be shared!
171:
172:            /**
173:             * A hash table of server attributes
174:             * These are the MailetContext attributes
175:             */
176:            private Hashtable attributes = new Hashtable();
177:
178:            /**
179:             * The Avalon context used by the instance
180:             */
181:            protected Context myContext;
182:
183:            /**
184:             * Currently used by storeMail to avoid code duplication (we moved store logic to that mailet).
185:             * TODO We should remove this and its initialization when we remove storeMail method.
186:             */
187:            protected Mailet localDeliveryMailet;
188:
189:            /**
190:             * @see org.apache.avalon.framework.context.Contextualizable#contextualize(Context)
191:             */
192:            public void contextualize(final Context context) {
193:                this .myContext = context;
194:            }
195:
196:            /**
197:             * @see org.apache.avalon.framework.service.Serviceable#service(ServiceManager)
198:             */
199:            public void service(ServiceManager comp) {
200:                compMgr = new DefaultServiceManager(comp);
201:                mailboxes = new ReferenceMap();
202:            }
203:
204:            /**
205:             * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
206:             */
207:            public void configure(Configuration conf) {
208:                this .conf = conf;
209:            }
210:
211:            /**
212:             * @see org.apache.avalon.framework.activity.Initializable#initialize()
213:             */
214:            public void initialize() throws Exception {
215:
216:                getLogger().info("JAMES init...");
217:
218:                // TODO: This should retrieve a more specific named thread pool from
219:                // Context that is set up in server.xml
220:                try {
221:                    store = (Store) compMgr.lookup(Store.ROLE);
222:                } catch (Exception e) {
223:                    if (getLogger().isWarnEnabled()) {
224:                        getLogger().warn("Can't get Store: " + e);
225:                    }
226:                }
227:                if (getLogger().isDebugEnabled()) {
228:                    getLogger().debug("Using Store: " + store.toString());
229:                }
230:                try {
231:                    spool = (SpoolRepository) compMgr
232:                            .lookup(SpoolRepository.ROLE);
233:                } catch (Exception e) {
234:                    if (getLogger().isWarnEnabled()) {
235:                        getLogger().warn("Can't get spoolRepository: " + e);
236:                    }
237:                }
238:                if (getLogger().isDebugEnabled()) {
239:                    getLogger().debug(
240:                            "Using SpoolRepository: " + spool.toString());
241:                }
242:                try {
243:                    usersStore = (UsersStore) compMgr.lookup(UsersStore.ROLE);
244:                } catch (Exception e) {
245:                    if (getLogger().isWarnEnabled()) {
246:                        getLogger().warn("Can't get Store: " + e);
247:                    }
248:                }
249:                if (getLogger().isDebugEnabled()) {
250:                    getLogger().debug(
251:                            "Using UsersStore: " + usersStore.toString());
252:                }
253:
254:                String hostName = null;
255:                try {
256:                    hostName = InetAddress.getLocalHost().getHostName();
257:                } catch (UnknownHostException ue) {
258:                    hostName = "localhost";
259:                }
260:
261:                context = new DefaultContext();
262:                context.put("HostName", hostName);
263:                getLogger().info("Local host is: " + hostName);
264:
265:                // Get the domains and hosts served by this instance
266:                serverNames = new HashSet();
267:                Configuration serverConf = conf.getChild("servernames");
268:                if (serverConf.getAttributeAsBoolean("autodetect")
269:                        && (!hostName.equals("localhost"))) {
270:                    serverNames.add(hostName.toLowerCase(Locale.US));
271:                }
272:
273:                final Configuration[] serverNameConfs = conf.getChild(
274:                        "servernames").getChildren("servername");
275:                for (int i = 0; i < serverNameConfs.length; i++) {
276:                    serverNames.add(serverNameConfs[i].getValue().toLowerCase(
277:                            Locale.US));
278:
279:                    if (serverConf.getAttributeAsBoolean("autodetectIP", true)) {
280:                        try {
281:                            /* This adds the IP address(es) for each host to support
282:                             * support <user@address-literal> - RFC 2821, sec 4.1.3.
283:                             * It might be proper to use the actual IP addresses
284:                             * available on this server, but we can't do that
285:                             * without NetworkInterface from JDK 1.4.  Because of
286:                             * Virtual Hosting considerations, we may need to modify
287:                             * this to keep hostname and IP associated, rather than
288:                             * just both in the set.
289:                             */
290:                            InetAddress[] addrs = InetAddress
291:                                    .getAllByName(serverNameConfs[i].getValue());
292:                            for (int j = 0; j < addrs.length; j++) {
293:                                serverNames.add(addrs[j].getHostAddress());
294:                            }
295:                        } catch (Exception genericException) {
296:                            getLogger().error(
297:                                    "Cannot get IP address(es) for "
298:                                            + serverNameConfs[i].getValue());
299:                        }
300:                    }
301:                }
302:                if (serverNames.isEmpty()) {
303:                    throw new ConfigurationException(
304:                            "Fatal configuration error: no servernames specified!");
305:                }
306:
307:                if (getLogger().isInfoEnabled()) {
308:                    for (Iterator i = serverNames.iterator(); i.hasNext();) {
309:                        getLogger().info("Handling mail for: " + i.next());
310:                    }
311:                }
312:
313:                String defaultDomain = (String) serverNames.iterator().next();
314:                context.put(Constants.DEFAULT_DOMAIN, defaultDomain);
315:                attributes.put(Constants.DEFAULT_DOMAIN, defaultDomain);
316:
317:                // Get postmaster
318:                String postMasterAddress = conf.getChild("postmaster")
319:                        .getValue("postmaster").toLowerCase(Locale.US);
320:                // if there is no @domain part, then add the first one from the
321:                // list of supported domains that isn't localhost.  If that
322:                // doesn't work, use the hostname, even if it is localhost.
323:                if (postMasterAddress.indexOf('@') < 0) {
324:                    String domainName = null; // the domain to use
325:                    // loop through candidate domains until we find one or exhaust the list
326:                    for (int i = 0; domainName == null
327:                            && i < serverNameConfs.length; i++) {
328:                        String serverName = serverNameConfs[i].getValue()
329:                                .toLowerCase(Locale.US);
330:                        if (!("localhost".equals(serverName))) {
331:                            domainName = serverName; // ok, not localhost, so use it
332:                        }
333:                    }
334:                    // if we found a suitable domain, use it.  Otherwise fallback to the host name.
335:                    postMasterAddress = postMasterAddress + "@"
336:                            + (domainName != null ? domainName : hostName);
337:                }
338:                this .postmaster = new MailAddress(postMasterAddress);
339:                context.put(Constants.POSTMASTER, postmaster);
340:
341:                if (!isLocalServer(postmaster.getHost())) {
342:                    StringBuffer warnBuffer = new StringBuffer(320)
343:                            .append("The specified postmaster address ( ")
344:                            .append(postmaster)
345:                            .append(
346:                                    " ) is not a local address.  This is not necessarily a problem, but it does mean that emails addressed to the postmaster will be routed to another server.  For some configurations this may cause problems.");
347:                    getLogger().warn(warnBuffer.toString());
348:                }
349:
350:                Configuration userNamesConf = conf.getChild("usernames");
351:                ignoreCase = userNamesConf.getAttributeAsBoolean("ignoreCase",
352:                        false);
353:                boolean enableAliases = userNamesConf.getAttributeAsBoolean(
354:                        "enableAliases", false);
355:                boolean enableForwarding = userNamesConf.getAttributeAsBoolean(
356:                        "enableForwarding", false);
357:                attributes.put(Constants.DEFAULT_ENABLE_ALIASES, new Boolean(
358:                        enableAliases));
359:                attributes.put(Constants.DEFAULT_ENABLE_FORWARDING,
360:                        new Boolean(enableForwarding));
361:                attributes.put(Constants.DEFAULT_IGNORE_USERNAME_CASE,
362:                        new Boolean(ignoreCase));
363:
364:                //Get localusers
365:                try {
366:                    localusers = (UsersRepository) compMgr
367:                            .lookup(UsersRepository.ROLE);
368:                } catch (Exception e) {
369:                    getLogger().error("Cannot open private UserRepository");
370:                    throw e;
371:                }
372:                //}
373:                compMgr.put(UsersRepository.ROLE, localusers);
374:                getLogger().info("Local users repository opened");
375:
376:                Configuration inboxConf = conf.getChild("inboxRepository");
377:                Configuration inboxRepConf = inboxConf.getChild("repository");
378:                // we could delete this block. I didn't remove this because I'm not sure
379:                // wether we need the "check" of the inbox repository here, or not.
380:                try {
381:                    store.select(inboxRepConf);
382:                } catch (Exception e) {
383:                    getLogger().error("Cannot open private MailRepository");
384:                    throw e;
385:                }
386:                inboxRootURL = inboxRepConf.getAttribute("destinationURL");
387:
388:                getLogger().info("Private Repository LocalInbox opened");
389:
390:                // Add this to comp
391:                compMgr.put(MailServer.ROLE, this );
392:
393:                // For mailet engine provide MailetContext
394:                //compMgr.put("org.apache.mailet.MailetContext", this);
395:                // For AVALON aware mailets and matchers, we put the Component object as
396:                // an attribute
397:                attributes.put(Constants.AVALON_COMPONENT_MANAGER, compMgr);
398:
399:                //Temporary get out to allow complex mailet config files to stop blocking sergei sozonoff's work on bouce processing
400:                java.io.File configDir = AvalonContextUtilities.getFile(
401:                        myContext, "file://conf/");
402:                attributes.put("confDir", configDir.getCanonicalPath());
403:
404:                // We can safely remove this and the localDeliveryField when we 
405:                // remove the storeMail method from James and from the MailetContext
406:                DefaultConfiguration conf = new DefaultConfiguration("mailet",
407:                        "generated:James.initialize()");
408:                MailetConfigImpl configImpl = new MailetConfigImpl();
409:                configImpl.setMailetName("LocalDelivery");
410:                configImpl.setConfiguration(conf);
411:                configImpl.setMailetContext(this );
412:                localDeliveryMailet = new LocalDelivery();
413:                localDeliveryMailet.init(configImpl);
414:
415:                System.out.println(SOFTWARE_NAME_VERSION);
416:                getLogger().info("JAMES ...init end");
417:            }
418:
419:            /**
420:             * Place a mail on the spool for processing
421:             *
422:             * @param message the message to send
423:             *
424:             * @throws MessagingException if an exception is caught while placing the mail
425:             *                            on the spool
426:             */
427:            public void sendMail(MimeMessage message) throws MessagingException {
428:                MailAddress sender = new MailAddress((InternetAddress) message
429:                        .getFrom()[0]);
430:                Collection recipients = new HashSet();
431:                Address addresses[] = message.getAllRecipients();
432:                if (addresses != null) {
433:                    for (int i = 0; i < addresses.length; i++) {
434:                        // Javamail treats the "newsgroups:" header field as a
435:                        // recipient, so we want to filter those out.
436:                        if (addresses[i] instanceof  InternetAddress) {
437:                            recipients.add(new MailAddress(
438:                                    (InternetAddress) addresses[i]));
439:                        }
440:                    }
441:                }
442:                sendMail(sender, recipients, message);
443:            }
444:
445:            /**
446:             * Place a mail on the spool for processing
447:             *
448:             * @param sender the sender of the mail
449:             * @param recipients the recipients of the mail
450:             * @param message the message to send
451:             *
452:             * @throws MessagingException if an exception is caught while placing the mail
453:             *                            on the spool
454:             */
455:            public void sendMail(MailAddress sender, Collection recipients,
456:                    MimeMessage message) throws MessagingException {
457:                sendMail(sender, recipients, message, Mail.DEFAULT);
458:            }
459:
460:            /**
461:             * Place a mail on the spool for processing
462:             *
463:             * @param sender the sender of the mail
464:             * @param recipients the recipients of the mail
465:             * @param message the message to send
466:             * @param state the state of the message
467:             *
468:             * @throws MessagingException if an exception is caught while placing the mail
469:             *                            on the spool
470:             */
471:            public void sendMail(MailAddress sender, Collection recipients,
472:                    MimeMessage message, String state)
473:                    throws MessagingException {
474:                MailImpl mail = new MailImpl(getId(), sender, recipients,
475:                        message);
476:                try {
477:                    mail.setState(state);
478:                    sendMail(mail);
479:                } finally {
480:                    ContainerUtil.dispose(mail);
481:                }
482:            }
483:
484:            /**
485:             * Place a mail on the spool for processing
486:             *
487:             * @param sender the sender of the mail
488:             * @param recipients the recipients of the mail
489:             * @param msg an <code>InputStream</code> containing the message
490:             *
491:             * @throws MessagingException if an exception is caught while placing the mail
492:             *                            on the spool
493:             */
494:            public void sendMail(MailAddress sender, Collection recipients,
495:                    InputStream msg) throws MessagingException {
496:                // parse headers
497:                MailHeaders headers = new MailHeaders(msg);
498:
499:                // if headers do not contains minimum REQUIRED headers fields throw Exception
500:                if (!headers.isValid()) {
501:                    throw new MessagingException(
502:                            "Some REQURED header field is missing. Invalid Message");
503:                }
504:                ByteArrayInputStream headersIn = new ByteArrayInputStream(
505:                        headers.toByteArray());
506:                sendMail(new MailImpl(getId(), sender, recipients,
507:                        new SequenceInputStream(headersIn, msg)));
508:            }
509:
510:            /**
511:             * Place a mail on the spool for processing
512:             *
513:             * @param mail the mail to place on the spool
514:             *
515:             * @throws MessagingException if an exception is caught while placing the mail
516:             *                            on the spool
517:             */
518:            public void sendMail(Mail mail) throws MessagingException {
519:                try {
520:                    spool.store(mail);
521:                } catch (Exception e) {
522:                    getLogger().error(
523:                            "Error storing message: " + e.getMessage(), e);
524:                    try {
525:                        spool.remove(mail);
526:                    } catch (Exception ignored) {
527:                        getLogger().error(
528:                                "Error removing message after an error storing it: "
529:                                        + e.getMessage(), e);
530:                    }
531:                    throw new MessagingException("Exception spooling message: "
532:                            + e.getMessage(), e);
533:                }
534:                if (getLogger().isDebugEnabled()) {
535:                    StringBuffer logBuffer = new StringBuffer(64).append(
536:                            "Mail ").append(mail.getName()).append(
537:                            " pushed in spool");
538:                    getLogger().debug(logBuffer.toString());
539:                }
540:            }
541:
542:            /**
543:             * <p>Retrieve the mail repository for a user</p>
544:             *
545:             * <p>For POP3 server only - at the moment.</p>
546:             *
547:             * @param userName the name of the user whose inbox is to be retrieved
548:             *
549:             * @return the POP3 inbox for the user
550:             */
551:            public synchronized MailRepository getUserInbox(String userName) {
552:                MailRepository userInbox = null;
553:
554:                userInbox = (MailRepository) mailboxes.get(userName);
555:
556:                if (userInbox != null) {
557:                    return userInbox;
558:                } else if (mailboxes.containsKey(userName)) {
559:                    // we have a problem
560:                    getLogger().error("Null mailbox for non-null key");
561:                    throw new RuntimeException("Error in getUserInbox.");
562:                } else {
563:                    // need mailbox object
564:                    if (getLogger().isDebugEnabled()) {
565:                        getLogger().debug(
566:                                "Retrieving and caching inbox for " + userName);
567:                    }
568:                    StringBuffer destinationBuffer = new StringBuffer(192)
569:                            .append(inboxRootURL).append(userName).append("/");
570:                    String destination = destinationBuffer.toString();
571:                    DefaultConfiguration mboxConf = new DefaultConfiguration(
572:                            "repository",
573:                            "generated:AvalonFileRepository.compose()");
574:                    mboxConf.setAttribute("destinationURL", destination);
575:                    mboxConf.setAttribute("type", "MAIL");
576:                    try {
577:                        userInbox = (MailRepository) store.select(mboxConf);
578:                        if (userInbox != null) {
579:                            mailboxes.put(userName, userInbox);
580:                        }
581:                    } catch (Exception e) {
582:                        if (getLogger().isErrorEnabled()) {
583:                            getLogger().error("Cannot open user Mailbox" + e);
584:                        }
585:                        throw new RuntimeException("Error in getUserInbox." + e);
586:                    }
587:                    return userInbox;
588:                }
589:            }
590:
591:            /**
592:             * Return a new mail id.
593:             *
594:             * @return a new mail id
595:             */
596:            public String getId() {
597:                long localCount = -1;
598:                synchronized (James.class) {
599:                    localCount = count++;
600:                }
601:                StringBuffer idBuffer = new StringBuffer(64).append("Mail")
602:                        .append(System.currentTimeMillis()).append("-").append(
603:                                localCount);
604:                return idBuffer.toString();
605:            }
606:
607:            /**
608:             * The main method.  Should never be invoked, as James must be called
609:             * from within an Avalon framework container.
610:             *
611:             * @param args the command line arguments
612:             */
613:            public static void main(String[] args) {
614:                System.out.println("ERROR!");
615:                System.out
616:                        .println("Cannot execute James as a stand alone application.");
617:                System.out
618:                        .println("To run James, you need to have the Avalon framework installed.");
619:                System.out
620:                        .println("Please refer to the Readme file to know how to run James.");
621:            }
622:
623:            //Methods for MailetContext
624:
625:            /**
626:             * <p>Get the prioritized list of mail servers for a given host.</p>
627:             *
628:             * <p>TODO: This needs to be made a more specific ordered subtype of Collection.</p>
629:             *
630:             * @param host
631:             */
632:            public Collection getMailServers(String host) {
633:                DNSServer dnsServer = null;
634:                try {
635:                    dnsServer = (DNSServer) compMgr.lookup(DNSServer.ROLE);
636:                } catch (final ServiceException cme) {
637:                    getLogger().error(
638:                            "Fatal configuration error - DNS Servers lost!",
639:                            cme);
640:                    throw new RuntimeException(
641:                            "Fatal configuration error - DNS Servers lost!");
642:                }
643:                return dnsServer.findMXRecords(host);
644:            }
645:
646:            public Object getAttribute(String key) {
647:                return attributes.get(key);
648:            }
649:
650:            public void setAttribute(String key, Object object) {
651:                attributes.put(key, object);
652:            }
653:
654:            public void removeAttribute(String key) {
655:                attributes.remove(key);
656:            }
657:
658:            public Iterator getAttributeNames() {
659:                Vector names = new Vector();
660:                for (Enumeration e = attributes.keys(); e.hasMoreElements();) {
661:                    names.add(e.nextElement());
662:                }
663:                return names.iterator();
664:            }
665:
666:            /**
667:             * This generates a response to the Return-Path address, or the address of
668:             * the message's sender if the Return-Path is not available.  Note that
669:             * this is different than a mail-client's reply, which would use the
670:             * Reply-To or From header. This will send the bounce with the server's
671:             * postmaster as the sender.
672:             */
673:            public void bounce(Mail mail, String message)
674:                    throws MessagingException {
675:                bounce(mail, message, getPostmaster());
676:            }
677:
678:            /**
679:             * This generates a response to the Return-Path address, or the
680:             * address of the message's sender if the Return-Path is not
681:             * available.  Note that this is different than a mail-client's
682:             * reply, which would use the Reply-To or From header.
683:             *
684:             * Bounced messages are attached in their entirety (headers and
685:             * content) and the resulting MIME part type is "message/rfc822".
686:             *
687:             * The attachment to the subject of the original message (or "No
688:             * Subject" if there is no subject in the original message)
689:             *
690:             * There are outstanding issues with this implementation revolving
691:             * around handling of the return-path header.
692:             *
693:             * MIME layout of the bounce message:
694:             *
695:             * multipart (mixed)/
696:             *     contentPartRoot (body) = mpContent (alternative)/
697:             *           part (body) = message
698:             *     part (body) = original
699:             *
700:             */
701:
702:            public void bounce(Mail mail, String message, MailAddress bouncer)
703:                    throws MessagingException {
704:                if (mail.getSender() == null) {
705:                    if (getLogger().isInfoEnabled())
706:                        getLogger()
707:                                .info(
708:                                        "Mail to be bounced contains a null (<>) reverse path.  No bounce will be sent.");
709:                    return;
710:                } else {
711:                    // Bounce message goes to the reverse path, not to the Reply-To address
712:                    if (getLogger().isInfoEnabled())
713:                        getLogger().info(
714:                                "Processing a bounce request for a message with a reverse path of "
715:                                        + mail.getSender().toString());
716:                }
717:
718:                MailImpl reply = rawBounce(mail, message);
719:                //Change the sender...
720:                reply.getMessage().setFrom(bouncer.toInternetAddress());
721:                reply.getMessage().saveChanges();
722:                //Send it off ... with null reverse-path
723:                reply.setSender(null);
724:                sendMail(reply);
725:                ContainerUtil.dispose(reply);
726:            }
727:
728:            /**
729:             * Generates a bounce mail that is a bounce of the original message.
730:             *
731:             * @param bounceText the text to be prepended to the message to describe the bounce condition
732:             *
733:             * @return the bounce mail
734:             *
735:             * @throws MessagingException if the bounce mail could not be created
736:             */
737:            private MailImpl rawBounce(Mail mail, String bounceText)
738:                    throws MessagingException {
739:                //This sends a message to the james component that is a bounce of the sent message
740:                MimeMessage original = mail.getMessage();
741:                MimeMessage reply = (MimeMessage) original.reply(false);
742:                reply.setSubject("Re: " + original.getSubject());
743:                reply.setSentDate(new Date());
744:                Collection recipients = new HashSet();
745:                recipients.add(mail.getSender());
746:                InternetAddress addr[] = { new InternetAddress(mail.getSender()
747:                        .toString()) };
748:                reply.setRecipients(Message.RecipientType.TO, addr);
749:                reply.setFrom(new InternetAddress(mail.getRecipients()
750:                        .iterator().next().toString()));
751:                reply.setText(bounceText);
752:                reply.setHeader(RFC2822Headers.MESSAGE_ID, "replyTo-"
753:                        + mail.getName());
754:                return new MailImpl("replyTo-" + mail.getName(),
755:                        new MailAddress(mail.getRecipients().iterator().next()
756:                                .toString()), recipients, reply);
757:            }
758:
759:            /**
760:             * Returns whether that account has a local inbox on this server
761:             *
762:             * @param name the name to be checked
763:             *
764:             * @return whether the account has a local inbox
765:             */
766:            public boolean isLocalUser(String name) {
767:                if (ignoreCase) {
768:                    return localusers.containsCaseInsensitive(name);
769:                } else {
770:                    return localusers.contains(name);
771:                }
772:            }
773:
774:            /**
775:             * Returns the address of the postmaster for this server.
776:             *
777:             * @return the <code>MailAddress</code> for the postmaster
778:             */
779:            public MailAddress getPostmaster() {
780:                return postmaster;
781:            }
782:
783:            /**
784:             * Return the major version number for the server
785:             *
786:             * @return the major vesion number for the server
787:             */
788:            public int getMajorVersion() {
789:                return 2;
790:            }
791:
792:            /**
793:             * Return the minor version number for the server
794:             *
795:             * @return the minor vesion number for the server
796:             */
797:            public int getMinorVersion() {
798:                return 3;
799:            }
800:
801:            /**
802:             * Check whether the mail domain in question is to be
803:             * handled by this server.
804:             *
805:             * @param serverName the name of the server to check
806:             * @return whether the server is local
807:             */
808:            public boolean isLocalServer(final String serverName) {
809:                return serverNames.contains(serverName.toLowerCase(Locale.US));
810:            }
811:
812:            /**
813:             * Return the type of the server
814:             *
815:             * @return the type of the server
816:             */
817:            public String getServerInfo() {
818:                return "Apache JAMES";
819:            }
820:
821:            /**
822:             * Return the logger for the Mailet API
823:             *
824:             * @return the logger for the Mailet API
825:             */
826:            private Logger getMailetLogger() {
827:                if (mailetLogger == null) {
828:                    mailetLogger = getLogger().getChildLogger("Mailet");
829:                }
830:                return mailetLogger;
831:            }
832:
833:            /**
834:             * Log a message to the Mailet logger
835:             *
836:             * @param message the message to pass to the Mailet logger
837:             */
838:            public void log(String message) {
839:                getMailetLogger().info(message);
840:            }
841:
842:            /**
843:             * Log a message and a Throwable to the Mailet logger
844:             *
845:             * @param message the message to pass to the Mailet logger
846:             * @param t the <code>Throwable</code> to be logged
847:             */
848:            public void log(String message, Throwable t) {
849:                getMailetLogger().info(message, t);
850:            }
851:
852:            /**
853:             * Adds a user to this mail server. Currently just adds user to a
854:             * UsersRepository.
855:             *
856:             * @param userName String representing user name, that is the portion of
857:             * an email address before the '@<domain>'.
858:             * @param password String plaintext password
859:             * @return boolean true if user added succesfully, else false.
860:             * 
861:             * @deprecated we deprecated this in the MailServer interface and this is an implementation
862:             * this component depends already depends on a UsersRepository: clients could directly 
863:             * use the addUser of the usersRepository.
864:             */
865:            public boolean addUser(String userName, String password) {
866:                boolean success;
867:                DefaultJamesUser user = new DefaultJamesUser(userName, "SHA");
868:                user.setPassword(password);
869:                user.initialize();
870:                success = localusers.addUser(user);
871:                return success;
872:            }
873:
874:            /**
875:             * Performs DNS lookups as needed to find servers which should or might
876:             * support SMTP.
877:             * Returns an Iterator over HostAddress, a specialized subclass of
878:             * javax.mail.URLName, which provides location information for
879:             * servers that are specified as mail handlers for the given
880:             * hostname.  This is done using MX records, and the HostAddress
881:             * instances are returned sorted by MX priority.  If no host is
882:             * found for domainName, the Iterator returned will be empty and the
883:             * first call to hasNext() will return false.
884:             *
885:             * @see org.apache.james.DNSServer#getSMTPHostAddresses(String)
886:             * @since Mailet API v2.2.0a16-unstable
887:             * @param domainName - the domain for which to find mail servers
888:             * @return an Iterator over HostAddress instances, sorted by priority
889:             */
890:            public Iterator getSMTPHostAddresses(String domainName) {
891:                DNSServer dnsServer = null;
892:                try {
893:                    dnsServer = (DNSServer) compMgr.lookup(DNSServer.ROLE);
894:                } catch (final ServiceException cme) {
895:                    getLogger().error(
896:                            "Fatal configuration error - DNS Servers lost!",
897:                            cme);
898:                    throw new RuntimeException(
899:                            "Fatal configuration error - DNS Servers lost!");
900:                }
901:                return dnsServer.getSMTPHostAddresses(domainName);
902:            }
903:
904:            /**
905:             * This method has been moved to LocalDelivery (the only client of the method).
906:             * Now we can safely remove it from the Mailet API and from this implementation of MailetContext.
907:             *
908:             * The local field localDeliveryMailet will be removed when we remove the storeMail method.
909:             * 
910:             * @deprecated since 2.2.0 look at the LocalDelivery code to find out how to do the local delivery.
911:             * @see org.apache.mailet.MailetContext#storeMail(org.apache.mailet.MailAddress, org.apache.mailet.MailAddress, javax.mail.internet.MimeMessage)
912:             */
913:            public void storeMail(MailAddress sender, MailAddress recipient,
914:                    MimeMessage msg) throws MessagingException {
915:                if (recipient == null) {
916:                    throw new IllegalArgumentException(
917:                            "Recipient for mail to be spooled cannot be null.");
918:                }
919:                if (msg == null) {
920:                    throw new IllegalArgumentException(
921:                            "Mail message to be spooled cannot be null.");
922:                }
923:                Collection recipients = new HashSet();
924:                recipients.add(recipient);
925:                MailImpl m = new MailImpl(getId(), sender, recipients, msg);
926:                localDeliveryMailet.service(m);
927:                ContainerUtil.dispose(m);
928:            }
929:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.