KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > james > fetchmail > MessageProcessor


1 /***********************************************************************
2  * Copyright (c) 2003-2004 The Apache Software Foundation. *
3  * All rights reserved. *
4  * ------------------------------------------------------------------- *
5  * Licensed under the Apache License, Version 2.0 (the "License"); you *
6  * may not use this file except in compliance with the License. You *
7  * may obtain a copy of the License at: *
8  * *
9  * http://www.apache.org/licenses/LICENSE-2.0 *
10  * *
11  * Unless required by applicable law or agreed to in writing, software *
12  * distributed under the License is distributed on an "AS IS" BASIS, *
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14  * implied. See the License for the specific language governing *
15  * permissions and limitations under the License. *
16  ***********************************************************************/

17  
18 package org.apache.james.fetchmail;
19
20 import java.io.InputStream;
21 import java.net.InetAddress;
22 import java.net.UnknownHostException;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Enumeration;
26 import java.util.Iterator;
27 import java.util.StringTokenizer;
28
29 import javax.mail.Address;
30 import javax.mail.Flags;
31 import javax.mail.Folder;
32 import javax.mail.MessagingException;
33 import javax.mail.Session;
34 import javax.mail.internet.InternetAddress;
35 import javax.mail.internet.InternetHeaders;
36 import javax.mail.internet.MimeMessage;
37 import javax.mail.internet.ParseException;
38
39 import org.apache.james.core.MailImpl;
40 import org.apache.james.util.RFC2822Headers;
41 import org.apache.mailet.Mail;
42 import org.apache.mailet.MailAddress;
43
44 /**
45  * <p>Class <code>MessageProcessor</code> handles the delivery of
46  * <code>MimeMessages</code> to the James input spool.</p>
47  *
48  * <p>Messages written to the input spool always have the following Mail
49  * Attributes set:</p>
50  * <dl>
51  * <dt>org.apache.james.fetchmail.taskName (java.lang.String)</dt>
52  * <dd>The name of the fetch task that processed the message</dd>
53  * <dt>org.apache.james.fetchmail.folderName (java.lang.String)</dt>
54  * <dd>The name of the folder from which the message was fetched</dd>
55  * </dl>
56  *
57  * <p>Messages written to the input spool have the following Mail Attributes
58  * set if the corresponding condition is satisfied:
59  * <dl>
60  * <dt>org.apache.james.fetchmail.isBlacklistedRecipient</dt>
61  * <dd>The recipient is in the configured blacklist</dd>
62  * <dt>org.apache.james.fetchmail.isMaxMessageSizeExceeded (java.lang.String)</dt>
63  * <dd>The message size exceeds the configured limit. An empty message is
64  * written to the input spool. The Mail Attribute value is a String
65  * representing the size of the original message in bytes.</dd>
66  * <dt>org.apache.james.fetchmail.isRecipientNotFound</dt>
67  * <dd>The recipient could not be found. Delivery is to the configured recipient.
68  * See the discussion of delivery to a sole intended recipient below.</dd>
69  * <dt>org.apache.james.fetchmail.isRemoteRecievedHeaderInvalid</dt>
70  * <dd>The Receieved header at the index specified by parameter
71  * <code>remoteReceivedHeaderIndex</code> is invalid.</dd>
72  * <dt>org.apache.james.fetchmail.isRemoteRecipient</dt>
73  * <dd>The recipient is on a remote host</dd>
74  * <dt>org.apache.james.fetchmail.isUserUndefined</dt>
75  * <dd>The recipient is on a localhost but not defined to James</dd>
76  * </dl>
77  *
78  * <p>Configuration settings -
79  * see <code>org.apache.james.fetchmail.ParsedConfiguration</code>
80  * - control the messages that are written to the James input spool, those that
81  * are rejected and what happens to messages that are rejected.</p>
82  *
83  * <p>Rejection processing is based on the following filters:</p>
84  * <dl>
85  * <dt>RejectRemoteRecipient</dt>
86  * <dd>Rejects recipients on remote hosts</dd>
87  * <dt>RejectBlacklistedRecipient</dt>
88  * <dd>Rejects recipients configured in a blacklist</dd>
89  * <dt>RejectUserUndefined</dt>
90  * <dd>Rejects recipients on local hosts who are not defined as James users</dd>
91  * <dt>RejectRecipientNotFound</dt>
92  * <dd>See the discussion of delivery to a sole intended recipient below</dd>
93  * <dt>RejectMaxMessageSizeExceeded</dt>
94  * <dd>Rejects messages whose size exceeds the configured limit</dd>
95  * <dt>RejectRemoteReceievedHeaderInvalid</dt>
96  * <dd>Rejects messages whose Received header is invalid.</dd>
97  * </dl>
98  *
99  * <p>Rejection processing is intentionally limited to managing the status of the
100  * messages that are rejected on the server from which they were fetched. View
101  * it as a simple automation of the manual processing an end-user would perform
102  * through a mail client. Messages may be marked as seen or be deleted.</p>
103  *
104  * <p>Further processing can be achieved by configuring to disable rejection for
105  * one or more filters. This enables Messages that would have been rejected to
106  * be written to the James input spool. The conditional Mail Attributes
107  * described above identify the filter states. The Matcher/Mailet chain can
108  * then be used to perform any further processing required, such as notifying
109  * the Postmaster and/or sender, marking the message for error processing, etc.</p>
110  *
111  * <p>Note that in the case of a message exceeding the message size limit, the
112  * message that is written to the input spool has no content. This enables
113  * configuration of a mailet notifying the sender that their mail has not been
114  * delivered due to its size while maintaining the purpose of the filter which is
115  * to avoid injecting excessively large messages into the input spool.</p>
116  *
117  * <p>Delivery is to a sole intended recipient. The recipient is determined in the
118  * following manner:</p>
119  *
120  * <ol>
121  * <li>If isIgnoreIntendedRecipient(), use the configured recipient</li>
122  * <li>If the Envelope contains a for: stanza, use the recipient in the stanza</li>
123  * <li>If the Message has a sole intended recipient, use this recipient</li>
124  * <li>If not rejectRecipientNotFound(), use the configured recipient</li>
125  * </ol>
126  *
127  * <p>If a recipient cannot be determined after these steps, the message is
128  * rejected.</p>
129  *
130  * <p>Every delivered message CURRENTLY has an "X-fetched-from" header added
131  * containing the name of the fetch task. Its primary uses are to detect bouncing
132  * mail and provide backwards compatibility with the fetchPop task that inserted
133  * this header to enable injected messages to be detected in the Matcher/Mailet
134  * chain. This header is DEPRECATED and WILL BE REMOVED in a future version of
135  * fetchmail. Use the Mail Attribute <code>org.apache.james.fetchmail.taskName</code>
136  * instead.
137  *
138  * <p><code>MessageProcessor</code> is as agnostic as it can be about the format
139  * and contents of the messages it delivers. There are no RFCs that govern its
140  * behavior. The most releveant RFCs relate to the exchange of messages between
141  * MTA servers, but not POP3 or IMAP servers which are normally end-point
142  * servers and not expected to re-inject mail into MTAs. None the less, the
143  * intent is to conform to the 'spirit' of the RFCs.
144  * <code>MessageProcessor</code> relies on the MTA (James in this
145  * implementation) to manage and validate the injected mail just as it would
146  * when receiving mail from an upstream MTA.</p>
147  *
148  * <p>The only correction applied by <code>MessageProcessor</code> is to correct a
149  * partial originator address. If the originator address has a valid user part
150  * but no domain part, a domain part is added. The added domain is either the
151  * default domain specified in the configuration, or if not specified, the
152  * fully qualified name of the machine on which the fetch task is running.</p>
153  *
154  * <p>The status of messages on the server from which they were fetched that
155  * cannot be injected into the input spool due to non-correctable errors is
156  * determined by the undeliverable configuration options.</p>
157  *
158  * <p>Creation Date: 27-May-03</p>
159  *
160  */

