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