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


0001:        /****************************************************************
0002:         * Licensed to the Apache Software Foundation (ASF) under one   *
0003:         * or more contributor license agreements.  See the NOTICE file *
0004:         * distributed with this work for additional information        *
0005:         * regarding copyright ownership.  The ASF licenses this file   *
0006:         * to you under the Apache License, Version 2.0 (the            *
0007:         * "License"); you may not use this file except in compliance   *
0008:         * with the License.  You may obtain a copy of the License at   *
0009:         *                                                              *
0010:         *   http://www.apache.org/licenses/LICENSE-2.0                 *
0011:         *                                                              *
0012:         * Unless required by applicable law or agreed to in writing,   *
0013:         * software distributed under the License is distributed on an  *
0014:         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
0015:         * KIND, either express or implied.  See the License for the    *
0016:         * specific language governing permissions and limitations      *
0017:         * under the License.                                           *
0018:         ****************************************************************/package org.apache.james.fetchmail;
0019:
0020:        import java.net.InetAddress;
0021:        import java.net.UnknownHostException;
0022:        import java.util.ArrayList;
0023:        import java.util.Collection;
0024:        import java.util.Enumeration;
0025:        import java.util.Iterator;
0026:        import java.util.StringTokenizer;
0027:
0028:        import javax.mail.Address;
0029:        import javax.mail.Flags;
0030:        import javax.mail.MessagingException;
0031:        import javax.mail.internet.InternetAddress;
0032:        import javax.mail.internet.MimeMessage;
0033:        import javax.mail.internet.ParseException;
0034:
0035:        import org.apache.james.core.MailImpl;
0036:        import org.apache.mailet.RFC2822Headers;
0037:        import org.apache.mailet.Mail;
0038:        import org.apache.mailet.MailAddress;
0039:
0040:        /**
0041:         * <p>Class <code>MessageProcessor</code> handles the delivery of 
0042:         * <code>MimeMessages</code> to the James input spool.</p>
0043:         * 
0044:         * <p>Messages written to the input spool always have the following Mail
0045:         * Attributes set:</p>
0046:         * <dl>
0047:         * <dt>org.apache.james.fetchmail.taskName (java.lang.String)</dt>
0048:         *      <dd>The name of the fetch task that processed the message</dd>
0049:         * <dt>org.apache.james.fetchmail.folderName (java.lang.String)</dt>
0050:         *      <dd>The name of the folder from which the message was fetched</dd>
0051:         * </dl>
0052:         * 
0053:         * <p>Messages written to the input spool have the following Mail Attributes
0054:         *  set if the corresponding condition is satisfied:
0055:         * <dl>
0056:         * <dt>org.apache.james.fetchmail.isBlacklistedRecipient</dt>
0057:         *      <dd>The recipient is in the configured blacklist</dd>
0058:         * <dt>org.apache.james.fetchmail.isMaxMessageSizeExceeded (java.lang.String)</dt>
0059:         *      <dd>The message size exceeds the configured limit. An empty message is
0060:         *          written to the input spool. The Mail Attribute value is a String
0061:         *          representing the size of the original message in bytes.</dd>
0062:         * <dt>org.apache.james.fetchmail.isRecipientNotFound</dt>
0063:         *      <dd>The recipient could not be found. Delivery is to the configured recipient. 
0064:         *          See the discussion of delivery to a sole intended recipient below.</dd>
0065:         * <dt>org.apache.james.fetchmail.isRemoteRecievedHeaderInvalid</dt>
0066:         *       <dd>The Receieved header at the index specified by parameter
0067:         *       <code>remoteReceivedHeaderIndex</code> is invalid.</dd>
0068:         * <dt>org.apache.james.fetchmail.isRemoteRecipient</dt>
0069:         *      <dd>The recipient is on a remote host</dd>
0070:         * <dt>org.apache.james.fetchmail.isUserUndefined</dt>
0071:         *      <dd>The recipient is on a localhost but not defined to James</dd>
0072:         * <dt>org.apache.james.fetchmail.isDefaultSenderLocalPart</dt>
0073:         *      <dd>The local part of the sender address could not be obtained. The
0074:         *          default value has been used.</dd>
0075:         * <dt>org.apache.james.fetchmail.isDefaultSenderDomainPart</dt>
0076:         *      <dd>The domain part of the sender address could not be obtained. The
0077:         *          default value has been used.</dd>
0078:         * <dt>org.apache.james.fetchmail.isDefaultRemoteAddress</dt>
0079:         *      <dd>The remote address could not be determined. The default value
0080:         *      (localhost/127.0.0.1)has been used.</dd>
0081:         * </dl>
0082:         * 
0083:         * <p>Configuration settings -
0084:         *  see <code>org.apache.james.fetchmail.ParsedConfiguration</code>
0085:         * - control the messages that are written to the James input spool, those that
0086:         * are rejected and what happens to messages that are rejected.</p>
0087:         * 
0088:         * <p>Rejection processing is based on the following filters:</p>
0089:         * <dl> 
0090:         * <dt>RejectRemoteRecipient</dt> 
0091:         *      <dd>Rejects recipients on remote hosts</dd>
0092:         * <dt>RejectBlacklistedRecipient</dt>
0093:         *      <dd>Rejects recipients configured in a blacklist</dd>
0094:         * <dt>RejectUserUndefined</dt>
0095:         *      <dd>Rejects recipients on local hosts who are not defined as James users</dd>
0096:         * <dt>RejectRecipientNotFound</dt>
0097:         *      <dd>See the discussion of delivery to a sole intended recipient below</dd>
0098:         * <dt>RejectMaxMessageSizeExceeded</dt>
0099:         *      <dd>Rejects messages whose size exceeds the configured limit</dd>
0100:         * <dt>RejectRemoteReceievedHeaderInvalid</dt>
0101:         *      <dd>Rejects messages whose Received header is invalid.</dd>
0102:         * </dl>
0103:         * 
0104:         * <p>Rejection processing is intentionally limited to managing the status of the
0105:         * messages that are rejected on the server from which they were fetched. View
0106:         * it as a simple automation of the manual processing an end-user would perform 
0107:         * through a mail client. Messages may be marked as seen or be deleted.</p> 
0108:         * 
0109:         * <p>Further processing can be achieved by configuring to disable rejection for 
0110:         * one or more filters. This enables Messages that would have been rejected to
0111:         * be written to the James input spool. The conditional Mail Attributes 
0112:         * described above identify the filter states. The Matcher/Mailet chain can 
0113:         * then be used to perform any further processing required, such as notifying
0114:         * the Postmaster and/or sender, marking the message for error processing, etc.</p>
0115:         * 
0116:         * <p>Note that in the case of a message exceeding the message size limit, the
0117:         * message that is written to the input spool has no content. This enables 
0118:         * configuration of a mailet notifying the sender that their mail has not been
0119:         * delivered due to its size while maintaining the purpose of the filter which is
0120:         * to avoid injecting excessively large messages into the input spool.</p>
0121:         * 
0122:         * <p>Delivery is to a sole intended recipient. The recipient is determined in the
0123:         * following manner:</p>
0124:         *
0125:         * <ol> 
0126:         * <li>If isIgnoreIntendedRecipient(), use the configured recipient</li>
0127:         * <li>If the Envelope contains a for: stanza, use the recipient in the stanza</li>
0128:         * <li>If the Message has a sole intended recipient, use this recipient</li>
0129:         * <li>If not rejectRecipientNotFound(), use the configured recipient</li>
0130:         * </ol>
0131:         * 
0132:         * <p>If a recipient cannot be determined after these steps, the message is 
0133:         * rejected.</p>
0134:         * 
0135:         * <p>Every delivered message CURRENTLY has an "X-fetched-from" header added 
0136:         * containing the name of the fetch task. Its primary uses are to detect bouncing
0137:         * mail and provide backwards compatibility with the fetchPop task that inserted
0138:         * this header to enable injected messages to be detected in the Matcher/Mailet 
0139:         * chain. This header is DEPRECATED and WILL BE REMOVED in a future version of 
0140:         * fetchmail. Use the Mail Attribute <code>org.apache.james.fetchmail.taskName</code>
0141:         * instead.
0142:         * 
0143:         * <p><code>MessageProcessor</code> is as agnostic as it can be about the format
0144:         * and contents of the messages it delivers. There are no RFCs that govern its
0145:         * behavior. The most releveant RFCs relate to the exchange of messages between
0146:         * MTA servers, but not POP3 or IMAP servers which are normally end-point
0147:         * servers and not expected to re-inject mail into MTAs. None the less, the
0148:         * intent is to conform to the 'spirit' of the RFCs.
0149:         * <code>MessageProcessor</code> relies on the MTA (James in this
0150:         * implementation) to manage and validate the injected mail just as it would
0151:         * when receiving mail from an upstream MTA.</p> 
0152:         * 
0153:         * <p>The only correction applied by <code>MessageProcessor</code> is to correct a
0154:         * missing or partial sender address. If the sender address can not be obtained,
0155:         * the default local part and default domain part is added. If the sender domain
0156:         * part is absent, the default domain part is added.</p>
0157:         * 
0158:         * <p>Mail with corrections applied to the sender address will most likely pass
0159:         * Matcher tests on the sender that they might otherwise fail. The 
0160:         * Mail Attributes <code>org.apache.james.fetchmail.isDefaultSenderLocalPart</code>
0161:         * and <code>org.apache.james.fetchmail.isDefaultSenderDomainPart</code> are added 
0162:         * to the injected mail to enable such mail to be detected and processed accordingly.
0163:         * </p>
0164:         * 
0165:         * <p>The status of messages on the server from which they were fetched that 
0166:         * cannot be injected into the input spool due to non-correctable errors is 
0167:         * determined by the undeliverable configuration options.</p>
0168:         * 
0169:         */
0170:        public class MessageProcessor extends ProcessorAbstract {
0171:            private MimeMessage fieldMessageIn;
0172:
0173:            /**
0174:             * Recipient cannot be found
0175:             */
0176:            private boolean fieldRecipientNotFound = false;
0177:
0178:            /**
0179:             * Recipient is a local user on a local host
0180:             */
0181:            private boolean fieldRemoteRecipient = true;
0182:
0183:            /**
0184:             * The mail's Received header at index remoteReceivedHeaderIndex is invalid.
0185:             */
0186:            private Boolean fieldRemoteReceivedHeaderInvalid;
0187:
0188:            /**
0189:             * Recipient is not a local user
0190:             */
0191:            private boolean fieldUserUndefined = false;
0192:
0193:            /**
0194:             * The Maximum Message has been exceeded
0195:             */
0196:            private Boolean fieldMaxMessageSizeExceeded;
0197:
0198:            /**
0199:             * Field names for an RFC2822 compliant RECEIVED Header
0200:             */
0201:            static final private String fieldRFC2822RECEIVEDHeaderFields = "from by via with id for ;";
0202:
0203:            /**
0204:             * Recipient is blacklisted
0205:             */
0206:            private boolean fieldBlacklistedRecipient = false;
0207:
0208:            /**
0209:             * The RFC2822 compliant "Received : from" domain
0210:             */
0211:            private String fieldRemoteDomain;
0212:
0213:            /**
0214:             * The remote address derived from the remote domain
0215:             */
0216:            private String fieldRemoteAddress;
0217:
0218:            /**
0219:             * The remote host name derived from the remote domain
0220:             */
0221:            private String fieldRemoteHostName;
0222:
0223:            /**
0224:             * The default sender local part has been used.
0225:             */
0226:            private boolean fieldDefaultSenderLocalPart = false;
0227:
0228:            /**
0229:             * The default sender domain part has been used.
0230:             */
0231:            private boolean fieldDefaultSenderDomainPart = false;
0232:
0233:            /**
0234:             * The default remote address has been used.
0235:             */
0236:            private boolean fieldDefaultRemoteAddress = false;
0237:
0238:            /**
0239:             * Constructor for MessageProcessor.
0240:             * 
0241:             * @param account
0242:             */
0243:            private MessageProcessor(Account account) {
0244:                super (account);
0245:            }
0246:
0247:            /**
0248:             * Constructor for MessageProcessor.
0249:             * 
0250:             * @param messageIn
0251:             * @param account
0252:             */
0253:
0254:            MessageProcessor(MimeMessage messageIn, Account account) {
0255:                this (account);
0256:                setMessageIn(messageIn);
0257:            }
0258:
0259:            /**
0260:             * Method process attempts to deliver a fetched message.
0261:             * 
0262:             * @see org.apache.james.fetchmail.ProcessorAbstract#process()
0263:             */
0264:            public void process() throws MessagingException {
0265:                // Log delivery attempt
0266:                if (getLogger().isDebugEnabled()) {
0267:                    StringBuffer logMessageBuffer = new StringBuffer(
0268:                            "Attempting delivery of message with id. ");
0269:                    logMessageBuffer.append(getMessageIn().getMessageID());
0270:                    getLogger().debug(logMessageBuffer.toString());
0271:                }
0272:
0273:                // Determine the intended recipient
0274:                MailAddress intendedRecipient = getIntendedRecipient();
0275:                setRecipientNotFound(null == intendedRecipient);
0276:
0277:                if (isRecipientNotFound()) {
0278:                    if (isDeferRecipientNotFound()) {
0279:
0280:                        String messageID = getMessageIn().getMessageID();
0281:                        if (!getDeferredRecipientNotFoundMessageIDs().contains(
0282:                                messageID)) {
0283:                            getDeferredRecipientNotFoundMessageIDs().add(
0284:                                    messageID);
0285:                            if (getLogger().isDebugEnabled()) {
0286:                                StringBuffer messageBuffer = new StringBuffer(
0287:                                        "Deferred processing of message for which the intended recipient could not be found. Message ID: ");
0288:                                messageBuffer.append(messageID);
0289:                                getLogger().debug(messageBuffer.toString());
0290:                            }
0291:                            return;
0292:                        } else {
0293:                            getDeferredRecipientNotFoundMessageIDs().remove(
0294:                                    messageID);
0295:                            if (getLogger().isDebugEnabled()) {
0296:                                StringBuffer messageBuffer = new StringBuffer(
0297:                                        "Processing deferred message for which the intended recipient could not be found. Message ID: ");
0298:                                messageBuffer.append(messageID);
0299:                                getLogger().debug(messageBuffer.toString());
0300:                            }
0301:                        }
0302:                    }
0303:
0304:                    if (isRejectRecipientNotFound()) {
0305:                        rejectRecipientNotFound();
0306:                        return;
0307:                    }
0308:                    intendedRecipient = getRecipient();
0309:                    StringBuffer messageBuffer = new StringBuffer(
0310:                            "Intended recipient not found. Using configured recipient as new envelope recipient - ");
0311:                    messageBuffer.append(intendedRecipient);
0312:                    messageBuffer.append('.');
0313:                    logStatusInfo(messageBuffer.toString());
0314:                }
0315:
0316:                // Set the filter states
0317:                setBlacklistedRecipient(isBlacklistedRecipient(intendedRecipient));
0318:                setRemoteRecipient(!isLocalServer(intendedRecipient));
0319:                setUserUndefined(!isLocalRecipient(intendedRecipient));
0320:
0321:                // Apply the filters. Return if rejected
0322:                if (isRejectBlacklisted() && isBlacklistedRecipient()) {
0323:                    rejectBlacklistedRecipient(intendedRecipient);
0324:                    return;
0325:                }
0326:
0327:                if (isRejectRemoteRecipient() && isRemoteRecipient()) {
0328:                    rejectRemoteRecipient(intendedRecipient);
0329:                    return;
0330:                }
0331:
0332:                if (isRejectUserUndefined() && isUserUndefined()) {
0333:                    rejectUserUndefined(intendedRecipient);
0334:                    return;
0335:                }
0336:
0337:                if (isRejectMaxMessageSizeExceeded()
0338:                        && isMaxMessageSizeExceeded().booleanValue()) {
0339:                    rejectMaxMessageSizeExceeded(getMessageIn().getSize());
0340:                    return;
0341:                }
0342:
0343:                if (isRejectRemoteReceivedHeaderInvalid()
0344:                        && isRemoteReceivedHeaderInvalid().booleanValue()) {
0345:                    rejectRemoteReceivedHeaderInvalid();
0346:                    return;
0347:                }
0348:
0349:                // Create the mail
0350:                // If any of the mail addresses are malformed, we will get a
0351:                // ParseException. 
0352:                // If the IP address and host name for the remote domain cannot
0353:                // be found, we will get an UnknownHostException.
0354:                // In both cases, we log the problem and
0355:                // return. The message disposition is defined by the
0356:                // <undeliverable> attributes.
0357:                Mail mail = null;
0358:                try {
0359:                    mail = createMail(createMessage(), intendedRecipient);
0360:                } catch (ParseException ex) {
0361:                    handleParseException(ex);
0362:                    return;
0363:                } catch (UnknownHostException ex) {
0364:                    handleUnknownHostException(ex);
0365:                    return;
0366:                }
0367:
0368:                addMailAttributes(mail);
0369:                addErrorMessages(mail);
0370:
0371:                // If this mail is bouncing move it to the ERROR repository
0372:                if (isBouncing()) {
0373:                    handleBouncing(mail);
0374:                    return;
0375:                }
0376:
0377:                // OK, lets send that mail!
0378:                sendMail(mail);
0379:            }
0380:
0381:            /**
0382:             * Method rejectRemoteRecipient.
0383:             * @param recipient
0384:             * @throws MessagingException
0385:             */
0386:            protected void rejectRemoteRecipient(MailAddress recipient)
0387:                    throws MessagingException {
0388:                // Update the flags of the received message
0389:                if (!isLeaveRemoteRecipient())
0390:                    setMessageDeleted();
0391:
0392:                if (isMarkRemoteRecipientSeen())
0393:                    setMessageSeen();
0394:
0395:                StringBuffer messageBuffer = new StringBuffer(
0396:                        "Rejected mail intended for remote recipient: ");
0397:                messageBuffer.append(recipient);
0398:                messageBuffer.append('.');
0399:                logStatusInfo(messageBuffer.toString());
0400:
0401:                return;
0402:            }
0403:
0404:            /**
0405:             * Method rejectBlacklistedRecipient.
0406:             * @param recipient
0407:             * @throws MessagingException
0408:             */
0409:            protected void rejectBlacklistedRecipient(MailAddress recipient)
0410:                    throws MessagingException {
0411:                // Update the flags of the received message
0412:                if (!isLeaveBlacklisted())
0413:                    setMessageDeleted();
0414:                if (isMarkBlacklistedSeen())
0415:                    setMessageSeen();
0416:
0417:                StringBuffer messageBuffer = new StringBuffer(
0418:                        "Rejected mail intended for blacklisted recipient: ");
0419:                messageBuffer.append(recipient);
0420:                messageBuffer.append('.');
0421:                logStatusInfo(messageBuffer.toString());
0422:
0423:                return;
0424:            }
0425:
0426:            /**
0427:             * Method rejectRecipientNotFound.
0428:             * @throws MessagingException
0429:             */
0430:            protected void rejectRecipientNotFound() throws MessagingException {
0431:                // Update the flags of the received message
0432:                if (!isLeaveRecipientNotFound())
0433:                    setMessageDeleted();
0434:
0435:                if (isMarkRecipientNotFoundSeen())
0436:                    setMessageSeen();
0437:
0438:                StringBuffer messageBuffer = new StringBuffer(
0439:                        "Rejected mail for which a sole intended recipient could not be found.");
0440:                messageBuffer.append(" Recipients: ");
0441:                Address[] allRecipients = getMessageIn().getAllRecipients();
0442:                for (int i = 0; i < allRecipients.length; i++) {
0443:                    messageBuffer.append(allRecipients[i]);
0444:                    messageBuffer.append(' ');
0445:                }
0446:                messageBuffer.append('.');
0447:                logStatusInfo(messageBuffer.toString());
0448:                return;
0449:            }
0450:
0451:            /**
0452:             * Method rejectUserUndefined.
0453:             * @param recipient
0454:             * @throws MessagingException
0455:             */
0456:            protected void rejectUserUndefined(MailAddress recipient)
0457:                    throws MessagingException {
0458:                // Update the flags of the received message
0459:                if (!isLeaveUserUndefined())
0460:                    setMessageDeleted();
0461:
0462:                if (isMarkUserUndefinedSeen())
0463:                    setMessageSeen();
0464:
0465:                StringBuffer messageBuffer = new StringBuffer(
0466:                        "Rejected mail intended for undefined user: ");
0467:                messageBuffer.append(recipient);
0468:                messageBuffer.append('.');
0469:                logStatusInfo(messageBuffer.toString());
0470:
0471:                return;
0472:            }
0473:
0474:            /**
0475:             * Method rejectMaxMessageSizeExceeded.
0476:             * @param message size
0477:             * @throws MessagingException
0478:             */
0479:            protected void rejectMaxMessageSizeExceeded(int messageSize)
0480:                    throws MessagingException {
0481:                // Update the flags of the received message
0482:                if (!isLeaveMaxMessageSizeExceeded())
0483:                    setMessageDeleted();
0484:
0485:                if (isMarkMaxMessageSizeExceededSeen())
0486:                    setMessageSeen();
0487:
0488:                StringBuffer messageBuffer = new StringBuffer(
0489:                        "Rejected mail exceeding message size limit. Message size: ");
0490:                messageBuffer.append(messageSize / 1024);
0491:                messageBuffer.append("KB.");
0492:                logStatusInfo(messageBuffer.toString());
0493:
0494:                return;
0495:            }
0496:
0497:            /**
0498:             * Method rejectRemoteReceivedHeaderInvalid.
0499:             * @throws MessagingException
0500:             */
0501:            protected void rejectRemoteReceivedHeaderInvalid()
0502:                    throws MessagingException {
0503:                // Update the flags of the received message
0504:                if (!isLeaveRemoteReceivedHeaderInvalid())
0505:                    setMessageDeleted();
0506:
0507:                if (isMarkRemoteReceivedHeaderInvalidSeen())
0508:                    setMessageSeen();
0509:
0510:                StringBuffer messageBuffer = new StringBuffer(
0511:                        "Rejected mail with an invalid Received: header at index ");
0512:                messageBuffer.append(getRemoteReceivedHeaderIndex());
0513:                messageBuffer.append(".");
0514:                logStatusInfo(messageBuffer.toString());
0515:                return;
0516:            }
0517:
0518:            /**
0519:             * <p>Method createMessage answers a new <code>MimeMessage</code> from the
0520:             * fetched message.</p>
0521:             * 
0522:             * <p>If the maximum message size is exceeded, an empty message is created,
0523:             * else the new message is a copy of the received message.</p>
0524:             * 
0525:             * @return MimeMessage
0526:             * @throws MessagingException
0527:             */
0528:            protected MimeMessage createMessage() throws MessagingException {
0529:                // Create a new messsage from the received message
0530:                MimeMessage messageOut = null;
0531:                if (isMaxMessageSizeExceeded().booleanValue())
0532:                    messageOut = createEmptyMessage();
0533:                else
0534:                    messageOut = new MimeMessage(getMessageIn());
0535:
0536:                // set the X-fetched headers
0537:                // Note this is still required to detect bouncing mail and
0538:                // for backwards compatibility with fetchPop 
0539:                messageOut.addHeader("X-fetched-from", getFetchTaskName());
0540:
0541:                return messageOut;
0542:            }
0543:
0544:            /**
0545:             * Method createEmptyMessage answers a new 
0546:             * <code>MimeMessage</code> from the fetched message with the message 
0547:             * contents removed. 
0548:             * 
0549:             * @return MimeMessage
0550:             * @throws MessagingException
0551:             */
0552:            protected MimeMessage createEmptyMessage()
0553:                    throws MessagingException {
0554:                // Create an empty messsage
0555:                MimeMessage messageOut = new MimeMessage(getSession());
0556:
0557:                // Propogate the headers and subject
0558:                Enumeration headersInEnum = getMessageIn().getAllHeaderLines();
0559:                while (headersInEnum.hasMoreElements())
0560:                    messageOut.addHeaderLine((String) headersInEnum
0561:                            .nextElement());
0562:                messageOut.setSubject(getMessageIn().getSubject());
0563:
0564:                // Add empty text
0565:                messageOut.setText("");
0566:
0567:                // Save
0568:                messageOut.saveChanges();
0569:
0570:                return messageOut;
0571:            }
0572:
0573:            /**
0574:             * Method createMail creates a new <code>Mail</code>.
0575:             * 
0576:             * @param message
0577:             * @param recipient
0578:             * @return Mail
0579:             * @throws MessagingException
0580:             */
0581:            protected Mail createMail(MimeMessage message, MailAddress recipient)
0582:                    throws MessagingException, UnknownHostException {
0583:                Collection recipients = new ArrayList(1);
0584:                recipients.add(recipient);
0585:                MailImpl mail = new MailImpl(getServer().getId(), getSender(),
0586:                        recipients, message);
0587:                // Ensure the mail is created with non-null remote host name and address,
0588:                // otherwise the Mailet chain may go splat!
0589:                if (getRemoteAddress() == null || getRemoteHostName() == null) {
0590:                    mail.setRemoteAddr("127.0.0.1");
0591:                    mail.setRemoteHost("localhost");
0592:                    setDefaultRemoteAddress(true);
0593:                    logStatusInfo("Remote address could not be determined. Using localhost/127.0.0.1");
0594:                } else {
0595:                    mail.setRemoteAddr(getRemoteAddress());
0596:                    mail.setRemoteHost(getRemoteHostName());
0597:                    setDefaultRemoteAddress(false);
0598:                }
0599:
0600:                if (getLogger().isDebugEnabled()) {
0601:                    StringBuffer messageBuffer = new StringBuffer(
0602:                            "Created mail with name: ");
0603:                    messageBuffer.append(mail.getName());
0604:                    messageBuffer.append(", sender: ");
0605:                    messageBuffer.append(mail.getSender());
0606:                    messageBuffer.append(", recipients: ");
0607:                    Iterator recipientIterator = mail.getRecipients()
0608:                            .iterator();
0609:                    while (recipientIterator.hasNext()) {
0610:                        messageBuffer.append(recipientIterator.next());
0611:                        messageBuffer.append(' ');
0612:                    }
0613:                    messageBuffer.append(", remote address: ");
0614:                    messageBuffer.append(mail.getRemoteAddr());
0615:                    messageBuffer.append(", remote host name: ");
0616:                    messageBuffer.append(mail.getRemoteHost());
0617:                    messageBuffer.append('.');
0618:                    getLogger().debug(messageBuffer.toString());
0619:                }
0620:                return mail;
0621:            }
0622:
0623:            /**
0624:             * <p>
0625:             * Method getSender answers a <code>MailAddress</code> for the sender.
0626:             * When the sender local part and/or domain part can not be obtained
0627:             * from the mail, default values are used. The flags 
0628:             * 'defaultSenderLocalPart' and 'defaultSenderDomainPart' are set 
0629:             * accordingly.
0630:             * </p>
0631:             * 
0632:             * @return MailAddress
0633:             * @throws MessagingException
0634:             */
0635:            protected MailAddress getSender() throws MessagingException {
0636:                String from = null;
0637:                InternetAddress internetAddress = null;
0638:
0639:                try {
0640:                    from = ((InternetAddress) getMessageIn().getFrom()[0])
0641:                            .getAddress().trim();
0642:                    setDefaultSenderLocalPart(false);
0643:                } catch (Exception _) {
0644:                    from = getDefaultLocalPart();
0645:                    setDefaultSenderLocalPart(true);
0646:                    StringBuffer buffer = new StringBuffer(32);
0647:                    buffer
0648:                            .append("Sender localpart is absent. Using default value (");
0649:                    buffer.append(getDefaultLocalPart());
0650:                    buffer.append(')');
0651:                    logStatusInfo(buffer.toString());
0652:                }
0653:
0654:                // Check for domain part, add default if missing
0655:                if (from.indexOf('@') < 0) {
0656:                    StringBuffer fromBuffer = new StringBuffer(from);
0657:                    fromBuffer.append('@');
0658:                    fromBuffer.append(getDefaultDomainName());
0659:                    internetAddress = new InternetAddress(fromBuffer.toString());
0660:                    setDefaultSenderDomainPart(true);
0661:
0662:                    StringBuffer buffer = new StringBuffer(32);
0663:                    buffer
0664:                            .append("Sender domain is absent. Using default value (");
0665:                    buffer.append(getDefaultDomainName());
0666:                    buffer.append(')');
0667:                    logStatusInfo(buffer.toString());
0668:                } else {
0669:                    internetAddress = new InternetAddress(from);
0670:                    setDefaultSenderDomainPart(false);
0671:                }
0672:
0673:                return new MailAddress(internetAddress);
0674:            }
0675:
0676:            /**
0677:             * <p>Method computeRemoteDomain answers a <code>String</code> that is the
0678:             * RFC2822 compliant "Received : from" domain extracted from the message
0679:             * being processed for the remote domain that sent the message.</p>
0680:             *
0681:             * <p>Often the remote domain is the domain that sent the message to the
0682:             * host of the message store, the second "received" header, which has an
0683:             * index of 1. Other times,  messages may be received by a edge mail server
0684:             * and relayed internally through one or more internal mail servers prior 
0685:             * to  arriving at the message store host. In these cases the index is 
0686:             * 1 + the number of internal servers through which a mail passes.
0687:             * </p>
0688:             * <p>The index of the header to use is specified by the configuration
0689:             * parameter <code>RemoteReceivedHeaderIndex</code>. This is set to
0690:             * point to the received header prior to the remote mail server, the one
0691:             * prior to the edge mail server.
0692:             * </p> 
0693:             * <p>"received" headers are searched starting at the specified index.
0694:             * If a domain in the "received" header is not found, successively closer 
0695:             * "received" headers are tried. If a domain is not found in this way, the
0696:             * local machine is used as the domain. Finally, if the local domain cannot
0697:             * be determined, the local address 127.0.0.1 is used.
0698:             * </p>
0699:             * 
0700:             * @return String An RFC2822 compliant "Received : from" domain name
0701:             */
0702:            protected String computeRemoteDomain() throws MessagingException {
0703:                StringBuffer domainBuffer = new StringBuffer();
0704:                String[] headers = null;
0705:
0706:                if (getRemoteReceivedHeaderIndex() > -1)
0707:                    headers = getMessageIn().getHeader(RFC2822Headers.RECEIVED);
0708:
0709:                // There are RECEIVED headers if the array is not null
0710:                // and its length at is greater than 0             
0711:                boolean hasHeaders = (null == headers ? false
0712:                        : headers.length > 0);
0713:
0714:                // If there are RECEIVED headers try and extract the domain
0715:                if (hasHeaders) {
0716:                    final String headerTokens = " \n\r";
0717:
0718:                    // Search the headers for a domain
0719:                    for (int headerIndex = headers.length > getRemoteReceivedHeaderIndex() ? getRemoteReceivedHeaderIndex()
0720:                            : headers.length - 1; headerIndex >= 0
0721:                            && domainBuffer.length() == 0; headerIndex--) {
0722:                        // Find the "from" token
0723:                        StringTokenizer tokenizer = new StringTokenizer(
0724:                                headers[headerIndex], headerTokens);
0725:                        boolean inFrom = false;
0726:                        while (!inFrom && tokenizer.hasMoreTokens())
0727:                            inFrom = tokenizer.nextToken().equals("from");
0728:                        // Add subsequent tokens to the domain buffer until another                  
0729:                        // field is encountered or there are no more tokens
0730:                        while (inFrom && tokenizer.hasMoreTokens()) {
0731:                            String token = tokenizer.nextToken();
0732:                            if (inFrom = getRFC2822RECEIVEDHeaderFields()
0733:                                    .indexOf(token) == -1) {
0734:                                domainBuffer.append(token);
0735:                                domainBuffer.append(' ');
0736:                            }
0737:                        }
0738:                    }
0739:                }
0740:                // If a domain was not found, the default is the local host and         
0741:                // if we cannot resolve this, the local address 127.0.0.1         
0742:                // Note that earlier versions of this code simply used 'localhost'         
0743:                // which works fine with java.net but is not resolved by dnsjava         
0744:                // which was introduced in v2.2.0. See Jira issue JAMES-302.          
0745:                if (domainBuffer.length() == 0) {
0746:                    try {
0747:                        InetAddress addr1 = java.net.InetAddress.getLocalHost();
0748:                        // These shenanigans are required to get the fully qualified                 
0749:                        // hostname prior to JDK 1.4 in which getCanonicalHostName()                 
0750:                        // does the job for us                 
0751:                        InetAddress addr2 = java.net.InetAddress
0752:                                .getByName(addr1.getHostAddress());
0753:                        InetAddress addr3 = java.net.InetAddress
0754:                                .getByName(addr2.getHostName());
0755:                        domainBuffer.append(addr3.getHostName());
0756:                    } catch (UnknownHostException ue) {
0757:                        domainBuffer.append("[127.0.0.1]");
0758:                    }
0759:                }
0760:                return domainBuffer.toString().trim();
0761:            }
0762:
0763:            /**
0764:             * Method handleBouncing sets the Mail state to ERROR and delete from
0765:             * the message store.
0766:             * 
0767:             * @param mail
0768:             */
0769:            protected void handleBouncing(Mail mail) throws MessagingException {
0770:                mail.setState(Mail.ERROR);
0771:                setMessageDeleted();
0772:
0773:                mail.setErrorMessage("This mail from FetchMail task "
0774:                        + getFetchTaskName() + " seems to be bouncing!");
0775:                logStatusError("Message is bouncing! Deleted from message store and moved to the Error repository.");
0776:            }
0777:
0778:            /**
0779:             * Method handleParseException.
0780:             * @param ex
0781:             * @throws MessagingException
0782:             */
0783:            protected void handleParseException(ParseException ex)
0784:                    throws MessagingException {
0785:                // Update the flags of the received message
0786:                if (!isLeaveUndeliverable())
0787:                    setMessageDeleted();
0788:                if (isMarkUndeliverableSeen())
0789:                    setMessageSeen();
0790:                logStatusWarn("Message could not be delivered due to an error parsing a mail address.");
0791:                if (getLogger().isDebugEnabled()) {
0792:                    StringBuffer messageBuffer = new StringBuffer(
0793:                            "UNDELIVERABLE Message ID: ");
0794:                    messageBuffer.append(getMessageIn().getMessageID());
0795:                    getLogger().debug(messageBuffer.toString(), ex);
0796:                }
0797:            }
0798:
0799:            /**
0800:             * Method handleUnknownHostException.
0801:             * @param ex
0802:             * @throws MessagingException
0803:             */
0804:            protected void handleUnknownHostException(UnknownHostException ex)
0805:                    throws MessagingException {
0806:                // Update the flags of the received message
0807:                if (!isLeaveUndeliverable())
0808:                    setMessageDeleted();
0809:
0810:                if (isMarkUndeliverableSeen())
0811:                    setMessageSeen();
0812:
0813:                logStatusWarn("Message could not be delivered due to an error determining the remote domain.");
0814:                if (getLogger().isDebugEnabled()) {
0815:                    StringBuffer messageBuffer = new StringBuffer(
0816:                            "UNDELIVERABLE Message ID: ");
0817:                    messageBuffer.append(getMessageIn().getMessageID());
0818:                    getLogger().debug(messageBuffer.toString(), ex);
0819:                }
0820:            }
0821:
0822:            /**
0823:             * Method isLocalRecipient.
0824:             * @param recipient
0825:             * @return boolean
0826:             */
0827:            protected boolean isLocalRecipient(MailAddress recipient) {
0828:                return isLocalUser(recipient) && isLocalServer(recipient);
0829:            }
0830:
0831:            /**
0832:             * Method isLocalServer.
0833:             * @param recipient
0834:             * @return boolean
0835:             */
0836:            protected boolean isLocalServer(MailAddress recipient) {
0837:                return getServer().isLocalServer(recipient.getHost());
0838:            }
0839:
0840:            /**
0841:             * Method isLocalUser.
0842:             * @param recipient
0843:             * @return boolean
0844:             */
0845:            protected boolean isLocalUser(MailAddress recipient) {
0846:                return getLocalUsers().containsCaseInsensitive(
0847:                        recipient.getUser());
0848:            }
0849:
0850:            /**
0851:             * Method isBlacklistedRecipient.
0852:             * @param recipient
0853:             * @return boolean
0854:             */
0855:            protected boolean isBlacklistedRecipient(MailAddress recipient) {
0856:                return getBlacklist().contains(recipient);
0857:            }
0858:
0859:            /**
0860:             * Check if this mail has been bouncing by counting the X-fetched-from 
0861:             * headers for this task
0862:             * 
0863:             * @return boolean
0864:             */
0865:            protected boolean isBouncing() throws MessagingException {
0866:                Enumeration enumeration = getMessageIn()
0867:                        .getMatchingHeaderLines(
0868:                                new String[] { "X-fetched-from" });
0869:                int count = 0;
0870:                while (enumeration.hasMoreElements()) {
0871:                    String header = (String) enumeration.nextElement();
0872:                    if (header.equals(getFetchTaskName()))
0873:                        count++;
0874:                }
0875:                return count >= 3;
0876:            }
0877:
0878:            /**
0879:             * Method sendMail.
0880:             * @param mail
0881:             * @throws MessagingException
0882:             */
0883:            protected void sendMail(Mail mail) throws MessagingException {
0884:                // send the mail
0885:                getServer().sendMail(mail);
0886:
0887:                // Update the flags of the received message
0888:                if (!isLeave())
0889:                    setMessageDeleted();
0890:
0891:                if (isMarkSeen())
0892:                    setMessageSeen();
0893:
0894:                // Log the status
0895:                StringBuffer messageBuffer = new StringBuffer(
0896:                        "Spooled message to recipients: ");
0897:                Iterator recipientIterator = mail.getRecipients().iterator();
0898:                while (recipientIterator.hasNext()) {
0899:                    messageBuffer.append(recipientIterator.next());
0900:                    messageBuffer.append(' ');
0901:                }
0902:                messageBuffer.append('.');
0903:                logStatusInfo(messageBuffer.toString());
0904:            }
0905:
0906:            /**
0907:             * Method getEnvelopeRecipient answers the recipient if found else null.
0908:             * 
0909:             * Try and parse the "for" parameter from a Received header
0910:             * Maybe not the most accurate parsing in the world but it should do
0911:             * I opted not to use ORO (maybe I should have)
0912:             * 
0913:             * @param msg
0914:             * @return String
0915:             */
0916:
0917:            protected String getEnvelopeRecipient(MimeMessage msg)
0918:                    throws MessagingException {
0919:                String res = getCustomRecipientHeader();
0920:                if (res != null && res.length() > 0) {
0921:                    String[] headers = msg
0922:                            .getHeader(getCustomRecipientHeader());
0923:                    if (headers != null) {
0924:                        String mailFor = headers[0];
0925:                        if (mailFor.startsWith("<") && mailFor.endsWith(">"))
0926:                            mailFor = mailFor.substring(1,
0927:                                    (mailFor.length() - 1));
0928:                        return mailFor;
0929:                    }
0930:                } else {
0931:                    try {
0932:                        Enumeration enumeration = msg
0933:                                .getMatchingHeaderLines(new String[] { "Received" });
0934:                        while (enumeration.hasMoreElements()) {
0935:                            String received = (String) enumeration
0936:                                    .nextElement();
0937:
0938:                            int nextSearchAt = 0;
0939:                            int i = 0;
0940:                            int start = 0;
0941:                            int end = 0;
0942:                            boolean hasBracket = false;
0943:                            boolean usableAddress = false;
0944:                            while (!usableAddress && (i != -1)) {
0945:                                hasBracket = false;
0946:                                i = received.indexOf("for ", nextSearchAt);
0947:                                if (i > 0) {
0948:                                    start = i + 4;
0949:                                    end = 0;
0950:                                    nextSearchAt = start;
0951:                                    for (int c = start; c < received.length(); c++) {
0952:                                        char ch = received.charAt(c);
0953:                                        switch (ch) {
0954:                                        case '<':
0955:                                            hasBracket = true;
0956:                                            continue;
0957:                                        case '@':
0958:                                            usableAddress = true;
0959:                                            continue;
0960:                                        case ' ':
0961:                                            end = c;
0962:                                            break;
0963:                                        case ';':
0964:                                            end = c;
0965:                                            break;
0966:                                        }
0967:                                        if (end > 0)
0968:                                            break;
0969:                                    }
0970:                                }
0971:                            }
0972:                            if (usableAddress) {
0973:                                // lets try and grab the email address
0974:                                String mailFor = received.substring(start, end);
0975:
0976:                                // strip the <> around the address if there are any
0977:                                if (mailFor.startsWith("<")
0978:                                        && mailFor.endsWith(">"))
0979:                                    mailFor = mailFor.substring(1, (mailFor
0980:                                            .length() - 1));
0981:
0982:                                return mailFor;
0983:                            }
0984:                        }
0985:                    } catch (MessagingException me) {
0986:                        logStatusWarn("No Received headers found.");
0987:                    }
0988:                }
0989:                return null;
0990:            }
0991:
0992:            /**
0993:             * Method getIntendedRecipient answers the sole intended recipient else null.
0994:             * 
0995:             * @return MailAddress
0996:             * @throws MessagingException
0997:             */
0998:            protected MailAddress getIntendedRecipient()
0999:                    throws MessagingException {
1000:                // If the original recipient should be ignored, answer the 
1001:                // hard-coded recipient
1002:                if (isIgnoreRecipientHeader()) {
1003:                    StringBuffer messageBuffer = new StringBuffer(
1004:                            "Ignoring recipient header. Using configured recipient as new envelope recipient: ");
1005:                    messageBuffer.append(getRecipient());
1006:                    messageBuffer.append('.');
1007:                    logStatusInfo(messageBuffer.toString());
1008:                    return getRecipient();
1009:                }
1010:
1011:                // If we can determine who the message was received for, answer
1012:                // the target recipient
1013:                String targetRecipient = getEnvelopeRecipient(getMessageIn());
1014:                if (targetRecipient != null) {
1015:                    MailAddress recipient = new MailAddress(targetRecipient);
1016:                    StringBuffer messageBuffer = new StringBuffer(
1017:                            "Using original envelope recipient as new envelope recipient: ");
1018:                    messageBuffer.append(recipient);
1019:                    messageBuffer.append('.');
1020:                    logStatusInfo(messageBuffer.toString());
1021:                    return recipient;
1022:                }
1023:
1024:                // If we can determine the intended recipient from all of the recipients,
1025:                // answer the intended recipient. This requires that there is exactly one
1026:                // recipient answered by getAllRecipients(), which examines the TO: CC: and
1027:                // BCC: headers
1028:                Address[] allRecipients = getMessageIn().getAllRecipients();
1029:                if (allRecipients.length == 1) {
1030:                    MailAddress recipient = new MailAddress(
1031:                            (InternetAddress) allRecipients[0]);
1032:                    StringBuffer messageBuffer = new StringBuffer(
1033:                            "Using sole recipient header address as new envelope recipient: ");
1034:                    messageBuffer.append(recipient);
1035:                    messageBuffer.append('.');
1036:                    logStatusInfo(messageBuffer.toString());
1037:                    return recipient;
1038:                }
1039:
1040:                return null;
1041:            }
1042:
1043:            /**
1044:             * Returns the messageIn.
1045:             * @return MimeMessage
1046:             */
1047:            protected MimeMessage getMessageIn() {
1048:                return fieldMessageIn;
1049:            }
1050:
1051:            /**
1052:             * Sets the messageIn.
1053:             * @param messageIn The messageIn to set
1054:             */
1055:            protected void setMessageIn(MimeMessage messageIn) {
1056:                fieldMessageIn = messageIn;
1057:            }
1058:
1059:            /**
1060:             * Returns the localRecipient.
1061:             * @return boolean
1062:             */
1063:            protected boolean isRemoteRecipient() {
1064:                return fieldRemoteRecipient;
1065:            }
1066:
1067:            /**
1068:             * Returns <code>boolean</code> indicating if the message to be delivered
1069:             * was unprocessed in a previous delivery attempt.
1070:             * @return boolean
1071:             */
1072:            protected boolean isPreviouslyUnprocessed() {
1073:                return true;
1074:            }
1075:
1076:            /**
1077:             * Log the status of the current message as INFO.
1078:             * @param detailMsg
1079:             */
1080:            protected void logStatusInfo(String detailMsg)
1081:                    throws MessagingException {
1082:                getLogger().info(getStatusReport(detailMsg).toString());
1083:            }
1084:
1085:            /**
1086:             * Log the status the current message as WARN.
1087:             * @param detailMsg
1088:             */
1089:            protected void logStatusWarn(String detailMsg)
1090:                    throws MessagingException {
1091:                getLogger().warn(getStatusReport(detailMsg).toString());
1092:            }
1093:
1094:            /**
1095:             * Log the status the current message as ERROR.
1096:             * @param detailMsg
1097:             */
1098:            protected void logStatusError(String detailMsg)
1099:                    throws MessagingException {
1100:                getLogger().error(getStatusReport(detailMsg).toString());
1101:            }
1102:
1103:            /**
1104:             * Answer a <code>StringBuffer</code> containing a message reflecting
1105:             * the current status of the message being processed.
1106:             * 
1107:             * @param detailMsg
1108:             * @return StringBuffer
1109:             */
1110:            protected StringBuffer getStatusReport(String detailMsg)
1111:                    throws MessagingException {
1112:                StringBuffer messageBuffer = new StringBuffer(detailMsg);
1113:                if (detailMsg.length() > 0)
1114:                    messageBuffer.append(' ');
1115:                messageBuffer.append("Message ID: ");
1116:                messageBuffer.append(getMessageIn().getMessageID());
1117:                messageBuffer.append(". Flags: Seen = ");
1118:                messageBuffer.append(new Boolean(isMessageSeen()));
1119:                messageBuffer.append(", Delete = ");
1120:                messageBuffer.append(new Boolean(isMessageDeleted()));
1121:                messageBuffer.append('.');
1122:                return messageBuffer;
1123:            }
1124:
1125:            /**
1126:             * Returns the userUndefined.
1127:             * @return boolean
1128:             */
1129:            protected boolean isUserUndefined() {
1130:                return fieldUserUndefined;
1131:            }
1132:
1133:            /**
1134:             * Is the DELETED flag set?
1135:             * @throws MessagingException
1136:             */
1137:            protected boolean isMessageDeleted() throws MessagingException {
1138:                return getMessageIn().isSet(Flags.Flag.DELETED);
1139:            }
1140:
1141:            /**
1142:             * Is the SEEN flag set?
1143:             * @throws MessagingException
1144:             */
1145:            protected boolean isMessageSeen() throws MessagingException {
1146:                return getMessageIn().isSet(Flags.Flag.SEEN);
1147:            }
1148:
1149:            /**
1150:             * Set the DELETED flag.
1151:             * @throws MessagingException
1152:             */
1153:            protected void setMessageDeleted() throws MessagingException {
1154:                getMessageIn().setFlag(Flags.Flag.DELETED, true);
1155:            }
1156:
1157:            /*    /**
1158:             * Set the SEEN flag.
1159:             * @throws MessagingException
1160:             */
1161:            protected void setMessageSeen() throws MessagingException {
1162:                // If the Seen flag is not handled by the folder
1163:                // allow a handler to do whatever it deems necessary
1164:                if (!getMessageIn().getFolder().getPermanentFlags().contains(
1165:                        Flags.Flag.SEEN))
1166:                    handleMarkSeenNotPermanent();
1167:                else
1168:                    getMessageIn().setFlag(Flags.Flag.SEEN, true);
1169:            }
1170:
1171:            /**
1172:             * <p>Handler for when the folder does not support the SEEN flag.
1173:             * The default behaviour implemented here is to log a warning and set the
1174:             * flag anyway.</p>
1175:             * 
1176:             * <p> Subclasses may choose to override this and implement their own
1177:             * solutions.</p>
1178:             *  
1179:             * @throws MessagingException
1180:             */
1181:            protected void handleMarkSeenNotPermanent()
1182:                    throws MessagingException {
1183:                getMessageIn().setFlag(Flags.Flag.SEEN, true);
1184:                logStatusWarn("Message marked as SEEN, but the folder does not support a permanent SEEN flag.");
1185:            }
1186:
1187:            /**
1188:             * Returns the Blacklisted.
1189:             * @return boolean
1190:             */
1191:            protected boolean isBlacklistedRecipient() {
1192:                return fieldBlacklistedRecipient;
1193:            }
1194:
1195:            /**
1196:             * Sets the localRecipient.
1197:             * @param localRecipient The localRecipient to set
1198:             */
1199:            protected void setRemoteRecipient(boolean localRecipient) {
1200:                fieldRemoteRecipient = localRecipient;
1201:            }
1202:
1203:            /**
1204:             * Sets the userUndefined.
1205:             * @param userUndefined The userUndefined to set
1206:             */
1207:            protected void setUserUndefined(boolean userUndefined) {
1208:                fieldUserUndefined = userUndefined;
1209:            }
1210:
1211:            /**
1212:             * Adds the mail attributes to a <code>Mail</code>. 
1213:             * @param aMail a Mail instance
1214:             */
1215:            protected void addMailAttributes(Mail aMail)
1216:                    throws MessagingException {
1217:                aMail.setAttribute(getAttributePrefix() + "taskName",
1218:                        getFetchTaskName());
1219:
1220:                aMail.setAttribute(getAttributePrefix() + "folderName",
1221:                        getMessageIn().getFolder().getFullName());
1222:
1223:                if (isRemoteRecipient())
1224:                    aMail.setAttribute(getAttributePrefix()
1225:                            + "isRemoteRecipient", null);
1226:
1227:                if (isUserUndefined())
1228:                    aMail.setAttribute(
1229:                            getAttributePrefix() + "isUserUndefined", null);
1230:
1231:                if (isBlacklistedRecipient())
1232:                    aMail.setAttribute(getAttributePrefix()
1233:                            + "isBlacklistedRecipient", null);
1234:
1235:                if (isRecipientNotFound())
1236:                    aMail.setAttribute(getAttributePrefix()
1237:                            + "isRecipientNotFound", null);
1238:
1239:                if (isMaxMessageSizeExceeded().booleanValue())
1240:                    aMail.setAttribute(getAttributePrefix()
1241:                            + "isMaxMessageSizeExceeded", new Integer(
1242:                            getMessageIn().getSize()).toString());
1243:
1244:                if (isRemoteReceivedHeaderInvalid().booleanValue())
1245:                    aMail.setAttribute(getAttributePrefix()
1246:                            + "isRemoteReceivedHeaderInvalid", null);
1247:
1248:                if (isDefaultSenderLocalPart())
1249:                    aMail.setAttribute(getAttributePrefix()
1250:                            + "isDefaultSenderLocalPart", null);
1251:
1252:                if (isDefaultSenderDomainPart())
1253:                    aMail.setAttribute(getAttributePrefix()
1254:                            + "isDefaultSenderDomainPart", null);
1255:
1256:                if (isDefaultRemoteAddress())
1257:                    aMail.setAttribute(getAttributePrefix()
1258:                            + "isDefaultRemoteAddress", null);
1259:            }
1260:
1261:            /**
1262:             * Adds any  required error messages to a <code>Mail</code>. 
1263:             * @param aMail a Mail instance
1264:             */
1265:            protected void addErrorMessages(Mail mail)
1266:                    throws MessagingException {
1267:                if (isMaxMessageSizeExceeded().booleanValue()) {
1268:                    StringBuffer msgBuffer = new StringBuffer(
1269:                            "550 - Rejected - This message has been rejected as the message size of ");
1270:                    msgBuffer
1271:                            .append(getMessageIn().getSize() * 1000 / 1024 / 1000f);
1272:                    msgBuffer
1273:                            .append("KB exceeds the maximum permitted size of ");
1274:                    msgBuffer.append(getMaxMessageSizeLimit() / 1024);
1275:                    msgBuffer.append("KB.");
1276:                    mail.setErrorMessage(msgBuffer.toString());
1277:                }
1278:            }
1279:
1280:            /**
1281:             * Sets the Blacklisted.
1282:             * @param blacklisted The blacklisted to set
1283:             */
1284:            protected void setBlacklistedRecipient(boolean blacklisted) {
1285:                fieldBlacklistedRecipient = blacklisted;
1286:            }
1287:
1288:            /**
1289:             * Returns the recipientNotFound.
1290:             * @return boolean
1291:             */
1292:            protected boolean isRecipientNotFound() {
1293:                return fieldRecipientNotFound;
1294:            }
1295:
1296:            /**
1297:             * Sets the recipientNotFound.
1298:             * @param recipientNotFound The recipientNotFound to set
1299:             */
1300:            protected void setRecipientNotFound(boolean recipientNotFound) {
1301:                fieldRecipientNotFound = recipientNotFound;
1302:            }
1303:
1304:            /**
1305:             * Returns the remoteDomain, lazily initialised as required.
1306:             * @return String
1307:             */
1308:            protected String getRemoteDomain() throws MessagingException {
1309:
1310:                String remoteDomain;
1311:                if (null == (remoteDomain = getRemoteDomainBasic())) {
1312:                    updateRemoteDomain();
1313:                    return getRemoteDomain();
1314:                }
1315:                return remoteDomain;
1316:            }
1317:
1318:            /**
1319:             * Returns the remoteDomain.
1320:             * @return String
1321:             */
1322:            private String getRemoteDomainBasic() {
1323:                return fieldRemoteDomain;
1324:            }
1325:
1326:            /**
1327:             * Sets the remoteDomain.
1328:             * @param remoteDomain The remoteDomain to set
1329:             */
1330:            protected void setRemoteDomain(String remoteDomain) {
1331:                fieldRemoteDomain = remoteDomain;
1332:            }
1333:
1334:            /**
1335:             * Updates the remoteDomain.
1336:             */
1337:            protected void updateRemoteDomain() throws MessagingException {
1338:                setRemoteDomain(computeRemoteDomain());
1339:            }
1340:
1341:            /**
1342:             * Answer the IP Address of the remote server for the message being 
1343:             * processed.
1344:             * @return String
1345:             * @throws MessagingException
1346:             * @throws UnknownHostException
1347:             */
1348:            protected String computeRemoteAddress() throws MessagingException,
1349:                    UnknownHostException {
1350:                String domain = getRemoteDomain();
1351:                String address = null;
1352:                String validatedAddress = null;
1353:                int ipAddressStart = domain.indexOf('[');
1354:                int ipAddressEnd = -1;
1355:                if (ipAddressStart > -1)
1356:                    ipAddressEnd = domain.indexOf(']', ipAddressStart);
1357:                if (ipAddressEnd > -1)
1358:                    address = domain
1359:                            .substring(ipAddressStart + 1, ipAddressEnd);
1360:                else {
1361:                    int hostNameEnd = domain.indexOf(' ');
1362:                    if (hostNameEnd == -1)
1363:                        hostNameEnd = domain.length();
1364:                    address = domain.substring(0, hostNameEnd);
1365:                }
1366:                validatedAddress = org.apache.james.dnsserver.DNSServer
1367:                        .getByName(address).getHostAddress();
1368:
1369:                return validatedAddress;
1370:            }
1371:
1372:            /**
1373:             * Answer the Canonical host name of the remote server for the message 
1374:             * being processed.
1375:             * @return String
1376:             * @throws MessagingException
1377:             * @throws UnknownHostException
1378:             */
1379:            protected String computeRemoteHostName() throws MessagingException,
1380:                    UnknownHostException {
1381:                // These shenanigans are required to get the fully qualified
1382:                // hostname prior to JDK 1.4 in which get getCanonicalHostName()
1383:                // does the job for us
1384:                InetAddress addr1 = org.apache.james.dnsserver.DNSServer
1385:                        .getByName(getRemoteAddress());
1386:                InetAddress addr2 = org.apache.james.dnsserver.DNSServer
1387:                        .getByName(addr1.getHostAddress());
1388:                return addr2.getHostName();
1389:            }
1390:
1391:            /**
1392:             * Returns the remoteAddress, lazily initialised as required.
1393:             * @return String
1394:             */
1395:            protected String getRemoteAddress() throws MessagingException,
1396:                    UnknownHostException {
1397:                String remoteAddress;
1398:                if (null == (remoteAddress = getRemoteAddressBasic())) {
1399:                    updateRemoteAddress();
1400:                    return getRemoteAddress();
1401:                }
1402:                return remoteAddress;
1403:            }
1404:
1405:            /**
1406:             * Returns the remoteAddress.
1407:             * @return String
1408:             */
1409:            private String getRemoteAddressBasic() {
1410:                return fieldRemoteAddress;
1411:            }
1412:
1413:            /**
1414:             * Returns the remoteHostName, lazily initialised as required.
1415:             * @return String
1416:             */
1417:            protected String getRemoteHostName() throws MessagingException,
1418:                    UnknownHostException {
1419:                String remoteHostName;
1420:                if (null == (remoteHostName = getRemoteHostNameBasic())) {
1421:                    updateRemoteHostName();
1422:                    return getRemoteHostName();
1423:                }
1424:                return remoteHostName;
1425:            }
1426:
1427:            /**
1428:             * Returns the remoteHostName.
1429:             * @return String
1430:             */
1431:            private String getRemoteHostNameBasic() {
1432:                return fieldRemoteHostName;
1433:            }
1434:
1435:            /**
1436:             * Sets the remoteAddress.
1437:             * @param remoteAddress The remoteAddress to set
1438:             */
1439:            protected void setRemoteAddress(String remoteAddress) {
1440:                fieldRemoteAddress = remoteAddress;
1441:            }
1442:
1443:            /**
1444:             * Updates the remoteAddress.
1445:             */
1446:            protected void updateRemoteAddress() throws MessagingException,
1447:                    UnknownHostException {
1448:                setRemoteAddress(computeRemoteAddress());
1449:            }
1450:
1451:            /**
1452:             * Sets the remoteHostName.
1453:             * @param remoteHostName The remoteHostName to set
1454:             */
1455:            protected void setRemoteHostName(String remoteHostName) {
1456:                fieldRemoteHostName = remoteHostName;
1457:            }
1458:
1459:            /**
1460:             * Updates the remoteHostName.
1461:             */
1462:            protected void updateRemoteHostName() throws MessagingException,
1463:                    UnknownHostException {
1464:                setRemoteHostName(computeRemoteHostName());
1465:            }
1466:
1467:            /**
1468:             * Returns the rFC2822RECEIVEDHeaderFields.
1469:             * @return String
1470:             */
1471:            public static String getRFC2822RECEIVEDHeaderFields() {
1472:                return fieldRFC2822RECEIVEDHeaderFields;
1473:            }
1474:
1475:            /**
1476:             * Returns the maxMessageSizeExceeded, lazily initialised as required.
1477:             * @return Boolean
1478:             */
1479:            protected Boolean isMaxMessageSizeExceeded()
1480:                    throws MessagingException {
1481:                Boolean isMaxMessageSizeExceeded = null;
1482:                if (null == (isMaxMessageSizeExceeded = isMaxMessageSizeExceededBasic())) {
1483:                    updateMaxMessageSizeExceeded();
1484:                    return isMaxMessageSizeExceeded();
1485:                }
1486:                return isMaxMessageSizeExceeded;
1487:            }
1488:
1489:            /**
1490:             * Refreshes the maxMessageSizeExceeded.
1491:             */
1492:            protected void updateMaxMessageSizeExceeded()
1493:                    throws MessagingException {
1494:                setMaxMessageSizeExceeded(computeMaxMessageSizeExceeded());
1495:            }
1496:
1497:            /**
1498:             * Compute the maxMessageSizeExceeded.
1499:             * @return Boolean
1500:             */
1501:            protected Boolean computeMaxMessageSizeExceeded()
1502:                    throws MessagingException {
1503:                if (0 == getMaxMessageSizeLimit())
1504:                    return Boolean.FALSE;
1505:                return new Boolean(
1506:                        getMessageIn().getSize() > getMaxMessageSizeLimit());
1507:            }
1508:
1509:            /**
1510:             * Returns the maxMessageSizeExceeded.
1511:             * @return Boolean
1512:             */
1513:            private Boolean isMaxMessageSizeExceededBasic() {
1514:                return fieldMaxMessageSizeExceeded;
1515:            }
1516:
1517:            /**
1518:             * Sets the maxMessageSizeExceeded.
1519:             * @param maxMessageSizeExceeded The maxMessageSizeExceeded to set
1520:             */
1521:            protected void setMaxMessageSizeExceeded(
1522:                    Boolean maxMessageSizeExceeded) {
1523:                fieldMaxMessageSizeExceeded = maxMessageSizeExceeded;
1524:            }
1525:
1526:            /**
1527:             * Returns the remoteReceivedHeaderInvalid, lazily initialised.
1528:             * @return Boolean
1529:             */
1530:            protected Boolean isRemoteReceivedHeaderInvalid()
1531:                    throws MessagingException {
1532:                Boolean isInvalid = null;
1533:                if (null == (isInvalid = isRemoteReceivedHeaderInvalidBasic())) {
1534:                    updateRemoteReceivedHeaderInvalid();
1535:                    return isRemoteReceivedHeaderInvalid();
1536:                }
1537:                return isInvalid;
1538:            }
1539:
1540:            /**
1541:             * Computes the remoteReceivedHeaderInvalid.
1542:             * @return Boolean
1543:             */
1544:            protected Boolean computeRemoteReceivedHeaderInvalid()
1545:                    throws MessagingException {
1546:                Boolean isInvalid = Boolean.FALSE;
1547:                try {
1548:                    getRemoteAddress();
1549:                } catch (UnknownHostException e) {
1550:                    isInvalid = Boolean.TRUE;
1551:                }
1552:                return isInvalid;
1553:            }
1554:
1555:            /**
1556:             * Returns the remoteReceivedHeaderInvalid.
1557:             * @return Boolean
1558:             */
1559:            private Boolean isRemoteReceivedHeaderInvalidBasic() {
1560:                return fieldRemoteReceivedHeaderInvalid;
1561:            }
1562:
1563:            /**
1564:             * Sets the remoteReceivedHeaderInvalid.
1565:             * @param remoteReceivedHeaderInvalid The remoteReceivedHeaderInvalid to set
1566:             */
1567:            protected void setRemoteReceivedHeaderInvalid(
1568:                    Boolean remoteReceivedHeaderInvalid) {
1569:                fieldRemoteReceivedHeaderInvalid = remoteReceivedHeaderInvalid;
1570:            }
1571:
1572:            /**
1573:             * Updates the remoteReceivedHeaderInvalid.
1574:             */
1575:            protected void updateRemoteReceivedHeaderInvalid()
1576:                    throws MessagingException {
1577:                setRemoteReceivedHeaderInvalid(computeRemoteReceivedHeaderInvalid());
1578:            }
1579:
1580:            /**
1581:             * Returns the defaultSenderDomainPart.
1582:             * @return boolean
1583:             */
1584:            protected boolean isDefaultSenderDomainPart() {
1585:                return fieldDefaultSenderDomainPart;
1586:            }
1587:
1588:            /**
1589:             * Returns the defaultSenderLocalPart.
1590:             * @return boolean
1591:             */
1592:            protected boolean isDefaultSenderLocalPart() {
1593:                return fieldDefaultSenderLocalPart;
1594:            }
1595:
1596:            /**
1597:             * Sets the defaultSenderDomainPart.
1598:             * @param defaultSenderDomainPart The defaultSenderDomainPart to set
1599:             */
1600:            protected void setDefaultSenderDomainPart(
1601:                    boolean defaultSenderDomainPart) {
1602:                fieldDefaultSenderDomainPart = defaultSenderDomainPart;
1603:            }
1604:
1605:            /**
1606:             * Sets the defaultSenderLocalPart.
1607:             * @param defaultSenderLocalPart The defaultSenderLocalPart to set
1608:             */
1609:            protected void setDefaultSenderLocalPart(
1610:                    boolean defaultSenderLocalPart) {
1611:                fieldDefaultSenderLocalPart = defaultSenderLocalPart;
1612:            }
1613:
1614:            /**
1615:             * Returns the defaultRemoteAddress.
1616:             * @return boolean
1617:             */
1618:            protected boolean isDefaultRemoteAddress() {
1619:                return fieldDefaultRemoteAddress;
1620:            }
1621:
1622:            /**
1623:             * Sets the defaultRemoteAddress.
1624:             * @param defaultRemoteAddress The defaultRemoteAddress to set
1625:             */
1626:            protected void setDefaultRemoteAddress(boolean defaultRemoteAddress) {
1627:                fieldDefaultRemoteAddress = defaultRemoteAddress;
1628:            }
1629:
1630:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.