161 public class MessageProcessor extends ProcessorAbstract
162 {
163     private MimeMessage fieldMessageIn;
164
165     /**
166      * Recipient cannot be found
167      */

168     private boolean fieldRecipientNotFound = false;
169
170     /**
171      * Recipient is a local user on a local host
172      */

173     private boolean fieldRemoteRecipient = true;
174
175     /**
176      * The mail's Received header at index remoteReceivedHeaderIndex is invalid.
177      */

178     private Boolean fieldRemoteReceivedHeaderInvalid;
179
180     /**
181      * Recipient is not a local user
182      */

183     private boolean fieldUserUndefined = false;
184     
185     /**
186      * The Maximum Message has been exceeded
187      */

188     private Boolean fieldMaxMessageSizeExceeded;
189     
190     
191     /**
192      * Field names for an RFC2822 compliant RECEIVED Header
193      */

194     static final private String fieldRFC2822RECEIVEDHeaderFields =
195         "from by via with id for ;";
196     
197     /**
198      * Recipient is blacklisted
199      */

200     private boolean fieldBlacklistedRecipient = false;
201     
202     /**
203      * The RFC2822 compliant "Received : from" domain
204      */

205     private String fieldRemoteDomain;
206     
207     /**
208      * The remote address derived from the remote domain
209      */

210     private String fieldRemoteAddress;
211     
212     /**
213      * The remote host name derived from the remote domain
214      */

215     private String fieldRemoteHostName;
216     
217     /**
218      * Constructor for MessageProcessor.
219      *
220      * @param account
221      */

222     private MessageProcessor(Account account)
223     {
224         super(account);
225     }
226     
227     /**
228      * Constructor for MessageProcessor.
229      *
230      * @param messageIn
231      * @param account
232      */

233
234     MessageProcessor(
235         MimeMessage messageIn,
236          Account account)
237     {
238         this(account);
239         setMessageIn(messageIn);
240     }
241
242     
243     /**
244      * Method process attempts to deliver a fetched message.
245      *
246      * @see org.apache.james.fetchmail.ProcessorAbstract#process()
247      */

248     public void process() throws MessagingException
249     {
250         // Log delivery attempt
251
if (getLogger().isDebugEnabled())
252         {
253             StringBuffer logMessageBuffer =
254                 new StringBuffer("Attempting delivery of message with id. ");
255             logMessageBuffer.append(getMessageIn().getMessageID());
256             getLogger().debug(logMessageBuffer.toString());
257         }
258
259         // Determine the intended recipient
260
MailAddress intendedRecipient = getIntendedRecipient();
261         setRecipientNotFound(null == intendedRecipient);
262
263         if (isRecipientNotFound())
264         {
265             if (isDeferRecipientNotFound())
266             {
267
268                 String messageID = getMessageIn().getMessageID();
269                 if (!getDeferredRecipientNotFoundMessageIDs()
270                     .contains(messageID))
271                 {
272                     getDeferredRecipientNotFoundMessageIDs().add(messageID);
273                     if (getLogger().isDebugEnabled())
274                     {
275                         StringBuffer messageBuffer =
276                             new StringBuffer("Deferred processing of message for which the intended recipient could not be found. Message ID: ");
277                         messageBuffer.append(messageID);
278                         getLogger().debug(messageBuffer.toString());
279                     }
280                     return;
281                 }
282                 else
283                 {
284                     getDeferredRecipientNotFoundMessageIDs().remove(messageID);
285                     if (getLogger().isDebugEnabled())
286                     {
287                         StringBuffer messageBuffer =
288                             new StringBuffer("Processing deferred message for which the intended recipient could not be found. Message ID: ");
289                         messageBuffer.append(messageID);
290                         getLogger().debug(messageBuffer.toString());
291                     }
292                 }
293             }
294
295             if (isRejectRecipientNotFound())
296             {
297                 rejectRecipientNotFound();
298                 return;
299             }
300             intendedRecipient = getRecipient();
301             StringBuffer messageBuffer =
302                 new StringBuffer("Intended recipient not found. Using configured recipient as new envelope recipient - ");
303             messageBuffer.append(intendedRecipient);
304             messageBuffer.append('.');
305             logStatusInfo(messageBuffer.toString());
306         }
307
308         // Set the filter states
309
setBlacklistedRecipient(isBlacklistedRecipient(intendedRecipient));
310         setRemoteRecipient(!isLocalServer(intendedRecipient));
311         setUserUndefined(!isLocalRecipient(intendedRecipient));
312
313         // Apply the filters. Return if rejected
314
if (isRejectBlacklisted() && isBlacklistedRecipient())
315         {
316             rejectBlacklistedRecipient(intendedRecipient);
317             return;
318         }
319
320         if (isRejectRemoteRecipient() && isRemoteRecipient())
321         {
322             rejectRemoteRecipient(intendedRecipient);
323             return;
324         }
325
326         if (isRejectUserUndefined() && isUserUndefined())
327         {
328             rejectUserUndefined(intendedRecipient);
329             return;
330         }
331
332         if (isRejectMaxMessageSizeExceeded()
333             && isMaxMessageSizeExceeded().booleanValue())
334         {
335             rejectMaxMessageSizeExceeded(getMessageIn().getSize());
336             return;
337         }
338         
339         if (isRejectRemoteReceivedHeaderInvalid()
340             && isRemoteReceivedHeaderInvalid().booleanValue())
341         {
342             rejectRemoteReceivedHeaderInvalid();
343             return;
344         }
345
346         // Create the mail
347
// If any of the mail addresses are malformed, we will get a
348
// ParseException.
349
// If the IP address and host name for the remote domain cannot
350
// be found, we will get an UnknownHostException.
351
// In both cases, we log the problem and
352
// return. The message disposition is defined by the
353
// <undeliverable> attributes.
354
Mail mail = null;
355         try
356         {
357             mail = createMail(createMessage(), intendedRecipient);
358         }
359         catch (ParseException ex)
360         {
361             handleParseException(ex);
362             return;
363         }
364         catch (UnknownHostException ex)
365         {
366             handleUnknownHostException(ex);
367             return;
368         }
369
370         addMailAttributes(mail);
371         addErrorMessages(mail);
372
373         // If this mail is bouncing move it to the ERROR repository
374
if (isBouncing())
375         {
376             handleBouncing(mail);
377             return;
378         }
379
380         // OK, lets send that mail!
381
sendMail(mail);
382     }
383
384     /**
385      * Method rejectRemoteRecipient.
386      * @param recipient
387      * @throws MessagingException
388      */

389     protected void rejectRemoteRecipient(MailAddress recipient)
390         throws MessagingException
391     {
392         // Update the flags of the received message
393
if (!isLeaveRemoteRecipient())
394             setMessageDeleted();
395
396         if (isMarkRemoteRecipientSeen())
397             setMessageSeen();
398
399         StringBuffer messageBuffer =
400             new StringBuffer("Rejected mail intended for remote recipient: ");
401         messageBuffer.append(recipient);
402         messageBuffer.append('.');
403         logStatusInfo(messageBuffer.toString());
404
405         return;
406     }
407     
408     /**
409      * Method rejectBlacklistedRecipient.
410      * @param recipient
411      * @throws MessagingException
412      */

413     protected void rejectBlacklistedRecipient(MailAddress recipient)
414         throws MessagingException
415     {
416         // Update the flags of the received message
417
if (!isLeaveBlacklisted())
418             setMessageDeleted();
419         if (isMarkBlacklistedSeen())
420             setMessageSeen();
421
422         StringBuffer messageBuffer =
423             new StringBuffer("Rejected mail intended for blacklisted recipient: ");
424         messageBuffer.append(recipient);
425         messageBuffer.append('.');
426         logStatusInfo(messageBuffer.toString());
427
428         return;
429     }
430
431     /**
432      * Method rejectRecipientNotFound.
433      * @throws MessagingException
434      */

435     protected void rejectRecipientNotFound() throws MessagingException
436     {
437         // Update the flags of the received message
438
if (!isLeaveRecipientNotFound())
439             setMessageDeleted();
440
441         if (isMarkRecipientNotFoundSeen())
442             setMessageSeen();
443
444         StringBuffer messageBuffer =
445             new StringBuffer("Rejected mail for which a sole intended recipient could not be found.");
446         messageBuffer.append(" Recipients: ");
447         Address[] allRecipients = getMessageIn().getAllRecipients();
448         for (int i = 0; i < allRecipients.length; i++)
449         {
450             messageBuffer.append(allRecipients[i]);
451             messageBuffer.append(' ');
452         }
453         messageBuffer.append('.');
454         logStatusInfo(messageBuffer.toString());
455         return;
456     }
457     
458     /**
459      * Method rejectUserUndefined.
460      * @param recipient
461      * @throws MessagingException
462      */

463     protected void rejectUserUndefined(MailAddress recipient)
464         throws MessagingException
465     {
466         // Update the flags of the received message
467
if (!isLeaveUserUndefined())
468             setMessageDeleted();
469
470         if (isMarkUserUndefinedSeen())
471             setMessageSeen();
472
473         StringBuffer messageBuffer =
474             new StringBuffer("Rejected mail intended for undefined user: ");
475         messageBuffer.append(recipient);
476         messageBuffer.append('.');
477         logStatusInfo(messageBuffer.toString());
478
479         return;
480     }
481     
482     /**
483      * Method rejectMaxMessageSizeExceeded.
484      * @param message size
485      * @throws MessagingException
486      */

487     protected void rejectMaxMessageSizeExceeded(int messageSize)
488         throws MessagingException
489     {
490         // Update the flags of the received message
491
if (!isLeaveMaxMessageSizeExceeded())
492             setMessageDeleted();
493
494         if (isMarkMaxMessageSizeExceededSeen())
495             setMessageSeen();
496
497         StringBuffer messageBuffer =
498             new StringBuffer("Rejected mail exceeding message size limit. Message size: ");
499         messageBuffer.append(messageSize/1024);
500         messageBuffer.append("KB.");
501         logStatusInfo(messageBuffer.toString());
502
503         return;
504     }
505     
506     /**
507      * Method rejectRemoteReceivedHeaderInvalid.
508      * @throws MessagingException
509      */

510     protected void rejectRemoteReceivedHeaderInvalid()
511         throws MessagingException
512     {
513         // Update the flags of the received message
514
if (!isLeaveRemoteReceivedHeaderInvalid())
515             setMessageDeleted();
516
517         if (isMarkRemoteReceivedHeaderInvalidSeen())
518             setMessageSeen();
519
520         StringBuffer messageBuffer =
521             new StringBuffer("Rejected mail with an invalid Received: header at index ");
522         messageBuffer.append(getRemoteReceivedHeaderIndex());
523         messageBuffer.append(".");
524         logStatusInfo(messageBuffer.toString());
525         return;
526     }
527     
528     /**
529      * <p>Method createMessage answers a new <code>MimeMessage</code> from the
530      * fetched message.</p>
531      *
532      * <p>If the maximum message size is exceeded, an empty message is created,
533      * else the new message is a copy of the received message.</p>
534      *
535      * @return MimeMessage
536      * @throws MessagingException
537      */

538     protected MimeMessage createMessage() throws MessagingException
539     {
540         // Create a new messsage from the received message
541
MimeMessage messageOut = null;
542         if (isMaxMessageSizeExceeded().booleanValue())
543             messageOut = createEmptyMessage();
544         else
545             messageOut = new MimeMessage(getMessageIn());
546
547         // set the X-fetched headers
548
// Note this is still required to detect bouncing mail and
549
// for backwards compatibility with fetchPop
550
messageOut.addHeader("X-fetched-from", getFetchTaskName());
551
552         return messageOut;
553     }
554     
555     /**
556      * Method createEmptyMessage answers a new
557      * <code>MimeMessage</code> from the fetched message with the message
558      * contents removed.
559      *
560      * @return MimeMessage
561      * @throws MessagingException
562      */

563     protected MimeMessage createEmptyMessage()
564         throws MessagingException
565     {
566         // Create an empty messsage
567
MimeMessage messageOut = new MimeMessage(getSession());
568
569         // Propogate the headers and subject
570
Enumeration headersInEnum = getMessageIn().getAllHeaderLines();
571         while (headersInEnum.hasMoreElements())
572             messageOut.addHeaderLine((String) headersInEnum.nextElement());
573         messageOut.setSubject(getMessageIn().getSubject());
574
575         // Add empty text
576
messageOut.setText("");
577
578         // Save
579
messageOut.saveChanges();
580
581         return messageOut;
582     }
583
584     /**
585      * Method createMail creates a new <code>Mail</code>.
586      *
587      * @param message
588      * @param recipient
589      * @return Mail
590      * @throws MessagingException
591      */

592     protected Mail createMail(MimeMessage message, MailAddress recipient)
593         throws MessagingException, UnknownHostException
594     {
595         Collection recipients = new ArrayList(1);
596         recipients.add(recipient);
597         MailImpl mail =
598             new MailImpl(getServer().getId(), getSender(), recipients, message);
599         // Ensure the mail is created with non-null remote host name and address,
600
// otherwise the Mailet chain may go splat!
601
if (getRemoteAddress() == null || getRemoteHostName() == null)
602         {
603             mail.setRemoteAddr("127.0.0.1");
604             mail.setRemoteHost("localhost");
605         }
606         else
607         {
608             mail.setRemoteAddr(getRemoteAddress());
609             mail.setRemoteHost(getRemoteHostName());
610         }
611
612         if (getLogger().isDebugEnabled())
613         {
614             StringBuffer messageBuffer =
615                 new StringBuffer("Created mail with name: ");
616             messageBuffer.append(mail.getName());
617             messageBuffer.append(", sender: ");
618             messageBuffer.append(mail.getSender());
619             messageBuffer.append(", recipients: ");
620             Iterator recipientIterator = mail.getRecipients().iterator();
621             while (recipientIterator.hasNext())
622             {
623                 messageBuffer.append(recipientIterator.next());
624                 messageBuffer.append(' ');
625             }
626             messageBuffer.append(", remote address: ");
627             messageBuffer.append(mail.getRemoteAddr());
628             messageBuffer.append(", remote host name: ");
629             messageBuffer.append(mail.getRemoteHost());
630             messageBuffer.append('.');
631             getLogger().debug(messageBuffer.toString());
632         }
633         return mail;
634     }
635      
636
637     /**
638      * Method getSender answers a <code>MailAddress</code> for the sender.
639      *
640      * @return MailAddress
641      * @throws MessagingException
642      */

643     protected MailAddress getSender() throws MessagingException
644     {
645         String from = "FETCHMAIL-SERVICE";
646         try {
647             from = ((InternetAddress) getMessageIn().getFrom()[0]).getAddress().trim();
648         }
649         catch (Exception _) {
650             getLogger().info("Could not identify sender -- using default value");
651         }
652
653         InternetAddress internetAddress = null;
654
655         // Check for domain part, add default if missing
656
if (from.indexOf('@') < 0)
657         {
658             StringBuffer fromBuffer = new StringBuffer(from);
659             fromBuffer.append('@');
660             fromBuffer.append(getDefaultDomainName());
661             internetAddress = new InternetAddress(fromBuffer.toString());
662         }
663         else
664             internetAddress = new InternetAddress(from);
665
666         return new MailAddress(internetAddress);
667     }
668     
669     /**
670      * <p>Method computeRemoteDomain answers a <code>String</code> that is the
671      * RFC2822 compliant "Received : from" domain extracted from the message
672      * being processed.</p>
673      *
674      * <p>Normally this is the domain that sent the message to the host for the
675      * message store as reported by the second "received" header. The index of
676      * the header to use is specified by the configuration parameter
677      * <code>RemoteReceivedHeaderIndex</code>. If a header at this index does
678      * not exist, the domain of the successively closer "received" headers
679      * is tried until they are exhausted, then "localhost" is used.</p>
680      *
681      * @return String
682      */

683     protected String computeRemoteDomain() throws MessagingException
684     {
685         StringBuffer domainBuffer = new StringBuffer();
686         String[] headers = null;
687         if (getRemoteReceivedHeaderIndex() > -1)
688               getMessageIn().getHeader(RFC2822Headers.RECEIVED);
689               
690         if (null != headers)
691         {
692             // If there are RECEIVED headers and the index to begin at is greater
693
// than -1, try and extract the domain
694
if (headers.length > 0)
695             {
696                 final String headerTokens = " \n\r";
697
698                 // Search the headers for a domain
699
for (int headerIndex =
700                     headers.length > getRemoteReceivedHeaderIndex()
701                         ? getRemoteReceivedHeaderIndex()
702                         : headers.length - 1;
703                     headerIndex >= 0 && domainBuffer.length() == 0;
704                     headerIndex--)
705                 {
706                     // Find the "from" token
707
StringTokenizer tokenizer =
708                         new StringTokenizer(headers[headerIndex], headerTokens);
709                     boolean inFrom = false;
710                     while (!inFrom && tokenizer.hasMoreTokens())
711                         inFrom = tokenizer.nextToken().equals("from");
712
713                     // Add subsequent tokens to the domain buffer until another
714
// field is encountered or there are no more tokens
715
while (inFrom && tokenizer.hasMoreTokens())
716                     {
717                         String token = tokenizer.nextToken();
718                         if (inFrom =
719                             getRFC2822RECEIVEDHeaderFields().indexOf(token)
720                                 == -1)
721                         {
722                             domainBuffer.append(token);
723                             domainBuffer.append(' ');
724                         }
725                     }
726                 }
727             }
728         }
729
730         // Default is "localhost"
731
if (domainBuffer.length() == 0)
732             domainBuffer.append("localhost");
733
734         return domainBuffer.toString().trim();
735     }
736     
737     /**
738      * Method handleBouncing sets the Mail state to ERROR and delete from
739      * the message store.
740      *
741      * @param mail
742      */

743     protected void handleBouncing(Mail mail) throws MessagingException
744     {
745         mail.setState(Mail.ERROR);
746         setMessageDeleted();
747
748         mail.setErrorMessage(
749             "This mail from FetchMail task "
750                 + getFetchTaskName()
751                 + " seems to be bouncing!");
752         logStatusError("Message is bouncing! Deleted from message store and moved to the Error repository.");
753     }
754     
755     /**
756      * Method handleParseException.
757      * @param ex
758      * @throws MessagingException
759      */

760     protected void handleParseException(ParseException ex)
761         throws MessagingException
762     {
763         // Update the flags of the received message
764
if (!isLeaveUndeliverable())
765             setMessageDeleted();
766         if (isMarkUndeliverableSeen())
767             setMessageSeen();
768         logStatusWarn("Message could not be delivered due to an error parsing a mail address.");
769         if (getLogger().isDebugEnabled())
770         {
771             StringBuffer messageBuffer =
772                 new StringBuffer("UNDELIVERABLE Message ID: ");
773             messageBuffer.append(getMessageIn().getMessageID());
774             getLogger().debug(messageBuffer.toString(), ex);
775         }
776     }
777     
778     /**
779      * Method handleUnknownHostException.
780      * @param ex
781      * @throws MessagingException
782      */

783     protected void handleUnknownHostException(UnknownHostException ex)
784         throws MessagingException
785     {
786         // Update the flags of the received message
787
if (!isLeaveUndeliverable())
788             setMessageDeleted();
789     
790         if (isMarkUndeliverableSeen())
791             setMessageSeen();
792     
793         logStatusWarn("Message could not be delivered due to an error determining the remote domain.");
794         if (getLogger().isDebugEnabled())
795         {
796             StringBuffer messageBuffer =
797                 new StringBuffer("UNDELIVERABLE Message ID: ");
798             messageBuffer.append(getMessageIn().getMessageID());
799             getLogger().debug(messageBuffer.toString(), ex);
800         }
801     }
802     
803     /**
804      * Method isLocalRecipient.
805      * @param recipient
806      * @return boolean
807      */

808     protected boolean isLocalRecipient(MailAddress recipient)
809     {
810         return isLocalUser(recipient) && isLocalServer(recipient);
811     }
812     
813     /**
814      * Method isLocalServer.
815      * @param recipient
816      * @return boolean
817      */

818     protected boolean isLocalServer(MailAddress recipient)
819     {
820         return getServer().isLocalServer(recipient.getHost());
821     }
822     
823     /**
824      * Method isLocalUser.
825      * @param recipient
826      * @return boolean
827      */

828     protected boolean isLocalUser(MailAddress recipient)
829     {
830         return getLocalUsers().containsCaseInsensitive(recipient.getUser());
831     }
832     
833     /**
834      * Method isBlacklistedRecipient.
835      * @param recipient
836      * @return boolean
837      */

838     protected boolean isBlacklistedRecipient(MailAddress recipient)
839     {
840         return getBlacklist().contains(recipient);
841     }
842
843     /**
844      * Check if this mail has been bouncing by counting the X-fetched-from
845      * headers for this task
846      *
847      * @return boolean
848      */

849     protected boolean isBouncing() throws MessagingException
850     {
851         Enumeration enum =
852             getMessageIn().getMatchingHeaderLines(
853                 new String[] { "X-fetched-from" });
854         int count = 0;
855         while (enum.hasMoreElements())
856         {
857             String header = (String) enum.nextElement();
858             if (header.equals(getFetchTaskName()))
859                 count++;
860         }
861         return count >= 3;
862     }
863     
864     /**
865      * Method sendMail.
866      * @param mail
867      * @throws MessagingException
868      */

869     protected void sendMail(Mail mail) throws MessagingException
870     {
871         // send the mail
872
getServer().sendMail(mail);
873
874         // Update the flags of the received message
875
if (!isLeave())
876             setMessageDeleted();
877
878         if (isMarkSeen())
879             setMessageSeen();
880
881         // Log the status
882
StringBuffer messageBuffer =
883             new StringBuffer("Spooled message to recipients: ");
884         Iterator recipientIterator = mail.getRecipients().iterator();
885         while (recipientIterator.hasNext())
886         {
887             messageBuffer.append(recipientIterator.next());
888             messageBuffer.append(' ');
889         }
890         messageBuffer.append('.');
891         logStatusInfo(messageBuffer.toString());
892     }
893
894
895     /**
896      * Method getEnvelopeRecipient answers the recipient if found else null.
897      *
898      * Try and parse the "for" parameter from a Received header
899      * Maybe not the most accurate parsing in the world but it should do
900      * I opted not to use ORO (maybe I should have)
901      *
902      * @param msg
903      * @return String
904      */

905
906     protected String getEnvelopeRecipient(MimeMessage msg) throws MessagingException
907     {
908         try
909         {
910             Enumeration enum =
911                 msg.getMatchingHeaderLines(new String[] { "Received" });
912             while (enum.hasMoreElements())
913             {
914                 String received = (String) enum.nextElement();
915
916                 int nextSearchAt = 0;
917                 int i = 0;
918                 int start = 0;
919                 int end = 0;
920                 boolean hasBracket = false;
921                 boolean usableAddress = false;
922                 while (!usableAddress && (i != -1))
923                 {
924                     hasBracket = false;
925                     i = received.indexOf("for ", nextSearchAt);
926                     if (i > 0)
927                     {
928                         start = i + 4;
929                         end = 0;
930                         nextSearchAt = start;
931                         for (int c = start; c < received.length(); c++)
932                         {
933                             char ch = received.charAt(c);
934                             switch (ch)
935                             {
936                                 case '<' :
937                                     hasBracket = true;
938                                     continue;
939                                 case '@' :
940                                     usableAddress = true;
941                                     continue;
942                                 case ' ' :
943                                     end = c;
944                                     break;
945                                 case ';' :
946                                     end = c;
947                                     break;
948                             }
949                             if (end > 0)
950                                 break;
951                         }
952                     }
953                 }
954                 if (usableAddress)
955                 {
956                     // lets try and grab the email address
957
String mailFor = received.substring(start, end);
958
959                     // strip the <> around the address if there are any
960
if (mailFor.startsWith("<") && mailFor.endsWith(">"))
961                         mailFor = mailFor.substring(1, (mailFor.length() - 1));
962
963                     return mailFor;
964                 }
965             }
966         }
967         catch (MessagingException me)
968         {
969             logStatusWarn("No Received headers found.");
970         }
971         return null;
972     }
973     
974     /**
975      * Method getIntendedRecipient answers the sole intended recipient else null.
976      *
977      * @return MailAddress
978      * @throws MessagingException
979      */

980     protected MailAddress getIntendedRecipient() throws MessagingException
981     {
982         // If the original recipient should be ignored, answer the
983
// hard-coded recipient
984
if (isIgnoreRecipientHeader())
985         {
986             StringBuffer messageBuffer =
987                 new StringBuffer("Ignoring recipient header. Using configured recipient as new envelope recipient: ");
988             messageBuffer.append(getRecipient());
989             messageBuffer.append('.');
990             logStatusInfo(messageBuffer.toString());
991             return getRecipient();
992         }
993
994         // If we can determine who the message was received for, answer
995
// the target recipient
996
String targetRecipient = getEnvelopeRecipient(getMessageIn());
997         if (targetRecipient != null)
998         {
999             MailAddress recipient = new MailAddress(targetRecipient);
1000            StringBuffer messageBuffer =
1001                new StringBuffer("Using original envelope recipient as new envelope recipient: ");
1002            messageBuffer.append(recipient);
1003            messageBuffer.append('.');
1004            logStatusInfo(messageBuffer.toString());
1005            return recipient;
1006        }
1007
1008        // If we can determine the intended recipient from all of the recipients,
1009
// answer the intended recipient. This requires that there is exactly one
1010
// recipient answered by getAllRecipients(), which examines the TO: CC: and
1011
// BCC: headers
1012
Address[] allRecipients = getMessageIn().getAllRecipients();
1013        if (allRecipients.length == 1)
1014        {
1015            MailAddress recipient =
1016                new MailAddress((InternetAddress) allRecipients[0]);
1017            StringBuffer messageBuffer =
1018                new StringBuffer("Using sole recipient header address as new envelope recipient: ");
1019            messageBuffer.append(recipient);
1020            messageBuffer.append('.');
1021            logStatusInfo(messageBuffer.toString());
1022            return recipient;
1023        }
1024
1025        return null;
1026    }
1027
1028    /**
1029     * Returns the messageIn.
1030     * @return MimeMessage
1031     */

1032    protected MimeMessage getMessageIn()
1033    {
1034        return fieldMessageIn;
1035    }
1036
1037    /**
1038     * Sets the messageIn.
1039     * @param messageIn The messageIn to set
1040     */

1041    protected void setMessageIn(MimeMessage messageIn)
1042    {
1043        fieldMessageIn = messageIn;
1044    }
1045
1046    /**
1047     * Returns the localRecipient.
1048     * @return boolean
1049     */

1050    protected boolean isRemoteRecipient()
1051    {
1052        return fieldRemoteRecipient;
1053    }
1054    
1055    /**
1056     * Returns <code>boolean</code> indicating if the message to be delivered
1057     * was unprocessed in a previous delivery attempt.
1058     * @return boolean
1059     */

1060    protected boolean isPreviouslyUnprocessed()
1061    {
1062        return true;
1063    }
1064    
1065    /**
1066     * Log the status of the current message as INFO.
1067     * @param detailMsg
1068     */

1069    protected void logStatusInfo(String detailMsg) throws MessagingException
1070    {
1071        getLogger().info(getStatusReport(detailMsg).toString());
1072    }
1073
1074    /**
1075     * Log the status the current message as WARN.
1076     * @param detailMsg
1077     */

1078    protected void logStatusWarn(String detailMsg) throws MessagingException
1079    {
1080        getLogger().warn(getStatusReport(detailMsg).toString());
1081    }
1082    
1083    /**
1084     * Log the status the current message as ERROR.
1085     * @param detailMsg
1086     */

1087    protected void logStatusError(String detailMsg) throws MessagingException
1088    {
1089        getLogger().error(getStatusReport(detailMsg).toString());
1090    }
1091
1092    /**
1093     * Answer a <code>StringBuffer</code> containing a message reflecting
1094     * the current status of the message being processed.
1095     *
1096     * @param detailMsg
1097     * @return StringBuffer
1098     */

1099    protected StringBuffer getStatusReport(String detailMsg) throws MessagingException
1100    {
1101        StringBuffer messageBuffer = new StringBuffer(detailMsg);
1102        if (detailMsg.length() > 0)
1103            messageBuffer.append(' ');
1104        messageBuffer.append("Message ID: ");
1105        messageBuffer.append(getMessageIn().getMessageID());
1106        messageBuffer.append(". Flags: Seen = ");
1107        messageBuffer.append(new Boolean(isMessageSeen()));
1108        messageBuffer.append(", Delete = ");
1109        messageBuffer.append(new Boolean(isMessageDeleted()));
1110        messageBuffer.append('.');
1111        return messageBuffer;
1112    }
1113    
1114    /**
1115     * Returns the userUndefined.
1116     * @return boolean
1117     */

1118    protected boolean isUserUndefined()
1119    {
1120        return fieldUserUndefined;
1121    }
1122    
1123    /**
1124     * Is the DELETED flag set?
1125     * @throws MessagingException
1126     */

1127    protected boolean isMessageDeleted() throws MessagingException
1128    {
1129       return getMessageIn().isSet(Flags.Flag.DELETED);
1130    }
1131    
1132    /**
1133     * Is the SEEN flag set?
1134     * @throws MessagingException
1135     */

1136    protected boolean isMessageSeen() throws MessagingException
1137    {
1138       return getMessageIn().isSet(Flags.Flag.SEEN);
1139    }
1140    
1141    /**
1142     * Set the DELETED flag.
1143     * @throws MessagingException
1144     */

1145    protected void setMessageDeleted() throws MessagingException
1146    {
1147            getMessageIn().setFlag(Flags.Flag.DELETED, true);
1148    }
1149    
1150    /* /**
1151     * Set the SEEN flag.
1152     * @throws MessagingException
1153     */

1154    protected void setMessageSeen() throws MessagingException
1155    {
1156        // If the Seen flag is not handled by the folder
1157
// allow a handler to do whatever it deems necessary
1158
if (!getMessageIn()
1159            .getFolder()
1160            .getPermanentFlags()
1161            .contains(Flags.Flag.SEEN))
1162            handleMarkSeenNotPermanent();
1163        else
1164            getMessageIn().setFlag(Flags.Flag.SEEN, true);
1165    }
1166    
1167    /**
1168     * <p>Handler for when the folder does not support the SEEN flag.
1169     * The default behaviour implemented here is to log a warning and set the
1170     * flag anyway.</p>
1171     *
1172     * <p> Subclasses may choose to override this and implement their own
1173     * solutions.</p>
1174     *
1175     * @throws MessagingException
1176     */

1177    protected void handleMarkSeenNotPermanent() throws MessagingException
1178    {
1179        getMessageIn().setFlag(Flags.Flag.SEEN, true);
1180        logStatusWarn("Message marked as SEEN, but the folder does not support a permanent SEEN flag.");
1181    }
1182
1183    /**
1184     * Returns the Blacklisted.
1185     * @return boolean
1186     */

1187    protected boolean isBlacklistedRecipient()
1188    {
1189        return fieldBlacklistedRecipient;
1190    }
1191
1192    /**
1193     * Sets the localRecipient.
1194     * @param localRecipient The localRecipient to set
1195     */

1196    protected void setRemoteRecipient(boolean localRecipient)
1197    {
1198        fieldRemoteRecipient = localRecipient;
1199    }
1200
1201    /**
1202     * Sets the userUndefined.
1203     * @param userUndefined The userUndefined to set
1204     */

1205    protected void setUserUndefined(boolean userUndefined)
1206    {
1207        fieldUserUndefined = userUndefined;
1208    }
1209    
1210    /**
1211     * Adds the mail attributes to a <code>Mail</code>.
1212     * @param aMail a Mail instance
1213     */

1214    protected void addMailAttributes(Mail aMail) throws MessagingException
1215    {
1216        aMail.setAttribute(
1217            getAttributePrefix() + "taskName",
1218            getFetchTaskName());
1219
1220        aMail.setAttribute(
1221            getAttributePrefix() + "folderName",
1222            getMessageIn().getFolder().getFullName());
1223
1224        if (isRemoteRecipient())
1225            aMail.setAttribute(
1226                getAttributePrefix() + "isRemoteRecipient",
1227                null);
1228
1229        if (isUserUndefined())
1230            aMail.setAttribute(getAttributePrefix() + "isUserUndefined", null);
1231
1232        if (isBlacklistedRecipient())
1233            aMail.setAttribute(
1234                getAttributePrefix() + "isBlacklistedRecipient",
1235                null);
1236
1237        if (isRecipientNotFound())
1238            aMail.setAttribute(
1239                getAttributePrefix() + "isRecipientNotFound",
1240                null);
1241
1242        if (isMaxMessageSizeExceeded().booleanValue())
1243            aMail.setAttribute(
1244                getAttributePrefix() + "isMaxMessageSizeExceeded",
1245                new Integer(getMessageIn().getSize()).toString());
1246                
1247        if (isRemoteReceivedHeaderInvalid().booleanValue())
1248            aMail.setAttribute(
1249                getAttributePrefix() + "isRemoteReceivedHeaderInvalid",
1250                null);
1251    }
1252
1253    /**
1254     * Adds any required error messages to a <code>Mail</code>.
1255     * @param aMail a Mail instance
1256     */

1257    protected void addErrorMessages(Mail mail) throws MessagingException
1258    {
1259        if (isMaxMessageSizeExceeded().booleanValue())
1260        {
1261            StringBuffer msgBuffer =
1262                new StringBuffer("550 - Rejected - This message has been rejected as the message size of ");
1263            msgBuffer.append(getMessageIn().getSize() * 1000 / 1024 / 1000f);
1264            msgBuffer.append("KB exceeds the maximum permitted size of ");
1265            msgBuffer.append(getMaxMessageSizeLimit() / 1024);
1266            msgBuffer.append("KB.");
1267            mail.setErrorMessage(msgBuffer.toString());
1268        }
1269    }
1270
1271    /**
1272     * Sets the Blacklisted.
1273     * @param blacklisted The blacklisted to set
1274     */

1275    protected void setBlacklistedRecipient(boolean blacklisted)
1276    {
1277        fieldBlacklistedRecipient = blacklisted;
1278    }
1279
1280    /**
1281     * Returns the recipientNotFound.
1282     * @return boolean
1283     */

1284    protected boolean isRecipientNotFound()
1285    {
1286        return fieldRecipientNotFound;
1287    }
1288
1289    /**
1290     * Sets the recipientNotFound.
1291     * @param recipientNotFound The recipientNotFound to set
1292     */

1293    protected void setRecipientNotFound(boolean recipientNotFound)
1294    {
1295        fieldRecipientNotFound = recipientNotFound;
1296    }
1297
1298    /**
1299     * Returns the remoteDomain, lazily initialised as required.
1300     * @return String
1301     */

1302    protected String getRemoteDomain() throws MessagingException
1303    {
1304        String remoteDomain;
1305        if (null == (remoteDomain = getRemoteDomainBasic()))
1306        {
1307            updateRemoteDomain();
1308            return getRemoteDomain();
1309        }
1310        return remoteDomain;
1311    }
1312    
1313    /**
1314     * Returns the remoteDomain.
1315     * @return String
1316     */

1317    private String getRemoteDomainBasic()
1318    {
1319        return fieldRemoteDomain;
1320    }
1321
1322    /**
1323     * Sets the remoteDomain.
1324     * @param remoteDomain The remoteDomain to set
1325     */

1326    protected void setRemoteDomain(String remoteDomain)
1327    {
1328        fieldRemoteDomain = remoteDomain;
1329    }
1330    
1331    /**
1332     * Updates the remoteDomain.
1333     */

1334    protected void updateRemoteDomain() throws MessagingException
1335    {
1336        setRemoteDomain(computeRemoteDomain());
1337    }
1338    
1339    /**
1340     * Answer the IP Address of the remote server for the message being
1341     * processed.
1342     * @return String
1343     * @throws MessagingException
1344     * @throws UnknownHostException
1345     */

1346    protected String computeRemoteAddress()
1347        throws MessagingException, UnknownHostException
1348    {
1349        String domain = getRemoteDomain();
1350        String address = null;
1351        String validatedAddress = null;
1352        int ipAddressStart = domain.indexOf('[');
1353        int ipAddressEnd = -1;
1354        if (ipAddressStart > -1)
1355            ipAddressEnd = domain.indexOf(']', ipAddressStart);
1356        if (ipAddressEnd > -1)
1357            address = domain.substring(ipAddressStart + 1, ipAddressEnd);
1358        else
1359        {
1360            int hostNameEnd = domain.indexOf(' ');
1361            if (hostNameEnd == -1)
1362                hostNameEnd = domain.length();
1363            address = domain.substring(0, hostNameEnd);
1364        }
1365        validatedAddress = org.apache.james.dnsserver.DNSServer.getByName(address).getHostAddress();
1366
1367        return validatedAddress;
1368    }
1369
1370    /**
1371     * Answer the Canonical host name of the remote server for the message
1372     * being processed.
1373     * @return String
1374     * @throws MessagingException
1375     * @throws UnknownHostException
1376     */

1377    protected String computeRemoteHostName()
1378        throws MessagingException, UnknownHostException
1379    {
1380        // These shenanigans are required to get the fully qualified
1381
// hostname prior to JDK 1.4 in which get getCanonicalHostName()
1382
// does the job for us
1383
InetAddress addr1 = org.apache.james.dnsserver.DNSServer.getByName(getRemoteAddress());
1384        InetAddress addr2 = org.apache.james.dnsserver.DNSServer.getByName(addr1.getHostAddress());
1385        return addr2.getHostName();
1386    }
1387
1388    /**
1389     * Returns the remoteAddress, lazily initialised as required.
1390     * @return String
1391     */

1392    protected String getRemoteAddress()
1393        throws MessagingException, UnknownHostException
1394    {
1395        String remoteAddress;
1396        if (null == (remoteAddress = getRemoteAddressBasic()))
1397        {
1398            updateRemoteAddress();
1399            return getRemoteAddress();
1400        }
1401        return remoteAddress;
1402    }
1403    
1404    /**
1405     * Returns the remoteAddress.
1406     * @return String
1407     */

1408    private String getRemoteAddressBasic()
1409    {
1410        return fieldRemoteAddress;
1411    }
1412
1413    /**
1414     * Returns the remoteHostName, lazily initialised as required.
1415     * @return String
1416     */

1417    protected String getRemoteHostName()
1418        throws MessagingException, UnknownHostException
1419    {
1420        String remoteHostName;
1421        if (null == (remoteHostName = getRemoteHostNameBasic()))
1422        {
1423            updateRemoteHostName();
1424            return getRemoteHostName();
1425        }
1426        return remoteHostName;
1427    }
1428    
1429    /**
1430     * Returns the remoteHostName.
1431     * @return String
1432     */

1433    private String getRemoteHostNameBasic()
1434    {
1435        return fieldRemoteHostName;
1436    }
1437
1438    /**
1439     * Sets the remoteAddress.
1440     * @param remoteAddress The remoteAddress to set
1441     */

1442    protected void setRemoteAddress(String remoteAddress)
1443    {
1444        fieldRemoteAddress = remoteAddress;
1445    }
1446    
1447    /**
1448     * Updates the remoteAddress.
1449     */

1450    protected void updateRemoteAddress()
1451        throws MessagingException, UnknownHostException
1452    {
1453        setRemoteAddress(computeRemoteAddress());
1454    }
1455
1456    /**
1457     * Sets the remoteHostName.
1458     * @param remoteHostName The remoteHostName to set
1459     */

1460    protected void setRemoteHostName(String remoteHostName)
1461    {
1462        fieldRemoteHostName = remoteHostName;
1463    }
1464    
1465    /**
1466     * Updates the remoteHostName.
1467     */

1468    protected void updateRemoteHostName()
1469        throws MessagingException, UnknownHostException
1470    {
1471        setRemoteHostName(computeRemoteHostName());
1472    }
1473
1474    /**
1475     * Returns the rFC2822RECEIVEDHeaderFields.
1476     * @return String
1477     */

1478    public static String getRFC2822RECEIVEDHeaderFields()
1479    {
1480        return fieldRFC2822RECEIVEDHeaderFields;
1481    }
1482
1483    /**
1484     * Returns the maxMessageSizeExceeded, lazily initialised as required.
1485     * @return Boolean
1486     */

1487    protected Boolean isMaxMessageSizeExceeded() throws MessagingException
1488    {
1489        Boolean isMaxMessageSizeExceeded = null;
1490        if (null
1491            == (isMaxMessageSizeExceeded = isMaxMessageSizeExceededBasic()))
1492        {
1493            updateMaxMessageSizeExceeded();
1494            return isMaxMessageSizeExceeded();
1495        }
1496        return isMaxMessageSizeExceeded;
1497    }
1498
1499    /**
1500     * Refreshes the maxMessageSizeExceeded.
1501     */

1502    protected void updateMaxMessageSizeExceeded() throws MessagingException
1503    {
1504        setMaxMessageSizeExceeded(computeMaxMessageSizeExceeded());
1505    }
1506
1507    /**
1508     * Compute the maxMessageSizeExceeded.
1509     * @return Boolean
1510     */

1511    protected Boolean computeMaxMessageSizeExceeded() throws MessagingException
1512    {
1513        if (0 == getMaxMessageSizeLimit())
1514            return Boolean.FALSE;
1515        return new Boolean(getMessageIn().getSize() > getMaxMessageSizeLimit());
1516    }
1517    
1518    /**
1519     * Returns the maxMessageSizeExceeded.
1520     * @return Boolean
1521     */

1522    private Boolean isMaxMessageSizeExceededBasic()
1523    {
1524        return fieldMaxMessageSizeExceeded;
1525    }
1526
1527    /**
1528     * Sets the maxMessageSizeExceeded.
1529     * @param maxMessageSizeExceeded The maxMessageSizeExceeded to set
1530     */

1531    protected void setMaxMessageSizeExceeded(Boolean maxMessageSizeExceeded)
1532    {
1533        fieldMaxMessageSizeExceeded = maxMessageSizeExceeded;
1534    }
1535
1536    /**
1537     * Returns the remoteReceivedHeaderInvalid, lazily initialised.
1538     * @return Boolean
1539     */

1540    protected Boolean isRemoteReceivedHeaderInvalid() throws MessagingException
1541    {
1542        Boolean isInvalid = null;
1543        if (null == (isInvalid = isRemoteReceivedHeaderInvalidBasic()))
1544        {
1545            updateRemoteReceivedHeaderInvalid();
1546            return isRemoteReceivedHeaderInvalid();
1547        }
1548        return isInvalid;
1549    }
1550    
1551    /**
1552     * Computes the remoteReceivedHeaderInvalid.
1553     * @return Boolean
1554     */

1555    protected Boolean computeRemoteReceivedHeaderInvalid()
1556        throws MessagingException
1557    {
1558        Boolean isInvalid = Boolean.FALSE;
1559        try
1560        {
1561            getRemoteAddress();
1562        }
1563        catch (UnknownHostException e)
1564        {
1565            isInvalid = Boolean.TRUE;
1566        }
1567        return isInvalid;
1568    }
1569    
1570    /**
1571     * Returns the remoteReceivedHeaderInvalid.
1572     * @return Boolean
1573     */

1574    private Boolean isRemoteReceivedHeaderInvalidBasic()
1575    {
1576        return fieldRemoteReceivedHeaderInvalid;
1577    }
1578
1579    /**
1580     * Sets the remoteReceivedHeaderInvalid.
1581     * @param remoteReceivedHeaderInvalid The remoteReceivedHeaderInvalid to set
1582     */

1583    protected void setRemoteReceivedHeaderInvalid(Boolean remoteReceivedHeaderInvalid)
1584    {
1585        fieldRemoteReceivedHeaderInvalid = remoteReceivedHeaderInvalid;
1586    }
1587    
1588    /**
1589     * Updates the remoteReceivedHeaderInvalid.
1590     */

1591    protected void updateRemoteReceivedHeaderInvalid() throws MessagingException
1592    {
1593        setRemoteReceivedHeaderInvalid(computeRemoteReceivedHeaderInvalid());
1594    }
1595
1596}
1597
Popular Tags