1 /************************************************************************
2 * Copyright (c) 2003-2006 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.net.InetAddress;
21 import java.net.UnknownHostException;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Enumeration;
25 import java.util.Iterator;
26 import java.util.StringTokenizer;
27
28 import javax.mail.Address;
29 import javax.mail.Flags;
30 import javax.mail.MessagingException;
31 import javax.mail.internet.InternetAddress;
32 import javax.mail.internet.MimeMessage;
33 import javax.mail.internet.ParseException;
34
35 import org.apache.james.core.MailImpl;
36 import org.apache.mailet.RFC2822Headers;
37 import org.apache.mailet.Mail;
38 import org.apache.mailet.MailAddress;
39
40 /***
41 * <p>Class <code>MessageProcessor</code> handles the delivery of
42 * <code>MimeMessages</code> to the James input spool.</p>
43 *
44 * <p>Messages written to the input spool always have the following Mail
45 * Attributes set:</p>
46 * <dl>
47 * <dt>org.apache.james.fetchmail.taskName (java.lang.String)</dt>
48 * <dd>The name of the fetch task that processed the message</dd>
49 * <dt>org.apache.james.fetchmail.folderName (java.lang.String)</dt>
50 * <dd>The name of the folder from which the message was fetched</dd>
51 * </dl>
52 *
53 * <p>Messages written to the input spool have the following Mail Attributes
54 * set if the corresponding condition is satisfied:
55 * <dl>
56 * <dt>org.apache.james.fetchmail.isBlacklistedRecipient</dt>
57 * <dd>The recipient is in the configured blacklist</dd>
58 * <dt>org.apache.james.fetchmail.isMaxMessageSizeExceeded (java.lang.String)</dt>
59 * <dd>The message size exceeds the configured limit. An empty message is
60 * written to the input spool. The Mail Attribute value is a String
61 * representing the size of the original message in bytes.</dd>
62 * <dt>org.apache.james.fetchmail.isRecipientNotFound</dt>
63 * <dd>The recipient could not be found. Delivery is to the configured recipient.
64 * See the discussion of delivery to a sole intended recipient below.</dd>
65 * <dt>org.apache.james.fetchmail.isRemoteRecievedHeaderInvalid</dt>
66 * <dd>The Receieved header at the index specified by parameter
67 * <code>remoteReceivedHeaderIndex</code> is invalid.</dd>
68 * <dt>org.apache.james.fetchmail.isRemoteRecipient</dt>
69 * <dd>The recipient is on a remote host</dd>
70 * <dt>org.apache.james.fetchmail.isUserUndefined</dt>
71 * <dd>The recipient is on a localhost but not defined to James</dd>
72 * <dt>org.apache.james.fetchmail.isDefaultSenderLocalPart</dt>
73 * <dd>The local part of the sender address could not be obtained. The
74 * default value has been used.</dd>
75 * <dt>org.apache.james.fetchmail.isDefaultSenderDomainPart</dt>
76 * <dd>The domain part of the sender address could not be obtained. The
77 * default value has been used.</dd>
78 * <dt>org.apache.james.fetchmail.isDefaultRemoteAddress</dt>
79 * <dd>The remote address could not be determined. The default value
80 * (localhost/127.0.0.1)has been used.</dd>
81 * </dl>
82 *
83 * <p>Configuration settings -
84 * see <code>org.apache.james.fetchmail.ParsedConfiguration</code>
85 * - control the messages that are written to the James input spool, those that
86 * are rejected and what happens to messages that are rejected.</p>
87 *
88 * <p>Rejection processing is based on the following filters:</p>
89 * <dl>
90 * <dt>RejectRemoteRecipient</dt>
91 * <dd>Rejects recipients on remote hosts</dd>
92 * <dt>RejectBlacklistedRecipient</dt>
93 * <dd>Rejects recipients configured in a blacklist</dd>
94 * <dt>RejectUserUndefined</dt>
95 * <dd>Rejects recipients on local hosts who are not defined as James users</dd>
96 * <dt>RejectRecipientNotFound</dt>
97 * <dd>See the discussion of delivery to a sole intended recipient below</dd>
98 * <dt>RejectMaxMessageSizeExceeded</dt>
99 * <dd>Rejects messages whose size exceeds the configured limit</dd>
100 * <dt>RejectRemoteReceievedHeaderInvalid</dt>
101 * <dd>Rejects messages whose Received header is invalid.</dd>
102 * </dl>
103 *
104 * <p>Rejection processing is intentionally limited to managing the status of the
105 * messages that are rejected on the server from which they were fetched. View
106 * it as a simple automation of the manual processing an end-user would perform
107 * through a mail client. Messages may be marked as seen or be deleted.</p>
108 *
109 * <p>Further processing can be achieved by configuring to disable rejection for
110 * one or more filters. This enables Messages that would have been rejected to
111 * be written to the James input spool. The conditional Mail Attributes
112 * described above identify the filter states. The Matcher/Mailet chain can
113 * then be used to perform any further processing required, such as notifying
114 * the Postmaster and/or sender, marking the message for error processing, etc.</p>
115 *
116 * <p>Note that in the case of a message exceeding the message size limit, the
117 * message that is written to the input spool has no content. This enables
118 * configuration of a mailet notifying the sender that their mail has not been
119 * delivered due to its size while maintaining the purpose of the filter which is
120 * to avoid injecting excessively large messages into the input spool.</p>
121 *
122 * <p>Delivery is to a sole intended recipient. The recipient is determined in the
123 * following manner:</p>
124 *
125 * <ol>
126 * <li>If isIgnoreIntendedRecipient(), use the configured recipient</li>
127 * <li>If the Envelope contains a for: stanza, use the recipient in the stanza</li>
128 * <li>If the Message has a sole intended recipient, use this recipient</li>
129 * <li>If not rejectRecipientNotFound(), use the configured recipient</li>
130 * </ol>
131 *
132 * <p>If a recipient cannot be determined after these steps, the message is
133 * rejected.</p>
134 *
135 * <p>Every delivered message CURRENTLY has an "X-fetched-from" header added
136 * containing the name of the fetch task. Its primary uses are to detect bouncing
137 * mail and provide backwards compatibility with the fetchPop task that inserted
138 * this header to enable injected messages to be detected in the Matcher/Mailet
139 * chain. This header is DEPRECATED and WILL BE REMOVED in a future version of
140 * fetchmail. Use the Mail Attribute <code>org.apache.james.fetchmail.taskName</code>
141 * instead.
142 *
143 * <p><code>MessageProcessor</code> is as agnostic as it can be about the format
144 * and contents of the messages it delivers. There are no RFCs that govern its
145 * behavior. The most releveant RFCs relate to the exchange of messages between
146 * MTA servers, but not POP3 or IMAP servers which are normally end-point
147 * servers and not expected to re-inject mail into MTAs. None the less, the
148 * intent is to conform to the 'spirit' of the RFCs.
149 * <code>MessageProcessor</code> relies on the MTA (James in this
150 * implementation) to manage and validate the injected mail just as it would
151 * when receiving mail from an upstream MTA.</p>
152 *
153 * <p>The only correction applied by <code>MessageProcessor</code> is to correct a
154 * missing or partial sender address. If the sender address can not be obtained,
155 * the default local part and default domain part is added. If the sender domain
156 * part is absent, the default domain part is added.</p>
157 *
158 * <p>Mail with corrections applied to the sender address will most likely pass
159 * Matcher tests on the sender that they might otherwise fail. The
160 * Mail Attributes <code>org.apache.james.fetchmail.isDefaultSenderLocalPart</code>
161 * and <code>org.apache.james.fetchmail.isDefaultSenderDomainPart</code> are added
162 * to the injected mail to enable such mail to be detected and processed accordingly.
163 * </p>
164 *
165 * <p>The status of messages on the server from which they were fetched that
166 * cannot be injected into the input spool due to non-correctable errors is
167 * determined by the undeliverable configuration options.</p>
168 *
169 */
170 public class MessageProcessor extends ProcessorAbstract
171 {
172 private MimeMessage fieldMessageIn;
173
174 /***
175 * Recipient cannot be found
176 */
177 private boolean fieldRecipientNotFound = false;
178
179 /***
180 * Recipient is a local user on a local host
181 */
182 private boolean fieldRemoteRecipient = true;
183
184 /***
185 * The mail's Received header at index remoteReceivedHeaderIndex is invalid.
186 */
187 private Boolean fieldRemoteReceivedHeaderInvalid;
188
189 /***
190 * Recipient is not a local user
191 */
192 private boolean fieldUserUndefined = false;
193
194 /***
195 * The Maximum Message has been exceeded
196 */
197 private Boolean fieldMaxMessageSizeExceeded;
198
199
200 /***
201 * Field names for an RFC2822 compliant RECEIVED Header
202 */
203 static final private String fieldRFC2822RECEIVEDHeaderFields =
204 "from by via with id for ;";
205
206 /***
207 * Recipient is blacklisted
208 */
209 private boolean fieldBlacklistedRecipient = false;
210
211 /***
212 * The RFC2822 compliant "Received : from" domain
213 */
214 private String fieldRemoteDomain;
215
216 /***
217 * The remote address derived from the remote domain
218 */
219 private String fieldRemoteAddress;
220
221 /***
222 * The remote host name derived from the remote domain
223 */
224 private String fieldRemoteHostName;
225
226 /***
227 * The default sender local part has been used.
228 */
229 private boolean fieldDefaultSenderLocalPart = false;
230
231 /***
232 * The default sender domain part has been used.
233 */
234 private boolean fieldDefaultSenderDomainPart = false;
235
236 /***
237 * The default remote address has been used.
238 */
239 private boolean fieldDefaultRemoteAddress = false;
240
241 /***
242 * Constructor for MessageProcessor.
243 *
244 * @param account
245 */
246 private MessageProcessor(Account account)
247 {
248 super(account);
249 }
250
251 /***
252 * Constructor for MessageProcessor.
253 *
254 * @param messageIn
255 * @param account
256 */
257
258 MessageProcessor(
259 MimeMessage messageIn,
260 Account account)
261 {
262 this(account);
263 setMessageIn(messageIn);
264 }
265
266
267 /***
268 * Method process attempts to deliver a fetched message.
269 *
270 * @see org.apache.james.fetchmail.ProcessorAbstract#process()
271 */
272 public void process() throws MessagingException
273 {
274
275 if (getLogger().isDebugEnabled())
276 {
277 StringBuffer logMessageBuffer =
278 new StringBuffer("Attempting delivery of message with id. ");
279 logMessageBuffer.append(getMessageIn().getMessageID());
280 getLogger().debug(logMessageBuffer.toString());
281 }
282
283
284 MailAddress intendedRecipient = getIntendedRecipient();
285 setRecipientNotFound(null == intendedRecipient);
286
287 if (isRecipientNotFound())
288 {
289 if (isDeferRecipientNotFound())
290 {
291
292 String messageID = getMessageIn().getMessageID();
293 if (!getDeferredRecipientNotFoundMessageIDs()
294 .contains(messageID))
295 {
296 getDeferredRecipientNotFoundMessageIDs().add(messageID);
297 if (getLogger().isDebugEnabled())
298 {
299 StringBuffer messageBuffer =
300 new StringBuffer("Deferred processing of message for which the intended recipient could not be found. Message ID: ");
301 messageBuffer.append(messageID);
302 getLogger().debug(messageBuffer.toString());
303 }
304 return;
305 }
306 else
307 {
308 getDeferredRecipientNotFoundMessageIDs().remove(messageID);
309 if (getLogger().isDebugEnabled())
310 {
311 StringBuffer messageBuffer =
312 new StringBuffer("Processing deferred message for which the intended recipient could not be found. Message ID: ");
313 messageBuffer.append(messageID);
314 getLogger().debug(messageBuffer.toString());
315 }
316 }
317 }
318
319 if (isRejectRecipientNotFound())
320 {
321 rejectRecipientNotFound();
322 return;
323 }
324 intendedRecipient = getRecipient();
325 StringBuffer messageBuffer =
326 new StringBuffer("Intended recipient not found. Using configured recipient as new envelope recipient - ");
327 messageBuffer.append(intendedRecipient);
328 messageBuffer.append('.');
329 logStatusInfo(messageBuffer.toString());
330 }
331
332
333 setBlacklistedRecipient(isBlacklistedRecipient(intendedRecipient));
334 setRemoteRecipient(!isLocalServer(intendedRecipient));
335 setUserUndefined(!isLocalRecipient(intendedRecipient));
336
337
338 if (isRejectBlacklisted() && isBlacklistedRecipient())
339 {
340 rejectBlacklistedRecipient(intendedRecipient);
341 return;
342 }
343
344 if (isRejectRemoteRecipient() && isRemoteRecipient())
345 {
346 rejectRemoteRecipient(intendedRecipient);
347 return;
348 }
349
350 if (isRejectUserUndefined() && isUserUndefined())
351 {
352 rejectUserUndefined(intendedRecipient);
353 return;
354 }
355
356 if (isRejectMaxMessageSizeExceeded()
357 && isMaxMessageSizeExceeded().booleanValue())
358 {
359 rejectMaxMessageSizeExceeded(getMessageIn().getSize());
360 return;
361 }
362
363 if (isRejectRemoteReceivedHeaderInvalid()
364 && isRemoteReceivedHeaderInvalid().booleanValue())
365 {
366 rejectRemoteReceivedHeaderInvalid();
367 return;
368 }
369
370
371
372
373
374
375
376
377
378 Mail mail = null;
379 try
380 {
381 mail = createMail(createMessage(), intendedRecipient);
382 }
383 catch (ParseException ex)
384 {
385 handleParseException(ex);
386 return;
387 }
388 catch (UnknownHostException ex)
389 {
390 handleUnknownHostException(ex);
391 return;
392 }
393
394 addMailAttributes(mail);
395 addErrorMessages(mail);
396
397
398 if (isBouncing())
399 {
400 handleBouncing(mail);
401 return;
402 }
403
404
405 sendMail(mail);
406 }
407
408 /***
409 * Method rejectRemoteRecipient.
410 * @param recipient
411 * @throws MessagingException
412 */
413 protected void rejectRemoteRecipient(MailAddress recipient)
414 throws MessagingException
415 {
416
417 if (!isLeaveRemoteRecipient())
418 setMessageDeleted();
419
420 if (isMarkRemoteRecipientSeen())
421 setMessageSeen();
422
423 StringBuffer messageBuffer =
424 new StringBuffer("Rejected mail intended for remote recipient: ");
425 messageBuffer.append(recipient);
426 messageBuffer.append('.');
427 logStatusInfo(messageBuffer.toString());
428
429 return;
430 }
431
432 /***
433 * Method rejectBlacklistedRecipient.
434 * @param recipient
435 * @throws MessagingException
436 */
437 protected void rejectBlacklistedRecipient(MailAddress recipient)
438 throws MessagingException
439 {
440
441 if (!isLeaveBlacklisted())
442 setMessageDeleted();
443 if (isMarkBlacklistedSeen())
444 setMessageSeen();
445
446 StringBuffer messageBuffer =
447 new StringBuffer("Rejected mail intended for blacklisted recipient: ");
448 messageBuffer.append(recipient);
449 messageBuffer.append('.');
450 logStatusInfo(messageBuffer.toString());
451
452 return;
453 }
454
455 /***
456 * Method rejectRecipientNotFound.
457 * @throws MessagingException
458 */
459 protected void rejectRecipientNotFound() throws MessagingException
460 {
461
462 if (!isLeaveRecipientNotFound())
463 setMessageDeleted();
464
465 if (isMarkRecipientNotFoundSeen())
466 setMessageSeen();
467
468 StringBuffer messageBuffer =
469 new StringBuffer("Rejected mail for which a sole intended recipient could not be found.");
470 messageBuffer.append(" Recipients: ");
471 Address[] allRecipients = getMessageIn().getAllRecipients();
472 for (int i = 0; i < allRecipients.length; i++)
473 {
474 messageBuffer.append(allRecipients[i]);
475 messageBuffer.append(' ');
476 }
477 messageBuffer.append('.');
478 logStatusInfo(messageBuffer.toString());
479 return;
480 }
481
482 /***
483 * Method rejectUserUndefined.
484 * @param recipient
485 * @throws MessagingException
486 */
487 protected void rejectUserUndefined(MailAddress recipient)
488 throws MessagingException
489 {
490
491 if (!isLeaveUserUndefined())
492 setMessageDeleted();
493
494 if (isMarkUserUndefinedSeen())
495 setMessageSeen();
496
497 StringBuffer messageBuffer =
498 new StringBuffer("Rejected mail intended for undefined user: ");
499 messageBuffer.append(recipient);
500 messageBuffer.append('.');
501 logStatusInfo(messageBuffer.toString());
502
503 return;
504 }
505
506 /***
507 * Method rejectMaxMessageSizeExceeded.
508 * @param message size
509 * @throws MessagingException
510 */
511 protected void rejectMaxMessageSizeExceeded(int messageSize)
512 throws MessagingException
513 {
514
515 if (!isLeaveMaxMessageSizeExceeded())
516 setMessageDeleted();
517
518 if (isMarkMaxMessageSizeExceededSeen())
519 setMessageSeen();
520
521 StringBuffer messageBuffer =
522 new StringBuffer("Rejected mail exceeding message size limit. Message size: ");
523 messageBuffer.append(messageSize/1024);
524 messageBuffer.append("KB.");
525 logStatusInfo(messageBuffer.toString());
526
527 return;
528 }
529
530 /***
531 * Method rejectRemoteReceivedHeaderInvalid.
532 * @throws MessagingException
533 */
534 protected void rejectRemoteReceivedHeaderInvalid()
535 throws MessagingException
536 {
537
538 if (!isLeaveRemoteReceivedHeaderInvalid())
539 setMessageDeleted();
540
541 if (isMarkRemoteReceivedHeaderInvalidSeen())
542 setMessageSeen();
543
544 StringBuffer messageBuffer =
545 new StringBuffer("Rejected mail with an invalid Received: header at index ");
546 messageBuffer.append(getRemoteReceivedHeaderIndex());
547 messageBuffer.append(".");
548 logStatusInfo(messageBuffer.toString());
549 return;
550 }
551
552 /***
553 * <p>Method createMessage answers a new <code>MimeMessage</code> from the
554 * fetched message.</p>
555 *
556 * <p>If the maximum message size is exceeded, an empty message is created,
557 * else the new message is a copy of the received message.</p>
558 *
559 * @return MimeMessage
560 * @throws MessagingException
561 */
562 protected MimeMessage createMessage() throws MessagingException
563 {
564
565 MimeMessage messageOut = null;
566 if (isMaxMessageSizeExceeded().booleanValue())
567 messageOut = createEmptyMessage();
568 else
569 messageOut = new MimeMessage(getMessageIn());
570
571
572
573
574 messageOut.addHeader("X-fetched-from", getFetchTaskName());
575
576 return messageOut;
577 }
578
579 /***
580 * Method createEmptyMessage answers a new
581 * <code>MimeMessage</code> from the fetched message with the message
582 * contents removed.
583 *
584 * @return MimeMessage
585 * @throws MessagingException
586 */
587 protected MimeMessage createEmptyMessage()
588 throws MessagingException
589 {
590
591 MimeMessage messageOut = new MimeMessage(getSession());
592
593
594 Enumeration headersInEnum = getMessageIn().getAllHeaderLines();
595 while (headersInEnum.hasMoreElements())
596 messageOut.addHeaderLine((String) headersInEnum.nextElement());
597 messageOut.setSubject(getMessageIn().getSubject());
598
599
600 messageOut.setText("");
601
602
603 messageOut.saveChanges();
604
605 return messageOut;
606 }
607
608 /***
609 * Method createMail creates a new <code>Mail</code>.
610 *
611 * @param message
612 * @param recipient
613 * @return Mail
614 * @throws MessagingException
615 */
616 protected Mail createMail(MimeMessage message, MailAddress recipient)
617 throws MessagingException, UnknownHostException
618 {
619 Collection recipients = new ArrayList(1);
620 recipients.add(recipient);
621 MailImpl mail =
622 new MailImpl(getServer().getId(), getSender(), recipients, message);
623
624
625 if (getRemoteAddress() == null || getRemoteHostName() == null)
626 {
627 mail.setRemoteAddr("127.0.0.1");
628 mail.setRemoteHost("localhost");
629 setDefaultRemoteAddress(true);
630 logStatusInfo("Remote address could not be determined. Using localhost/127.0.0.1");
631 }
632 else
633 {
634 mail.setRemoteAddr(getRemoteAddress());
635 mail.setRemoteHost(getRemoteHostName());
636 setDefaultRemoteAddress(false);
637 }
638
639 if (getLogger().isDebugEnabled())
640 {
641 StringBuffer messageBuffer =
642 new StringBuffer("Created mail with name: ");
643 messageBuffer.append(mail.getName());
644 messageBuffer.append(", sender: ");
645 messageBuffer.append(mail.getSender());
646 messageBuffer.append(", recipients: ");
647 Iterator recipientIterator = mail.getRecipients().iterator();
648 while (recipientIterator.hasNext())
649 {
650 messageBuffer.append(recipientIterator.next());
651 messageBuffer.append(' ');
652 }
653 messageBuffer.append(", remote address: ");
654 messageBuffer.append(mail.getRemoteAddr());
655 messageBuffer.append(", remote host name: ");
656 messageBuffer.append(mail.getRemoteHost());
657 messageBuffer.append('.');
658 getLogger().debug(messageBuffer.toString());
659 }
660 return mail;
661 }
662
663
664 /***
665 * <p>
666 * Method getSender answers a <code>MailAddress</code> for the sender.
667 * When the sender local part and/or domain part can not be obtained
668 * from the mail, default values are used. The flags
669 * 'defaultSenderLocalPart' and 'defaultSenderDomainPart' are set
670 * accordingly.
671 * </p>
672 *
673 * @return MailAddress
674 * @throws MessagingException
675 */
676 protected MailAddress getSender() throws MessagingException
677 {
678 String from = null;
679 InternetAddress internetAddress = null;
680
681 try {
682 from = ((InternetAddress) getMessageIn().getFrom()[0]).getAddress().trim();
683 setDefaultSenderLocalPart(false);
684 }
685 catch (Exception _) {
686 from = getDefaultLocalPart();
687 setDefaultSenderLocalPart(true);
688 StringBuffer buffer = new StringBuffer(32);
689 buffer.append("Sender localpart is absent. Using default value (");
690 buffer.append(getDefaultLocalPart());
691 buffer.append(')');
692 logStatusInfo(buffer.toString());
693 }
694
695
696 if (from.indexOf('@') < 0)
697 {
698 StringBuffer fromBuffer = new StringBuffer(from);
699 fromBuffer.append('@');
700 fromBuffer.append(getDefaultDomainName());
701 internetAddress = new InternetAddress(fromBuffer.toString());
702 setDefaultSenderDomainPart(true);
703
704 StringBuffer buffer = new StringBuffer(32);
705 buffer.append("Sender domain is absent. Using default value (");
706 buffer.append(getDefaultDomainName());
707 buffer.append(')');
708 logStatusInfo(buffer.toString());
709 }
710 else
711 {
712 internetAddress = new InternetAddress(from);
713 setDefaultSenderDomainPart(false);
714 }
715
716 return new MailAddress(internetAddress);
717 }
718
719 /***
720 * <p>Method computeRemoteDomain answers a <code>String</code> that is the
721 * RFC2822 compliant "Received : from" domain extracted from the message
722 * being processed for the remote domain that sent the message.</p>
723 *
724 * <p>Often the remote domain is the domain that sent the message to the
725 * host of the message store, the second "received" header, which has an
726 * index of 1. Other times, messages may be received by a edge mail server
727 * and relayed internally through one or more internal mail servers prior
728 * to arriving at the message store host. In these cases the index is
729 * 1 + the number of internal servers through which a mail passes.
730 * </p>
731 * <p>The index of the header to use is specified by the configuration
732 * parameter <code>RemoteReceivedHeaderIndex</code>. This is set to
733 * point to the received header prior to the remote mail server, the one
734 * prior to the edge mail server.
735 * </p>
736 * <p>"received" headers are searched starting at the specified index.
737 * If a domain in the "received" header is not found, successively closer
738 * "received" headers are tried. If a domain is not found in this way, the
739 * local machine is used as the domain. Finally, if the local domain cannot
740 * be determined, the local address 127.0.0.1 is used.
741 * </p>
742 *
743 * @return String An RFC2822 compliant "Received : from" domain name
744 */
745 protected String computeRemoteDomain() throws MessagingException
746 {
747 StringBuffer domainBuffer = new StringBuffer();
748 String[] headers = null;
749
750 if (getRemoteReceivedHeaderIndex() > -1)
751 headers = getMessageIn().getHeader(RFC2822Headers.RECEIVED);
752
753
754
755 boolean hasHeaders = (null == headers ? false : headers.length > 0);
756
757
758 if (hasHeaders)
759 {
760 final String headerTokens = " \n\r";
761
762
763 for (int headerIndex =
764 headers.length > getRemoteReceivedHeaderIndex()
765 ? getRemoteReceivedHeaderIndex()
766 : headers.length - 1;
767 headerIndex >= 0 && domainBuffer.length() == 0;
768 headerIndex--)
769 {
770
771 StringTokenizer tokenizer =
772 new StringTokenizer(headers[headerIndex], headerTokens);
773 boolean inFrom = false;
774 while (!inFrom && tokenizer.hasMoreTokens())
775 inFrom = tokenizer.nextToken().equals("from");
776
777
778 while (inFrom && tokenizer.hasMoreTokens())
779 {
780 String token = tokenizer.nextToken();
781 if (inFrom =
782 getRFC2822RECEIVEDHeaderFields().indexOf(token) == -1)
783 {
784 domainBuffer.append(token);
785 domainBuffer.append(' ');
786 }
787 }
788 }
789 }
790
791
792
793
794
795 if (domainBuffer.length() == 0)
796 {
797 try
798 {
799 InetAddress addr1 = java.net.InetAddress.getLocalHost();
800
801
802
803 InetAddress addr2 =
804 java.net.InetAddress.getByName(addr1.getHostAddress());
805 InetAddress addr3 =
806 java.net.InetAddress.getByName(addr2.getHostName());
807 domainBuffer.append(addr3.getHostName());
808 }
809 catch (UnknownHostException ue)
810 {
811 domainBuffer.append("[127.0.0.1]");
812 }
813 }
814 return domainBuffer.toString().trim();
815 }
816
817 /***
818 * Method handleBouncing sets the Mail state to ERROR and delete from
819 * the message store.
820 *
821 * @param mail
822 */
823 protected void handleBouncing(Mail mail) throws MessagingException
824 {
825 mail.setState(Mail.ERROR);
826 setMessageDeleted();
827
828 mail.setErrorMessage(
829 "This mail from FetchMail task "
830 + getFetchTaskName()
831 + " seems to be bouncing!");
832 logStatusError("Message is bouncing! Deleted from message store and moved to the Error repository.");
833 }
834
835 /***
836 * Method handleParseException.
837 * @param ex
838 * @throws MessagingException
839 */
840 protected void handleParseException(ParseException ex)
841 throws MessagingException
842 {
843
844 if (!isLeaveUndeliverable())
845 setMessageDeleted();
846 if (isMarkUndeliverableSeen())
847 setMessageSeen();
848 logStatusWarn("Message could not be delivered due to an error parsing a mail address.");
849 if (getLogger().isDebugEnabled())
850 {
851 StringBuffer messageBuffer =
852 new StringBuffer("UNDELIVERABLE Message ID: ");
853 messageBuffer.append(getMessageIn().getMessageID());
854 getLogger().debug(messageBuffer.toString(), ex);
855 }
856 }
857
858 /***
859 * Method handleUnknownHostException.
860 * @param ex
861 * @throws MessagingException
862 */
863 protected void handleUnknownHostException(UnknownHostException ex)
864 throws MessagingException
865 {
866
867 if (!isLeaveUndeliverable())
868 setMessageDeleted();
869
870 if (isMarkUndeliverableSeen())
871 setMessageSeen();
872
873 logStatusWarn("Message could not be delivered due to an error determining the remote domain.");
874 if (getLogger().isDebugEnabled())
875 {
876 StringBuffer messageBuffer =
877 new StringBuffer("UNDELIVERABLE Message ID: ");
878 messageBuffer.append(getMessageIn().getMessageID());
879 getLogger().debug(messageBuffer.toString(), ex);
880 }
881 }
882
883 /***
884 * Method isLocalRecipient.
885 * @param recipient
886 * @return boolean
887 */
888 protected boolean isLocalRecipient(MailAddress recipient)
889 {
890 return isLocalUser(recipient) && isLocalServer(recipient);
891 }
892
893 /***
894 * Method isLocalServer.
895 * @param recipient
896 * @return boolean
897 */
898 protected boolean isLocalServer(MailAddress recipient)
899 {
900 return getServer().isLocalServer(recipient.getHost());
901 }
902
903 /***
904 * Method isLocalUser.
905 * @param recipient
906 * @return boolean
907 */
908 protected boolean isLocalUser(MailAddress recipient)
909 {
910 return getLocalUsers().containsCaseInsensitive(recipient.getUser());
911 }
912
913 /***
914 * Method isBlacklistedRecipient.
915 * @param recipient
916 * @return boolean
917 */
918 protected boolean isBlacklistedRecipient(MailAddress recipient)
919 {
920 return getBlacklist().contains(recipient);
921 }
922
923 /***
924 * Check if this mail has been bouncing by counting the X-fetched-from
925 * headers for this task
926 *
927 * @return boolean
928 */
929 protected boolean isBouncing() throws MessagingException
930 {
931 Enumeration enumeration =
932 getMessageIn().getMatchingHeaderLines(
933 new String[] { "X-fetched-from" });
934 int count = 0;
935 while (enumeration.hasMoreElements())
936 {
937 String header = (String) enumeration.nextElement();
938 if (header.equals(getFetchTaskName()))
939 count++;
940 }
941 return count >= 3;
942 }
943
944 /***
945 * Method sendMail.
946 * @param mail
947 * @throws MessagingException
948 */
949 protected void sendMail(Mail mail) throws MessagingException
950 {
951
952 getServer().sendMail(mail);
953
954
955 if (!isLeave())
956 setMessageDeleted();
957
958 if (isMarkSeen())
959 setMessageSeen();
960
961
962 StringBuffer messageBuffer =
963 new StringBuffer("Spooled message to recipients: ");
964 Iterator recipientIterator = mail.getRecipients().iterator();
965 while (recipientIterator.hasNext())
966 {
967 messageBuffer.append(recipientIterator.next());
968 messageBuffer.append(' ');
969 }
970 messageBuffer.append('.');
971 logStatusInfo(messageBuffer.toString());
972 }
973
974
975 /***
976 * Method getEnvelopeRecipient answers the recipient if found else null.
977 *
978 * Try and parse the "for" parameter from a Received header
979 * Maybe not the most accurate parsing in the world but it should do
980 * I opted not to use ORO (maybe I should have)
981 *
982 * @param msg
983 * @return String
984 */
985
986 protected String getEnvelopeRecipient(MimeMessage msg) throws MessagingException
987 {
988 String res = getCustomRecipientHeader();
989 if (res != null && res.length() > 0) {
990 String[] headers = msg.getHeader(getCustomRecipientHeader());
991 if (headers != null) {
992 String mailFor = headers[0];
993 if (mailFor.startsWith("<") && mailFor.endsWith(">"))
994 mailFor = mailFor.substring(1, (mailFor.length() - 1));
995 return mailFor;
996 }
997 } else {
998 try
999 {
1000 Enumeration enumeration =
1001 msg.getMatchingHeaderLines(new String[] { "Received" });
1002 while (enumeration.hasMoreElements())
1003 {
1004 String received = (String) enumeration.nextElement();
1005
1006 int nextSearchAt = 0;
1007 int i = 0;
1008 int start = 0;
1009 int end = 0;
1010 boolean hasBracket = false;
1011 boolean usableAddress = false;
1012 while (!usableAddress && (i != -1))
1013 {
1014 hasBracket = false;
1015 i = received.indexOf("for ", nextSearchAt);
1016 if (i > 0)
1017 {
1018 start = i + 4;
1019 end = 0;
1020 nextSearchAt = start;
1021 for (int c = start; c < received.length(); c++)
1022 {
1023 char ch = received.charAt(c);
1024 switch (ch)
1025 {
1026 case '<' :
1027 hasBracket = true;
1028 continue;
1029 case '@' :
1030 usableAddress = true;
1031 continue;
1032 case ' ' :
1033 end = c;
1034 break;
1035 case ';' :
1036 end = c;
1037 break;
1038 }
1039 if (end > 0)
1040 break;
1041 }
1042 }
1043 }
1044 if (usableAddress)
1045 {
1046
1047 String mailFor = received.substring(start, end);
1048
1049
1050 if (mailFor.startsWith("<") && mailFor.endsWith(">"))
1051 mailFor = mailFor.substring(1, (mailFor.length() - 1));
1052
1053 return mailFor;
1054 }
1055 }
1056 }
1057 catch (MessagingException me)
1058 {
1059 logStatusWarn("No Received headers found.");
1060 }
1061 }
1062 return null;
1063 }
1064
1065 /***
1066 * Method getIntendedRecipient answers the sole intended recipient else null.
1067 *
1068 * @return MailAddress
1069 * @throws MessagingException
1070 */
1071 protected MailAddress getIntendedRecipient() throws MessagingException
1072 {
1073
1074
1075 if (isIgnoreRecipientHeader())
1076 {
1077 StringBuffer messageBuffer =
1078 new StringBuffer("Ignoring recipient header. Using configured recipient as new envelope recipient: ");
1079 messageBuffer.append(getRecipient());
1080 messageBuffer.append('.');
1081 logStatusInfo(messageBuffer.toString());
1082 return getRecipient();
1083 }
1084
1085
1086
1087 String targetRecipient = getEnvelopeRecipient(getMessageIn());
1088 if (targetRecipient != null)
1089 {
1090 MailAddress recipient = new MailAddress(targetRecipient);
1091 StringBuffer messageBuffer =
1092 new StringBuffer("Using original envelope recipient as new envelope recipient: ");
1093 messageBuffer.append(recipient);
1094 messageBuffer.append('.');
1095 logStatusInfo(messageBuffer.toString());
1096 return recipient;
1097 }
1098
1099
1100
1101
1102
1103 Address[] allRecipients = getMessageIn().getAllRecipients();
1104 if (allRecipients.length == 1)
1105 {
1106 MailAddress recipient =
1107 new MailAddress((InternetAddress) allRecipients[0]);
1108 StringBuffer messageBuffer =
1109 new StringBuffer("Using sole recipient header address as new envelope recipient: ");
1110 messageBuffer.append(recipient);
1111 messageBuffer.append('.');
1112 logStatusInfo(messageBuffer.toString());
1113 return recipient;
1114 }
1115
1116 return null;
1117 }
1118
1119 /***
1120 * Returns the messageIn.
1121 * @return MimeMessage
1122 */
1123 protected MimeMessage getMessageIn()
1124 {
1125 return fieldMessageIn;
1126 }
1127
1128 /***
1129 * Sets the messageIn.
1130 * @param messageIn The messageIn to set
1131 */
1132 protected void setMessageIn(MimeMessage messageIn)
1133 {
1134 fieldMessageIn = messageIn;
1135 }
1136
1137 /***
1138 * Returns the localRecipient.
1139 * @return boolean
1140 */
1141 protected boolean isRemoteRecipient()
1142 {
1143 return fieldRemoteRecipient;
1144 }
1145
1146 /***
1147 * Returns <code>boolean</code> indicating if the message to be delivered
1148 * was unprocessed in a previous delivery attempt.
1149 * @return boolean
1150 */
1151 protected boolean isPreviouslyUnprocessed()
1152 {
1153 return true;
1154 }
1155
1156 /***
1157 * Log the status of the current message as INFO.
1158 * @param detailMsg
1159 */
1160 protected void logStatusInfo(String detailMsg) throws MessagingException
1161 {
1162 getLogger().info(getStatusReport(detailMsg).toString());
1163 }
1164
1165 /***
1166 * Log the status the current message as WARN.
1167 * @param detailMsg
1168 */
1169 protected void logStatusWarn(String detailMsg) throws MessagingException
1170 {
1171 getLogger().warn(getStatusReport(detailMsg).toString());
1172 }
1173
1174 /***
1175 * Log the status the current message as ERROR.
1176 * @param detailMsg
1177 */
1178 protected void logStatusError(String detailMsg) throws MessagingException
1179 {
1180 getLogger().error(getStatusReport(detailMsg).toString());
1181 }
1182
1183 /***
1184 * Answer a <code>StringBuffer</code> containing a message reflecting
1185 * the current status of the message being processed.
1186 *
1187 * @param detailMsg
1188 * @return StringBuffer
1189 */
1190 protected StringBuffer getStatusReport(String detailMsg) throws MessagingException
1191 {
1192 StringBuffer messageBuffer = new StringBuffer(detailMsg);
1193 if (detailMsg.length() > 0)
1194 messageBuffer.append(' ');
1195 messageBuffer.append("Message ID: ");
1196 messageBuffer.append(getMessageIn().getMessageID());
1197 messageBuffer.append(". Flags: Seen = ");
1198 messageBuffer.append(new Boolean(isMessageSeen()));
1199 messageBuffer.append(", Delete = ");
1200 messageBuffer.append(new Boolean(isMessageDeleted()));
1201 messageBuffer.append('.');
1202 return messageBuffer;
1203 }
1204
1205 /***
1206 * Returns the userUndefined.
1207 * @return boolean
1208 */
1209 protected boolean isUserUndefined()
1210 {
1211 return fieldUserUndefined;
1212 }
1213
1214 /***
1215 * Is the DELETED flag set?
1216 * @throws MessagingException
1217 */
1218 protected boolean isMessageDeleted() throws MessagingException
1219 {
1220 return getMessageIn().isSet(Flags.Flag.DELETED);
1221 }
1222
1223 /***
1224 * Is the SEEN flag set?
1225 * @throws MessagingException
1226 */
1227 protected boolean isMessageSeen() throws MessagingException
1228 {
1229 return getMessageIn().isSet(Flags.Flag.SEEN);
1230 }
1231
1232 /***
1233 * Set the DELETED flag.
1234 * @throws MessagingException
1235 */
1236 protected void setMessageDeleted() throws MessagingException
1237 {
1238 getMessageIn().setFlag(Flags.Flag.DELETED, true);
1239 }
1240
1241 /* /***
1242 * Set the SEEN flag.
1243 * @throws MessagingException
1244 */
1245 protected void setMessageSeen() throws MessagingException
1246 {
1247
1248
1249 if (!getMessageIn()
1250 .getFolder()
1251 .getPermanentFlags()
1252 .contains(Flags.Flag.SEEN))
1253 handleMarkSeenNotPermanent();
1254 else
1255 getMessageIn().setFlag(Flags.Flag.SEEN, true);
1256 }
1257
1258 /***
1259 * <p>Handler for when the folder does not support the SEEN flag.
1260 * The default behaviour implemented here is to log a warning and set the
1261 * flag anyway.</p>
1262 *
1263 * <p> Subclasses may choose to override this and implement their own
1264 * solutions.</p>
1265 *
1266 * @throws MessagingException
1267 */
1268 protected void handleMarkSeenNotPermanent() throws MessagingException
1269 {
1270 getMessageIn().setFlag(Flags.Flag.SEEN, true);
1271 logStatusWarn("Message marked as SEEN, but the folder does not support a permanent SEEN flag.");
1272 }
1273
1274 /***
1275 * Returns the Blacklisted.
1276 * @return boolean
1277 */
1278 protected boolean isBlacklistedRecipient()
1279 {
1280 return fieldBlacklistedRecipient;
1281 }
1282
1283 /***
1284 * Sets the localRecipient.
1285 * @param localRecipient The localRecipient to set
1286 */
1287 protected void setRemoteRecipient(boolean localRecipient)
1288 {
1289 fieldRemoteRecipient = localRecipient;
1290 }
1291
1292 /***
1293 * Sets the userUndefined.
1294 * @param userUndefined The userUndefined to set
1295 */
1296 protected void setUserUndefined(boolean userUndefined)
1297 {
1298 fieldUserUndefined = userUndefined;
1299 }
1300
1301 /***
1302 * Adds the mail attributes to a <code>Mail</code>.
1303 * @param aMail a Mail instance
1304 */
1305 protected void addMailAttributes(Mail aMail) throws MessagingException
1306 {
1307 aMail.setAttribute(
1308 getAttributePrefix() + "taskName",
1309 getFetchTaskName());
1310
1311 aMail.setAttribute(
1312 getAttributePrefix() + "folderName",
1313 getMessageIn().getFolder().getFullName());
1314
1315 if (isRemoteRecipient())
1316 aMail.setAttribute(
1317 getAttributePrefix() + "isRemoteRecipient",
1318 null);
1319
1320 if (isUserUndefined())
1321 aMail.setAttribute(getAttributePrefix() + "isUserUndefined", null);
1322
1323 if (isBlacklistedRecipient())
1324 aMail.setAttribute(
1325 getAttributePrefix() + "isBlacklistedRecipient",
1326 null);
1327
1328 if (isRecipientNotFound())
1329 aMail.setAttribute(
1330 getAttributePrefix() + "isRecipientNotFound",
1331 null);
1332
1333 if (isMaxMessageSizeExceeded().booleanValue())
1334 aMail.setAttribute(
1335 getAttributePrefix() + "isMaxMessageSizeExceeded",
1336 new Integer(getMessageIn().getSize()).toString());
1337
1338 if (isRemoteReceivedHeaderInvalid().booleanValue())
1339 aMail.setAttribute(
1340 getAttributePrefix() + "isRemoteReceivedHeaderInvalid",
1341 null);
1342
1343 if (isDefaultSenderLocalPart())
1344 aMail.setAttribute(
1345 getAttributePrefix() + "isDefaultSenderLocalPart",
1346 null);
1347
1348 if (isDefaultSenderDomainPart())
1349 aMail.setAttribute(
1350 getAttributePrefix() + "isDefaultSenderDomainPart",
1351 null);
1352
1353 if (isDefaultRemoteAddress())
1354 aMail.setAttribute(
1355 getAttributePrefix() + "isDefaultRemoteAddress",
1356 null);
1357 }
1358
1359 /***
1360 * Adds any required error messages to a <code>Mail</code>.
1361 * @param aMail a Mail instance
1362 */
1363 protected void addErrorMessages(Mail mail) throws MessagingException
1364 {
1365 if (isMaxMessageSizeExceeded().booleanValue())
1366 {
1367 StringBuffer msgBuffer =
1368 new StringBuffer("550 - Rejected - This message has been rejected as the message size of ");
1369 msgBuffer.append(getMessageIn().getSize() * 1000 / 1024 / 1000f);
1370 msgBuffer.append("KB exceeds the maximum permitted size of ");
1371 msgBuffer.append(getMaxMessageSizeLimit() / 1024);
1372 msgBuffer.append("KB.");
1373 mail.setErrorMessage(msgBuffer.toString());
1374 }
1375 }
1376
1377 /***
1378 * Sets the Blacklisted.
1379 * @param blacklisted The blacklisted to set
1380 */
1381 protected void setBlacklistedRecipient(boolean blacklisted)
1382 {
1383 fieldBlacklistedRecipient = blacklisted;
1384 }
1385
1386 /***
1387 * Returns the recipientNotFound.
1388 * @return boolean
1389 */
1390 protected boolean isRecipientNotFound()
1391 {
1392 return fieldRecipientNotFound;
1393 }
1394
1395 /***
1396 * Sets the recipientNotFound.
1397 * @param recipientNotFound The recipientNotFound to set
1398 */
1399 protected void setRecipientNotFound(boolean recipientNotFound)
1400 {
1401 fieldRecipientNotFound = recipientNotFound;
1402 }
1403
1404 /***
1405 * Returns the remoteDomain, lazily initialised as required.
1406 * @return String
1407 */
1408 protected String getRemoteDomain() throws MessagingException
1409 {
1410 String remoteDomain;
1411 if (null == (remoteDomain = getRemoteDomainBasic()))
1412 {
1413 updateRemoteDomain();
1414 return getRemoteDomain();
1415 }
1416 return remoteDomain;
1417 }
1418
1419 /***
1420 * Returns the remoteDomain.
1421 * @return String
1422 */
1423 private String getRemoteDomainBasic()
1424 {
1425 return fieldRemoteDomain;
1426 }
1427
1428 /***
1429 * Sets the remoteDomain.
1430 * @param remoteDomain The remoteDomain to set
1431 */
1432 protected void setRemoteDomain(String remoteDomain)
1433 {
1434 fieldRemoteDomain = remoteDomain;
1435 }
1436
1437 /***
1438 * Updates the remoteDomain.
1439 */
1440 protected void updateRemoteDomain() throws MessagingException
1441 {
1442 setRemoteDomain(computeRemoteDomain());
1443 }
1444
1445 /***
1446 * Answer the IP Address of the remote server for the message being
1447 * processed.
1448 * @return String
1449 * @throws MessagingException
1450 * @throws UnknownHostException
1451 */
1452 protected String computeRemoteAddress()
1453 throws MessagingException, UnknownHostException
1454 {
1455 String domain = getRemoteDomain();
1456 String address = null;
1457 String validatedAddress = null;
1458 int ipAddressStart = domain.indexOf('[');
1459 int ipAddressEnd = -1;
1460 if (ipAddressStart > -1)
1461 ipAddressEnd = domain.indexOf(']', ipAddressStart);
1462 if (ipAddressEnd > -1)
1463 address = domain.substring(ipAddressStart + 1, ipAddressEnd);
1464 else
1465 {
1466 int hostNameEnd = domain.indexOf(' ');
1467 if (hostNameEnd == -1)
1468 hostNameEnd = domain.length();
1469 address = domain.substring(0, hostNameEnd);
1470 }
1471 validatedAddress = org.apache.james.dnsserver.DNSServer.getByName(address).getHostAddress();
1472
1473 return validatedAddress;
1474 }
1475
1476 /***
1477 * Answer the Canonical host name of the remote server for the message
1478 * being processed.
1479 * @return String
1480 * @throws MessagingException
1481 * @throws UnknownHostException
1482 */
1483 protected String computeRemoteHostName()
1484 throws MessagingException, UnknownHostException
1485 {
1486
1487
1488
1489 InetAddress addr1 = org.apache.james.dnsserver.DNSServer.getByName(getRemoteAddress());
1490 InetAddress addr2 = org.apache.james.dnsserver.DNSServer.getByName(addr1.getHostAddress());
1491 return addr2.getHostName();
1492 }
1493
1494 /***
1495 * Returns the remoteAddress, lazily initialised as required.
1496 * @return String
1497 */
1498 protected String getRemoteAddress()
1499 throws MessagingException, UnknownHostException
1500 {
1501 String remoteAddress;
1502 if (null == (remoteAddress = getRemoteAddressBasic()))
1503 {
1504 updateRemoteAddress();
1505 return getRemoteAddress();
1506 }
1507 return remoteAddress;
1508 }
1509
1510 /***
1511 * Returns the remoteAddress.
1512 * @return String
1513 */
1514 private String getRemoteAddressBasic()
1515 {
1516 return fieldRemoteAddress;
1517 }
1518
1519 /***
1520 * Returns the remoteHostName, lazily initialised as required.
1521 * @return String
1522 */
1523 protected String getRemoteHostName()
1524 throws MessagingException, UnknownHostException
1525 {
1526 String remoteHostName;
1527 if (null == (remoteHostName = getRemoteHostNameBasic()))
1528 {
1529 updateRemoteHostName();
1530 return getRemoteHostName();
1531 }
1532 return remoteHostName;
1533 }
1534
1535 /***
1536 * Returns the remoteHostName.
1537 * @return String
1538 */
1539 private String getRemoteHostNameBasic()
1540 {
1541 return fieldRemoteHostName;
1542 }
1543
1544 /***
1545 * Sets the remoteAddress.
1546 * @param remoteAddress The remoteAddress to set
1547 */
1548 protected void setRemoteAddress(String remoteAddress)
1549 {
1550 fieldRemoteAddress = remoteAddress;
1551 }
1552
1553 /***
1554 * Updates the remoteAddress.
1555 */
1556 protected void updateRemoteAddress()
1557 throws MessagingException, UnknownHostException
1558 {
1559 setRemoteAddress(computeRemoteAddress());
1560 }
1561
1562 /***
1563 * Sets the remoteHostName.
1564 * @param remoteHostName The remoteHostName to set
1565 */
1566 protected void setRemoteHostName(String remoteHostName)
1567 {
1568 fieldRemoteHostName = remoteHostName;
1569 }
1570
1571 /***
1572 * Updates the remoteHostName.
1573 */
1574 protected void updateRemoteHostName()
1575 throws MessagingException, UnknownHostException
1576 {
1577 setRemoteHostName(computeRemoteHostName());
1578 }
1579
1580 /***
1581 * Returns the rFC2822RECEIVEDHeaderFields.
1582 * @return String
1583 */
1584 public static String getRFC2822RECEIVEDHeaderFields()
1585 {
1586 return fieldRFC2822RECEIVEDHeaderFields;
1587 }
1588
1589 /***
1590 * Returns the maxMessageSizeExceeded, lazily initialised as required.
1591 * @return Boolean
1592 */
1593 protected Boolean isMaxMessageSizeExceeded() throws MessagingException
1594 {
1595 Boolean isMaxMessageSizeExceeded = null;
1596 if (null
1597 == (isMaxMessageSizeExceeded = isMaxMessageSizeExceededBasic()))
1598 {
1599 updateMaxMessageSizeExceeded();
1600 return isMaxMessageSizeExceeded();
1601 }
1602 return isMaxMessageSizeExceeded;
1603 }
1604
1605 /***
1606 * Refreshes the maxMessageSizeExceeded.
1607 */
1608 protected void updateMaxMessageSizeExceeded() throws MessagingException
1609 {
1610 setMaxMessageSizeExceeded(computeMaxMessageSizeExceeded());
1611 }
1612
1613 /***
1614 * Compute the maxMessageSizeExceeded.
1615 * @return Boolean
1616 */
1617 protected Boolean computeMaxMessageSizeExceeded() throws MessagingException
1618 {
1619 if (0 == getMaxMessageSizeLimit())
1620 return Boolean.FALSE;
1621 return new Boolean(getMessageIn().getSize() > getMaxMessageSizeLimit());
1622 }
1623
1624 /***
1625 * Returns the maxMessageSizeExceeded.
1626 * @return Boolean
1627 */
1628 private Boolean isMaxMessageSizeExceededBasic()
1629 {
1630 return fieldMaxMessageSizeExceeded;
1631 }
1632
1633 /***
1634 * Sets the maxMessageSizeExceeded.
1635 * @param maxMessageSizeExceeded The maxMessageSizeExceeded to set
1636 */
1637 protected void setMaxMessageSizeExceeded(Boolean maxMessageSizeExceeded)
1638 {
1639 fieldMaxMessageSizeExceeded = maxMessageSizeExceeded;
1640 }
1641
1642 /***
1643 * Returns the remoteReceivedHeaderInvalid, lazily initialised.
1644 * @return Boolean
1645 */
1646 protected Boolean isRemoteReceivedHeaderInvalid() throws MessagingException
1647 {
1648 Boolean isInvalid = null;
1649 if (null == (isInvalid = isRemoteReceivedHeaderInvalidBasic()))
1650 {
1651 updateRemoteReceivedHeaderInvalid();
1652 return isRemoteReceivedHeaderInvalid();
1653 }
1654 return isInvalid;
1655 }
1656
1657 /***
1658 * Computes the remoteReceivedHeaderInvalid.
1659 * @return Boolean
1660 */
1661 protected Boolean computeRemoteReceivedHeaderInvalid()
1662 throws MessagingException
1663 {
1664 Boolean isInvalid = Boolean.FALSE;
1665 try
1666 {
1667 getRemoteAddress();
1668 }
1669 catch (UnknownHostException e)
1670 {
1671 isInvalid = Boolean.TRUE;
1672 }
1673 return isInvalid;
1674 }
1675
1676 /***
1677 * Returns the remoteReceivedHeaderInvalid.
1678 * @return Boolean
1679 */
1680 private Boolean isRemoteReceivedHeaderInvalidBasic()
1681 {
1682 return fieldRemoteReceivedHeaderInvalid;
1683 }
1684
1685 /***
1686 * Sets the remoteReceivedHeaderInvalid.
1687 * @param remoteReceivedHeaderInvalid The remoteReceivedHeaderInvalid to set
1688 */
1689 protected void setRemoteReceivedHeaderInvalid(Boolean remoteReceivedHeaderInvalid)
1690 {
1691 fieldRemoteReceivedHeaderInvalid = remoteReceivedHeaderInvalid;
1692 }
1693
1694 /***
1695 * Updates the remoteReceivedHeaderInvalid.
1696 */
1697 protected void updateRemoteReceivedHeaderInvalid() throws MessagingException
1698 {
1699 setRemoteReceivedHeaderInvalid(computeRemoteReceivedHeaderInvalid());
1700 }
1701
1702 /***
1703 * Returns the defaultSenderDomainPart.
1704 * @return boolean
1705 */
1706 protected boolean isDefaultSenderDomainPart()
1707 {
1708 return fieldDefaultSenderDomainPart;
1709 }
1710
1711 /***
1712 * Returns the defaultSenderLocalPart.
1713 * @return boolean
1714 */
1715 protected boolean isDefaultSenderLocalPart()
1716 {
1717 return fieldDefaultSenderLocalPart;
1718 }
1719
1720 /***
1721 * Sets the defaultSenderDomainPart.
1722 * @param defaultSenderDomainPart The defaultSenderDomainPart to set
1723 */
1724 protected void setDefaultSenderDomainPart(boolean defaultSenderDomainPart)
1725 {
1726 fieldDefaultSenderDomainPart = defaultSenderDomainPart;
1727 }
1728
1729 /***
1730 * Sets the defaultSenderLocalPart.
1731 * @param defaultSenderLocalPart The defaultSenderLocalPart to set
1732 */
1733 protected void setDefaultSenderLocalPart(boolean defaultSenderLocalPart)
1734 {
1735 fieldDefaultSenderLocalPart = defaultSenderLocalPart;
1736 }
1737
1738 /***
1739 * Returns the defaultRemoteAddress.
1740 * @return boolean
1741 */
1742 protected boolean isDefaultRemoteAddress()
1743 {
1744 return fieldDefaultRemoteAddress;
1745 }
1746
1747 /***
1748 * Sets the defaultRemoteAddress.
1749 * @param defaultRemoteAddress The defaultRemoteAddress to set
1750 */
1751 protected void setDefaultRemoteAddress(boolean defaultRemoteAddress)
1752 {
1753 fieldDefaultRemoteAddress = defaultRemoteAddress;
1754 }
1755
1756 }