📄 messageprocessor.java
字号:
/*********************************************************************** * Copyright (c) 2003-2004 The Apache Software Foundation. * * All rights reserved. * * ------------------------------------------------------------------- * * Licensed under the Apache License, Version 2.0 (the "License"); you * * may not use this file except in compliance with the License. You * * may obtain a copy of the License at: * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * * implied. See the License for the specific language governing * * permissions and limitations under the License. * ***********************************************************************/ package org.apache.james.fetchmail;import java.io.InputStream;import java.net.InetAddress;import java.net.UnknownHostException;import java.util.ArrayList;import java.util.Collection;import java.util.Enumeration;import java.util.Iterator;import java.util.StringTokenizer;import javax.mail.Address;import javax.mail.Flags;import javax.mail.Folder;import javax.mail.MessagingException;import javax.mail.Session;import javax.mail.internet.InternetAddress;import javax.mail.internet.InternetHeaders;import javax.mail.internet.MimeMessage;import javax.mail.internet.ParseException;import org.apache.james.core.MailImpl;import org.apache.james.util.RFC2822Headers;import org.apache.mailet.Mail;import org.apache.mailet.MailAddress;/** * <p>Class <code>MessageProcessor</code> handles the delivery of * <code>MimeMessages</code> to the James input spool.</p> * * <p>Messages written to the input spool always have the following Mail * Attributes set:</p> * <dl> * <dt>org.apache.james.fetchmail.taskName (java.lang.String)</dt> * <dd>The name of the fetch task that processed the message</dd> * <dt>org.apache.james.fetchmail.folderName (java.lang.String)</dt> * <dd>The name of the folder from which the message was fetched</dd> * </dl> * * <p>Messages written to the input spool have the following Mail Attributes * set if the corresponding condition is satisfied: * <dl> * <dt>org.apache.james.fetchmail.isBlacklistedRecipient</dt> * <dd>The recipient is in the configured blacklist</dd> * <dt>org.apache.james.fetchmail.isMaxMessageSizeExceeded (java.lang.String)</dt> * <dd>The message size exceeds the configured limit. An empty message is * written to the input spool. The Mail Attribute value is a String * representing the size of the original message in bytes.</dd> * <dt>org.apache.james.fetchmail.isRecipientNotFound</dt> * <dd>The recipient could not be found. Delivery is to the configured recipient. * See the discussion of delivery to a sole intended recipient below.</dd> * <dt>org.apache.james.fetchmail.isRemoteRecievedHeaderInvalid</dt> * <dd>The Receieved header at the index specified by parameter * <code>remoteReceivedHeaderIndex</code> is invalid.</dd> * <dt>org.apache.james.fetchmail.isRemoteRecipient</dt> * <dd>The recipient is on a remote host</dd> * <dt>org.apache.james.fetchmail.isUserUndefined</dt> * <dd>The recipient is on a localhost but not defined to James</dd> * </dl> * * <p>Configuration settings - * see <code>org.apache.james.fetchmail.ParsedConfiguration</code> * - control the messages that are written to the James input spool, those that * are rejected and what happens to messages that are rejected.</p> * * <p>Rejection processing is based on the following filters:</p> * <dl> * <dt>RejectRemoteRecipient</dt> * <dd>Rejects recipients on remote hosts</dd> * <dt>RejectBlacklistedRecipient</dt> * <dd>Rejects recipients configured in a blacklist</dd> * <dt>RejectUserUndefined</dt> * <dd>Rejects recipients on local hosts who are not defined as James users</dd> * <dt>RejectRecipientNotFound</dt> * <dd>See the discussion of delivery to a sole intended recipient below</dd> * <dt>RejectMaxMessageSizeExceeded</dt> * <dd>Rejects messages whose size exceeds the configured limit</dd> * <dt>RejectRemoteReceievedHeaderInvalid</dt> * <dd>Rejects messages whose Received header is invalid.</dd> * </dl> * * <p>Rejection processing is intentionally limited to managing the status of the * messages that are rejected on the server from which they were fetched. View * it as a simple automation of the manual processing an end-user would perform * through a mail client. Messages may be marked as seen or be deleted.</p> * * <p>Further processing can be achieved by configuring to disable rejection for * one or more filters. This enables Messages that would have been rejected to * be written to the James input spool. The conditional Mail Attributes * described above identify the filter states. The Matcher/Mailet chain can * then be used to perform any further processing required, such as notifying * the Postmaster and/or sender, marking the message for error processing, etc.</p> * * <p>Note that in the case of a message exceeding the message size limit, the * message that is written to the input spool has no content. This enables * configuration of a mailet notifying the sender that their mail has not been * delivered due to its size while maintaining the purpose of the filter which is * to avoid injecting excessively large messages into the input spool.</p> * * <p>Delivery is to a sole intended recipient. The recipient is determined in the * following manner:</p> * * <ol> * <li>If isIgnoreIntendedRecipient(), use the configured recipient</li> * <li>If the Envelope contains a for: stanza, use the recipient in the stanza</li> * <li>If the Message has a sole intended recipient, use this recipient</li> * <li>If not rejectRecipientNotFound(), use the configured recipient</li> * </ol> * * <p>If a recipient cannot be determined after these steps, the message is * rejected.</p> * * <p>Every delivered message CURRENTLY has an "X-fetched-from" header added * containing the name of the fetch task. Its primary uses are to detect bouncing * mail and provide backwards compatibility with the fetchPop task that inserted * this header to enable injected messages to be detected in the Matcher/Mailet * chain. This header is DEPRECATED and WILL BE REMOVED in a future version of * fetchmail. Use the Mail Attribute <code>org.apache.james.fetchmail.taskName</code> * instead. * * <p><code>MessageProcessor</code> is as agnostic as it can be about the format * and contents of the messages it delivers. There are no RFCs that govern its * behavior. The most releveant RFCs relate to the exchange of messages between * MTA servers, but not POP3 or IMAP servers which are normally end-point * servers and not expected to re-inject mail into MTAs. None the less, the * intent is to conform to the 'spirit' of the RFCs. * <code>MessageProcessor</code> relies on the MTA (James in this * implementation) to manage and validate the injected mail just as it would * when receiving mail from an upstream MTA.</p> * * <p>The only correction applied by <code>MessageProcessor</code> is to correct a * partial originator address. If the originator address has a valid user part * but no domain part, a domain part is added. The added domain is either the * default domain specified in the configuration, or if not specified, the * fully qualified name of the machine on which the fetch task is running.</p> * * <p>The status of messages on the server from which they were fetched that * cannot be injected into the input spool due to non-correctable errors is * determined by the undeliverable configuration options.</p> * * <p>Creation Date: 27-May-03</p> * */public class MessageProcessor extends ProcessorAbstract{ private MimeMessage fieldMessageIn; /** * Recipient cannot be found */ private boolean fieldRecipientNotFound = false; /** * Recipient is a local user on a local host */ private boolean fieldRemoteRecipient = true; /** * The mail's Received header at index remoteReceivedHeaderIndex is invalid. */ private Boolean fieldRemoteReceivedHeaderInvalid; /** * Recipient is not a local user */ private boolean fieldUserUndefined = false; /** * The Maximum Message has been exceeded */ private Boolean fieldMaxMessageSizeExceeded; /** * Field names for an RFC2822 compliant RECEIVED Header */ static final private String fieldRFC2822RECEIVEDHeaderFields = "from by via with id for ;"; /** * Recipient is blacklisted */ private boolean fieldBlacklistedRecipient = false; /** * The RFC2822 compliant "Received : from" domain */ private String fieldRemoteDomain; /** * The remote address derived from the remote domain */ private String fieldRemoteAddress; /** * The remote host name derived from the remote domain */ private String fieldRemoteHostName; /** * Constructor for MessageProcessor. * * @param account */ private MessageProcessor(Account account) { super(account); } /** * Constructor for MessageProcessor. * * @param messageIn * @param account */ MessageProcessor( MimeMessage messageIn, Account account) { this(account); setMessageIn(messageIn); } /** * Method process attempts to deliver a fetched message. * * @see org.apache.james.fetchmail.ProcessorAbstract#process() */ public void process() throws MessagingException { // Log delivery attempt if (getLogger().isDebugEnabled()) { StringBuffer logMessageBuffer = new StringBuffer("Attempting delivery of message with id. "); logMessageBuffer.append(getMessageIn().getMessageID()); getLogger().debug(logMessageBuffer.toString()); } // Determine the intended recipient MailAddress intendedRecipient = getIntendedRecipient(); setRecipientNotFound(null == intendedRecipient); if (isRecipientNotFound()) { if (isDeferRecipientNotFound()) { String messageID = getMessageIn().getMessageID(); if (!getDeferredRecipientNotFoundMessageIDs() .contains(messageID)) { getDeferredRecipientNotFoundMessageIDs().add(messageID); if (getLogger().isDebugEnabled()) { StringBuffer messageBuffer = new StringBuffer("Deferred processing of message for which the intended recipient could not be found. Message ID: "); messageBuffer.append(messageID); getLogger().debug(messageBuffer.toString()); } return; } else { getDeferredRecipientNotFoundMessageIDs().remove(messageID); if (getLogger().isDebugEnabled()) { StringBuffer messageBuffer = new StringBuffer("Processing deferred message for which the intended recipient could not be found. Message ID: "); messageBuffer.append(messageID); getLogger().debug(messageBuffer.toString()); } } } if (isRejectRecipientNotFound()) { rejectRecipientNotFound(); return; } intendedRecipient = getRecipient(); StringBuffer messageBuffer = new StringBuffer("Intended recipient not found. Using configured recipient as new envelope recipient - "); messageBuffer.append(intendedRecipient); messageBuffer.append('.'); logStatusInfo(messageBuffer.toString()); } // Set the filter states setBlacklistedRecipient(isBlacklistedRecipient(intendedRecipient)); setRemoteRecipient(!isLocalServer(intendedRecipient)); setUserUndefined(!isLocalRecipient(intendedRecipient)); // Apply the filters. Return if rejected if (isRejectBlacklisted() && isBlacklistedRecipient()) { rejectBlacklistedRecipient(intendedRecipient); return; } if (isRejectRemoteRecipient() && isRemoteRecipient()) { rejectRemoteRecipient(intendedRecipient); return; } if (isRejectUserUndefined() && isUserUndefined()) { rejectUserUndefined(intendedRecipient); return; } if (isRejectMaxMessageSizeExceeded() && isMaxMessageSizeExceeded().booleanValue()) { rejectMaxMessageSizeExceeded(getMessageIn().getSize()); return; } if (isRejectRemoteReceivedHeaderInvalid() && isRemoteReceivedHeaderInvalid().booleanValue()) { rejectRemoteReceivedHeaderInvalid(); return; } // Create the mail // If any of the mail addresses are malformed, we will get a // ParseException. // If the IP address and host name for the remote domain cannot // be found, we will get an UnknownHostException. // In both cases, we log the problem and // return. The message disposition is defined by the // <undeliverable> attributes. Mail mail = null; try { mail = createMail(createMessage(), intendedRecipient); } catch (ParseException ex) { handleParseException(ex); return; } catch (UnknownHostException ex) { handleUnknownHostException(ex); return; } addMailAttributes(mail); addErrorMessages(mail); // If this mail is bouncing move it to the ERROR repository if (isBouncing()) { handleBouncing(mail); return; } // OK, lets send that mail! sendMail(mail); } /** * Method rejectRemoteRecipient. * @param recipient * @throws MessagingException */ protected void rejectRemoteRecipient(MailAddress recipient) throws MessagingException { // Update the flags of the received message if (!isLeaveRemoteRecipient()) setMessageDeleted(); if (isMarkRemoteRecipientSeen()) setMessageSeen(); StringBuffer messageBuffer = new StringBuffer("Rejected mail intended for remote recipient: ");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -