You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by no...@apache.org on 2003/10/20 05:43:27 UTC

cvs commit: james-server/src/xdocs fetchmail_configuration_2_2.xml

noel        2003/10/19 20:43:27

  Modified:    src/conf Tag: branch_2_1_fcs james-fetchmail.xml
               src/java/org/apache/james/fetchmail Tag: branch_2_1_fcs
                        FetchMail.java FolderProcessor.java
                        MessageProcessor.java ParsedConfiguration.java
                        ProcessorAbstract.java StoreProcessor.java
               src/xdocs Tag: branch_2_1_fcs
                        fetchmail_configuration_2_2.xml
  Log:
  1) The MailImpl instance sent to James now includes the remote address and
  remote host of the n'th relay in the delivery chain as reported by the
  'from' field of the 'RECEIVED' headers. This is equivalent to the remote
  address and remote host set in the MailImpl by the SMTPHandler deduced from
  the socket of the connected server.
  
  The n'th relay is specified by the new fetchmail configuration parameter
  'remoteReceivedHeaderIndex'. This is explained in the configuration file and
  updated xdoc.
  
  The InSpammerBlackList matcher validates against the remote address in the
  MailImpl. Prior to this patch it was having no effect and all mail was
  considered valid.
  
  2) Made logging at the INFO level less verbose and logging at the DEBUG
  level more detailed.
  
  Submitted by:	Steve Brewin
  
  Revision  Changes    Path
  No                   revision
  No                   revision
  1.1.2.4   +13 -0     james-server/src/conf/Attic/james-fetchmail.xml
  
  Index: james-fetchmail.xml
  ===================================================================
  RCS file: /home/cvs/james-server/src/conf/Attic/james-fetchmail.xml,v
  retrieving revision 1.1.2.3
  retrieving revision 1.1.2.4
  diff -u -r1.1.2.3 -r1.1.2.4
  --- james-fetchmail.xml	23 Sep 2003 19:04:35 -0000	1.1.2.3
  +++ james-fetchmail.xml	20 Oct 2003 03:43:26 -0000	1.1.2.4
  @@ -68,6 +68,19 @@
               <!-- How frequently this host is checked - in milliseconds. 600000 is every ten minutes -->
               <interval>600000</interval>
               
  +            <!-- The zero based index of the RECEIVED Header used to compute the remote address and remote host name -->
  +            <!-- of the MTA that delivered a fetched message. -->
  +            <!-- Typically, the first (index = 0) RECEIVED Header is for the local MTA that delivers mail to the message store -->
  +            <!-- and the second RECEIVED Header (index = 1) is the remote domain delivering mail to the MTA, so the second -->
  +            <!-- RECEIVED Header is the one to use. -->
  +            <!-- Some configurations will differ. Look at the RECEIVED Headers and set the index to point to the first -->
  +            <!-- remote MTA. -->
  +            <!-- Matchers such as InSpammerBlacklist use the remote address and/or remote host name to identify illegitimate -->
  +            <!-- remote MTAs. -->
  +            <!-- This tag is optional. If omitted, it will default to an index of -1, which is interpreted as use 127.0.0.1 for the -->
  +            <!-- remote address and use 'localhost' for the remote host name. Both are almost always considered legitimate. -->
  +            <remoteReceivedHeaderIndex>1</RemoteReceivedHeaderIndex>
  +            
               <!-- name of the javamail provider you wish to use -->
               <!-- (pop3, imap, etc. -->
               <javaMailProviderName>pop3</javaMailProviderName>
  
  
  
  No                   revision
  No                   revision
  1.9.2.4   +4 -2      james-server/src/java/org/apache/james/fetchmail/FetchMail.java
  
  Index: FetchMail.java
  ===================================================================
  RCS file: /home/cvs/james-server/src/java/org/apache/james/fetchmail/FetchMail.java,v
  retrieving revision 1.9.2.3
  retrieving revision 1.9.2.4
  diff -u -r1.9.2.3 -r1.9.2.4
  --- FetchMail.java	23 Sep 2003 19:04:35 -0000	1.9.2.3
  +++ FetchMail.java	20 Oct 2003 03:43:26 -0000	1.9.2.4
  @@ -566,13 +566,15 @@
                   }
                   catch (MessagingException ex)
                   {
  -                    getLogger().error(ex.toString());
  +                    getLogger().error(
  +                        "A MessagingException has terminated processing of this Account",
  +                        ex);
                   }
               }
           }
           catch (Exception ex)
           {
  -            getLogger().error(ex.toString());
  +            getLogger().error("An Exception has terminated this fetch.", ex);
           }
           finally
           {
  
  
  
  1.1.2.3   +8 -6      james-server/src/java/org/apache/james/fetchmail/Attic/FolderProcessor.java
  
  Index: FolderProcessor.java
  ===================================================================
  RCS file: /home/cvs/james-server/src/java/org/apache/james/fetchmail/Attic/FolderProcessor.java,v
  retrieving revision 1.1.2.2
  retrieving revision 1.1.2.3
  diff -u -r1.1.2.2 -r1.1.2.3
  --- FolderProcessor.java	21 Sep 2003 20:03:35 -0000	1.1.2.2
  +++ FolderProcessor.java	20 Oct 2003 03:43:26 -0000	1.1.2.3
  @@ -144,18 +144,18 @@
                       catch (MessagingException mex)
                       {
                           StringBuffer logMessageBuffer =
  -                            new StringBuffer("Exception processing message ID: ");
  +                            new StringBuffer("MessagingException processing message ID: ");
                           logMessageBuffer.append(message.getMessageID());
  -                        logMessageBuffer.append(" - ");
  -                        logMessageBuffer.append(mex.toString());
  -                        getLogger().error(logMessageBuffer.toString());
  +                        getLogger().error(logMessageBuffer.toString(), mex);
                       }
                   }
               }
           }
           catch (MessagingException mex)
           {
  -            getLogger().error(mex.toString());
  +            getLogger().error(
  +                "A MessagingException has terminated fetching messages for this folder",
  +                mex);
           }
           finally
           {
  @@ -184,7 +184,9 @@
           }
           catch (MessagingException mex)
           {
  -            getLogger().error(mex.toString());
  +            getLogger().error(
  +                "A MessagingException has terminated recursing through sub-folders",
  +                mex);
           }
   
           return;
  
  
  
  1.1.2.3   +505 -97   james-server/src/java/org/apache/james/fetchmail/Attic/MessageProcessor.java
  
  Index: MessageProcessor.java
  ===================================================================
  RCS file: /home/cvs/james-server/src/java/org/apache/james/fetchmail/Attic/MessageProcessor.java,v
  retrieving revision 1.1.2.2
  retrieving revision 1.1.2.3
  diff -u -r1.1.2.2 -r1.1.2.3
  --- MessageProcessor.java	21 Sep 2003 20:03:35 -0000	1.1.2.2
  +++ MessageProcessor.java	20 Oct 2003 03:43:26 -0000	1.1.2.3
  @@ -58,9 +58,13 @@
    
   package org.apache.james.fetchmail;
   
  +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;
  @@ -70,6 +74,7 @@
   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;
   
  @@ -192,12 +197,34 @@
        */ 
       private boolean fieldUserUndefined = false;
       
  +    
  +    /**
  +     * 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
  @@ -229,12 +256,15 @@
        * @see org.apache.james.fetchmail.ProcessorAbstract#process()
        */
       public void process() throws MessagingException
  -    {      
  +    {
           // Log delivery attempt
  -        StringBuffer logMessageBuffer =
  -            new StringBuffer("Attempting delivery of message with id. ");
  -        logMessageBuffer.append(getMessageIn().getMessageID());
  -        getLogger().info(logMessageBuffer.toString());
  +        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();
  @@ -250,20 +280,25 @@
                       .contains(messageID))
                   {
                       getDeferredRecipientNotFoundMessageIDs().add(messageID);
  -                    StringBuffer messageBuffer =
  -                        new StringBuffer("Deferred processing of message for which the intended recipient could not be found. Message ID: ");
  -                    messageBuffer.append(messageID);
  -                    getLogger().info(messageBuffer.toString());
  +                    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);
  -                    StringBuffer messageBuffer =
  -                        new StringBuffer("Processing deferred message for which the intended recipient could not be found. Message ID: ");
  -                    messageBuffer.append(messageID);
  -                    getLogger().info(messageBuffer.toString());
  +                    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());
  +                    }
                   }
               }
   
  @@ -275,39 +310,44 @@
               intendedRecipient = getRecipient();
               StringBuffer messageBuffer =
                   new StringBuffer("Intended recipient not found. Using configured recipient as new envelope recipient - ");
  -            messageBuffer.append(intendedRecipient.toString());
  -            getLogger().info(messageBuffer.toString());
  +            messageBuffer.append(intendedRecipient);
  +            messageBuffer.append('.');            
  +            logStatusInfo(messageBuffer.toString());
           }
   
           // Set the filter states
  +        setBlacklistedRecipient(isBlacklistedRecipient(intendedRecipient));
           setRemoteRecipient(!isLocalServer(intendedRecipient));
           setUserUndefined(!isLocalRecipient(intendedRecipient));
  -        setBlacklistedRecipient(isBlacklistedRecipient(intendedRecipient));
   
           // Check recipient against blacklist / whitelist
           // Return if rejected
  -        if (isRejectRemoteRecipient() & isRemoteRecipient())
  +        if (isRejectBlacklisted() && isBlacklistedRecipient())
           {
  -            rejectRemoteRecipient(intendedRecipient);
  +            rejectBlacklistedRecipient(intendedRecipient);
               return;
           }
   
  -        if (isRejectUserUndefined() & isUserUndefined())
  +        if (isRejectRemoteRecipient() && isRemoteRecipient())
           {
  -            rejectUserUndefined(intendedRecipient);
  +            rejectRemoteRecipient(intendedRecipient);
               return;
           }
   
  -        if (isRejectBlacklisted() & isBlacklistedRecipient())
  +        if (isRejectUserUndefined() && isUserUndefined())
           {
  -            rejectBlacklistedRecipient(intendedRecipient);
  +            rejectUserUndefined(intendedRecipient);
               return;
           }
   
           // Create the mail
  -        // If any of the addresses are malformed, we will get a
  -        // ParseException. In which case, we log the problem and
  -        // return. The message will be left unaltered on the server.
  +        // 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
           {
  @@ -315,13 +355,25 @@
           }
           catch (ParseException ex)
           {
  -            handleParseException(ex, intendedRecipient);
  +            handleParseException(ex);
  +            return;
  +        }
  +        catch (UnknownHostException ex)
  +        {
  +            handleUnknownHostException(ex);
               return;
           }
   
           createMailAttributes(mail);
   
  -        // OK, lets try and send that mail  
  +        // If this mail is bouncing move it to the ERROR repository
  +        if (isBouncing())
  +        {
  +            handleBouncing(mail);
  +            return;
  +        }
  +
  +        // OK, lets send that mail!
           sendMail(mail);
       }
   
  @@ -342,8 +394,9 @@
   
           StringBuffer messageBuffer =
               new StringBuffer("Rejected mail intended for remote recipient: ");
  -        messageBuffer.append(recipient.toString());
  -        getLogger().info(messageBuffer.toString());
  +        messageBuffer.append(recipient);
  +        messageBuffer.append('.');          
  +        logStatusInfo(messageBuffer.toString());
   
           return;
       }
  @@ -364,8 +417,9 @@
   
           StringBuffer messageBuffer =
               new StringBuffer("Rejected mail intended for blacklisted recipient: ");
  -        messageBuffer.append(recipient.toString());
  -        getLogger().info(messageBuffer.toString());
  +        messageBuffer.append(recipient);
  +        messageBuffer.append('.');        
  +        logStatusInfo(messageBuffer.toString());
   
           return;
       }
  @@ -384,16 +438,16 @@
               setMessageSeen();
   
           StringBuffer messageBuffer =
  -            new StringBuffer("Rejected mail for which a sole intended recipient could not be found. Message ID: ");
  -        messageBuffer.append(getMessageIn().getMessageID());
  -        messageBuffer.append(", recipients: ");
  +            new StringBuffer("Rejected mail for which a sole intended recipient could not be found.");
  +        messageBuffer.append(" Recipients: ");
           Address[] allRecipients = getMessageIn().getAllRecipients();
           for (int i = 0; i < allRecipients.length; i++)
           {
  -            messageBuffer.append(allRecipients[i].toString());
  +            messageBuffer.append(allRecipients[i]);
               messageBuffer.append(' ');
           }
  -        getLogger().info(messageBuffer.toString());
  +        messageBuffer.append('.');          
  +        logStatusInfo(messageBuffer.toString());
           return;
       }
       
  @@ -414,8 +468,9 @@
   
           StringBuffer messageBuffer =
               new StringBuffer("Rejected mail intended for undefined user: ");
  -        messageBuffer.append(recipient.toString());
  -        getLogger().info(messageBuffer.toString());
  +        messageBuffer.append(recipient);
  +        messageBuffer.append('.');          
  +        logStatusInfo(messageBuffer.toString());
   
           return;
       }   
  @@ -449,15 +504,37 @@
        * @throws MessagingException
        */
       protected Mail createMail(MimeMessage message, MailAddress recipient)
  -        throws MessagingException
  +        throws MessagingException, UnknownHostException
       {
           Collection recipients = new ArrayList(1);
           recipients.add(recipient);
  -        return new MailImpl(
  -            getServer().getId(),
  -            getSender(),
  -            recipients,
  -            message);
  +        MailImpl mail =
  +            new MailImpl(getServer().getId(), getSender(), recipients, message);
  +        mail.setRemoteAddr(getRemoteAddress());
  +        mail.setRemoteHost(getRemoteHostName());
  +
  +        if (getLogger().isDebugEnabled())
  +        {
  +            StringBuffer messageBuffer =
  +                new StringBuffer("Created mail with name: ");
  +            messageBuffer.append(mail.getName());
  +            messageBuffer.append(", sender: ");
  +            messageBuffer.append(mail.getSender());
  +            messageBuffer.append(", recipients: ");
  +            Iterator recipientIterator = mail.getRecipients().iterator();
  +            while (recipientIterator.hasNext())
  +            {
  +                messageBuffer.append(recipientIterator.next());
  +                messageBuffer.append(' ');
  +            }
  +            messageBuffer.append(", remote address: ");
  +            messageBuffer.append(mail.getRemoteAddr());
  +            messageBuffer.append(", remote host name: ");
  +            messageBuffer.append(mail.getRemoteHost());
  +            messageBuffer.append('.');
  +            getLogger().debug(messageBuffer.toString());
  +        }
  +        return mail;
       }
   
       /**
  @@ -487,32 +564,114 @@
       }
       
       /**
  -     * Method handleBouncing sets the Mail state to ERROR.
  +     * <p>Method computeRemoteDomain answers a <code>String</code> that is the
  +     * RFC2822 compliant "Received : from" domain extracted from the message
  +     * being processed.</p>
  +     * 
  +     * <p>Normally this is the domain that sent the message to the host for the
  +     * message store as reported by the second "received" header. The index of
  +     * the header to use is specified by the configuration parameter
  +     * <code>RemoteReceivedHeaderIndex</code>. If a header at this index does
  +     * not exist, the domain of the successively closer "received" headers
  +     * is tried until they are exhausted, then "localhost" is used.</p>
  +     * 
  +     * @return String
  +     */
  +    protected String computeRemoteDomain() throws MessagingException
  +    {
  +        String[] headers = getMessageIn().getHeader(RFC2822Headers.RECEIVED);
  +        StringBuffer domainBuffer = new StringBuffer();
  +
  +        // If there are RECEIVED headers and the index to begin at is greater
  +        // than -1, try and extract the domain
  +        if (headers.length > 0 && getRemoteReceivedHeaderIndex() > -1)
  +        {
  +            final String headerTokens = " \n\r";
  +
  +            // Search the headers for a domain
  +            for (int headerIndex =
  +                headers.length > getRemoteReceivedHeaderIndex()
  +                    ? getRemoteReceivedHeaderIndex()
  +                    : headers.length - 1;
  +                headerIndex >= 0 && domainBuffer.length() == 0;
  +                headerIndex--)
  +            {
  +                // Find the "from" token
  +                StringTokenizer tokenizer =
  +                    new StringTokenizer(headers[headerIndex], headerTokens);
  +                boolean inFrom = false;
  +                while (!inFrom && tokenizer.hasMoreTokens())
  +                    inFrom = tokenizer.nextToken().equals("from");
  +
  +                // Add subsequent tokens to the domain buffer until another 
  +                // field is encountered or there are no more tokens
  +                while (inFrom && tokenizer.hasMoreTokens())
  +                {
  +                    String token = tokenizer.nextToken();
  +                    if (inFrom =
  +                        getRFC2822RECEIVEDHeaderFields().indexOf(token) == -1)
  +                    {
  +                        domainBuffer.append(token);
  +                        domainBuffer.append(' ');
  +                    }
  +                }
  +            }
  +        }
  +
  +        // Default is "localhost"
  +        if (domainBuffer.length() == 0)
  +            domainBuffer.append("localhost");
  +
  +        return domainBuffer.toString().trim();
  +    }    
  +    
  +    /**
  +     * Method handleBouncing sets the Mail state to ERROR and delete from
  +     * the message store.
        * 
        * @param mail
        */
  -    protected void handleBouncing(Mail mail)
  +    protected void handleBouncing(Mail mail) throws MessagingException
       {
           mail.setState(Mail.ERROR);
  +        setMessageDeleted();
  +
           mail.setErrorMessage(
               "This mail from FetchMail task "
                   + getFetchTaskName()
                   + " seems to be bouncing!");
  -        getLogger().error(
  -            "A message from FetchMail task "
  -                + getFetchTaskName()
  -                + " seems to be bouncing! Moved to Error repository");
  +        logStatusError("Message is bouncing! Deleted from message store and moved to the Error repository.");
       }
       
       /**
        * Method handleParseException.
        * @param ex
  -     * @param intendedRecipient
        * @throws MessagingException
        */
  -    protected void handleParseException(
  -        ParseException ex,
  -        MailAddress intendedRecipient)
  +    protected void handleParseException(ParseException ex)
  +        throws MessagingException
  +    {
  +        // Update the flags of the received message
  +        if (!isLeaveUndeliverable())
  +            setMessageDeleted();
  +        if (isMarkUndeliverableSeen())
  +            setMessageSeen();
  +        logStatusWarn("Message could not be delivered due to an error parsing a mail address.");
  +        if (getLogger().isDebugEnabled())
  +        {
  +            StringBuffer messageBuffer =
  +                new StringBuffer("UNDELIVERABLE Message ID: ");
  +            messageBuffer.append(getMessageIn().getMessageID());
  +            getLogger().debug(messageBuffer.toString(), ex);
  +        }
  +    }
  +    
  +    /**
  +     * Method handleUnknownHostException.
  +     * @param ex
  +     * @throws MessagingException
  +     */
  +    protected void handleUnknownHostException(UnknownHostException ex)
           throws MessagingException
       {
           // Update the flags of the received message
  @@ -522,18 +681,15 @@
           if (isMarkUndeliverableSeen())
               setMessageSeen();
   
  -        getLogger().error(
  -            getFetchTaskName()
  -                + " Message could not be processed due to an error parsing the addresses."
  -                + " Subject: "
  -                + getMessageIn().getSubject()
  -                + " From: "
  -                + getMessageIn().getFrom()[0].toString()
  -                + " To: "
  -                + intendedRecipient.toString());
  -        getLogger().debug(ex.toString());
  -        //      ex.printStackTrace();
  -    }
  +        logStatusWarn("Message could not be delivered due to an error determining the remote domain.");
  +        if (getLogger().isDebugEnabled())
  +        {
  +            StringBuffer messageBuffer =
  +                new StringBuffer("UNDELIVERABLE Message ID: ");
  +            messageBuffer.append(getMessageIn().getMessageID());
  +            getLogger().debug(messageBuffer.toString(), ex);
  +        }
  +    }    
       
       /**
        * Method isLocalRecipient.
  @@ -601,18 +757,8 @@
        */
       protected void sendMail(Mail mail) throws MessagingException
       {
  -        // If this mail is bouncing move it to the ERROR repository
  -        //     else
  -        // Send the mail
  -        if (isBouncing())
  -            handleBouncing(mail);
  -        else
  -        {
  -            getServer().sendMail(mail);
  -            getLogger().info(
  -                "Spooled message to " + mail.getRecipients().toString());
  -            getLogger().debug("Sent message " + mail.getMessage().toString());
  -        }
  +        // send the mail
  +        getServer().sendMail(mail);
   
           // Update the flags of the received message
           if (!isLeave())
  @@ -620,6 +766,18 @@
   
           if (isMarkSeen())
               setMessageSeen();
  +
  +        // Log the status
  +        StringBuffer messageBuffer =
  +            new StringBuffer("Spooled message to recipients: ");
  +        Iterator recipientIterator = mail.getRecipients().iterator();
  +        while (recipientIterator.hasNext())
  +        {
  +            messageBuffer.append(recipientIterator.next());
  +            messageBuffer.append(' ');
  +        }
  +        messageBuffer.append('.');
  +        logStatusInfo(messageBuffer.toString());
       }   
   
   
  @@ -634,7 +792,7 @@
        * @return String
        */
   
  -    protected String getEnvelopeRecipient(MimeMessage msg)
  +    protected String getEnvelopeRecipient(MimeMessage msg) throws MessagingException
       {
           try
           {
  @@ -697,7 +855,7 @@
           }
           catch (MessagingException me)
           {
  -            getLogger().warn("No Received headers found");
  +            logStatusWarn("No Received headers found.");
           }
           return null;
       }
  @@ -715,9 +873,10 @@
           if (isIgnoreRecipientHeader())
           {
               StringBuffer messageBuffer =
  -                new StringBuffer("Ignoring recipient header. Using configured recipient as new envelope recipient - ");
  -            messageBuffer.append(getRecipient().toString());
  -            getLogger().info(messageBuffer.toString());
  +                new StringBuffer("Ignoring recipient header. Using configured recipient as new envelope recipient: ");
  +            messageBuffer.append(getRecipient());
  +            messageBuffer.append('.');            
  +            logStatusInfo(messageBuffer.toString());
               return getRecipient();
           }
   
  @@ -728,9 +887,10 @@
           {
               MailAddress recipient = new MailAddress(targetRecipient);
               StringBuffer messageBuffer =
  -                new StringBuffer("Using original envelope recipient as new envelope recipient - ");
  -            messageBuffer.append(recipient.toString());
  -            getLogger().info(messageBuffer.toString());
  +                new StringBuffer("Using original envelope recipient as new envelope recipient: ");
  +            messageBuffer.append(recipient);
  +            messageBuffer.append('.');              
  +            logStatusInfo(messageBuffer.toString());
               return recipient;
           }
   
  @@ -744,9 +904,10 @@
               MailAddress recipient =
                   new MailAddress((InternetAddress) allRecipients[0]);
               StringBuffer messageBuffer =
  -                new StringBuffer("Using sole recipient header address as new envelope recipient - ");
  -            messageBuffer.append(recipient.toString());
  -            getLogger().info(messageBuffer.toString());
  +                new StringBuffer("Using sole recipient header address as new envelope recipient: ");
  +            messageBuffer.append(recipient);
  +            messageBuffer.append('.');              
  +            logStatusInfo(messageBuffer.toString());
               return recipient;
           }
   
  @@ -791,6 +952,55 @@
       }
       
       /**
  +     * Log the status of the current message as INFO.
  +     * @param detailMsg
  +     */
  +    protected void logStatusInfo(String detailMsg) throws MessagingException
  +    {
  +        getLogger().info(getStatusReport(detailMsg).toString());
  +    }
  +
  +    /**
  +     * Log the status the current message as WARN.
  +     * @param detailMsg
  +     */
  +    protected void logStatusWarn(String detailMsg) throws MessagingException
  +    {
  +        getLogger().warn(getStatusReport(detailMsg).toString());
  +    }
  +    
  +    /**
  +     * Log the status the current message as ERROR.
  +     * @param detailMsg
  +     */
  +    protected void logStatusError(String detailMsg) throws MessagingException
  +    {
  +        getLogger().error(getStatusReport(detailMsg).toString());
  +    }    
  +
  +    /**
  +     * Answer a <code>StringBuffer</code> containing a message reflecting
  +     * the current status of the message being processed.
  +     * 
  +     * @param detailMsg
  +     * @return StringBuffer
  +     */
  +    protected StringBuffer getStatusReport(String detailMsg) throws MessagingException
  +    {
  +        StringBuffer messageBuffer = new StringBuffer(detailMsg);
  +        if (detailMsg.length() > 0)
  +            messageBuffer.append(' ');
  +        messageBuffer.append("Message ID: ");
  +        messageBuffer.append(getMessageIn().getMessageID());
  +        messageBuffer.append(". Flags: Seen = ");
  +        messageBuffer.append(new Boolean(isMessageSeen()));
  +        messageBuffer.append(", Delete = ");
  +        messageBuffer.append(new Boolean(isMessageDeleted()));
  +        messageBuffer.append('.');
  +        return messageBuffer;
  +    }    
  +    
  +    /**
        * Returns the userUndefined.
        * @return boolean
        */
  @@ -800,13 +1010,31 @@
       }
       
       /**
  +     * Is the DELETED flag set?
  +     * @throws MessagingException
  +     */
  +    protected boolean isMessageDeleted() throws MessagingException
  +    {
  +       return getMessageIn().isSet(Flags.Flag.DELETED);
  +    }
  +    
  +    /**
  +     * Is the SEEN flag set?
  +     * @throws MessagingException
  +     */
  +    protected boolean isMessageSeen() throws MessagingException
  +    {
  +       return getMessageIn().isSet(Flags.Flag.SEEN);
  +    }    
  +    
  +    /**
        * Set the DELETED flag.
        * @throws MessagingException
        */
       protected void setMessageDeleted() throws MessagingException
       {
               getMessageIn().setFlag(Flags.Flag.DELETED, true);
  -    }
  +    }    
       
       /*    /**
        * Set the SEEN flag.
  @@ -837,13 +1065,8 @@
        */
       protected void handleMarkSeenNotPermanent() throws MessagingException
       {
  -        StringBuffer messageBuffer = new StringBuffer("Marking message ID: ");
  -        messageBuffer.append(getMessageIn().getMessageID());
  -        messageBuffer.append(
  -            " as SEEN, but the folder does not support a permanent SEEN flag.");
  -        getLogger().warn(messageBuffer.toString());
  -        
           getMessageIn().setFlag(Flags.Flag.SEEN, true);
  +        logStatusWarn("Message marked as SEEN, but the folder does not support a permanent SEEN flag.");
       }            
   
       /**
  @@ -931,6 +1154,191 @@
       protected void setRecipientNotFound(boolean recipientNotFound)
       {
           fieldRecipientNotFound = recipientNotFound;
  +    }
  +
  +    /**
  +     * Returns the remoteDomain, lazily initialised as required.
  +     * @return String
  +     */
  +    protected String getRemoteDomain() throws MessagingException
  +    {
  +        String remoteDomain;
  +        if (null == (remoteDomain = getRemoteDomainBasic()))
  +        {
  +            updateRemoteDomain();
  +            return getRemoteDomain();
  +        }    
  +        return remoteDomain;
  +    }
  +    
  +    /**
  +     * Returns the remoteDomain.
  +     * @return String
  +     */
  +    private String getRemoteDomainBasic()
  +    {
  +        return fieldRemoteDomain;
  +    }    
  +
  +    /**
  +     * Sets the remoteDomain.
  +     * @param remoteDomain The remoteDomain to set
  +     */
  +    protected void setRemoteDomain(String remoteDomain)
  +    {
  +        fieldRemoteDomain = remoteDomain;
  +    }
  +    
  +    /**
  +     * Updates the remoteDomain.
  +     */
  +    protected void updateRemoteDomain() throws MessagingException
  +    {
  +        setRemoteDomain(computeRemoteDomain());
  +    }
  +    
  +    /**
  +     * Answer the IP Address of the remote server for the message being 
  +     * processed.
  +     * @return String
  +     * @throws MessagingException
  +     * @throws UnknownHostException
  +     */
  +    protected String computeRemoteAddress()
  +        throws MessagingException, UnknownHostException
  +    {
  +        String domain = getRemoteDomain();
  +        String address = null;
  +        String validatedAddress = null;
  +        int ipAddressStart = domain.indexOf('[');
  +        int ipAddressEnd = -1;
  +        if (ipAddressStart > -1)
  +            ipAddressEnd = domain.indexOf(']', ipAddressStart);
  +        if (ipAddressEnd > -1)
  +            address = domain.substring(ipAddressStart + 1, ipAddressEnd);
  +        else
  +        {
  +            int hostNameEnd = domain.indexOf(' ');
  +            if (hostNameEnd == -1)
  +                hostNameEnd = domain.length();
  +            address = domain.substring(0, hostNameEnd);
  +        }
  +        validatedAddress = InetAddress.getByName(address).getHostAddress();
  +
  +        return validatedAddress;
  +    }
  +
  +    /**
  +     * Answer the Canonical host name of the remote server for the message 
  +     * being processed.
  +     * @return String
  +     * @throws MessagingException
  +     * @throws UnknownHostException
  +     */
  +    protected String computeRemoteHostName()
  +        throws MessagingException, UnknownHostException
  +    {
  +        // These shenanigans are required to get the fully qualified
  +        // hostname prior to JDK 1.4 in which get getCanonicalHostName()
  +        // does the job for us
  +        InetAddress addr1 = InetAddress.getByName(getRemoteAddress());
  +        InetAddress addr2 = addr1.getByName(addr1.getHostAddress());
  +        return addr2.getHostName();
  +    }        
  +
  +    /**
  +     * Returns the remoteAddress, lazily initialised as required.
  +     * @return String
  +     */
  +    protected String getRemoteAddress()
  +        throws MessagingException, UnknownHostException
  +    {
  +        String remoteAddress;
  +        if (null == (remoteAddress = getRemoteAddressBasic()))
  +        {
  +            updateRemoteAddress();
  +            return getRemoteAddress();
  +        }
  +        return remoteAddress;
  +    }
  +    
  +    /**
  +     * Returns the remoteAddress.
  +     * @return String
  +     */
  +    private String getRemoteAddressBasic()
  +    {
  +        return fieldRemoteAddress;
  +    }    
  +
  +    /**
  +     * Returns the remoteHostName, lazily initialised as required.
  +     * @return String
  +     */
  +    protected String getRemoteHostName()
  +        throws MessagingException, UnknownHostException
  +    {
  +        String remoteHostName;
  +        if (null == (remoteHostName = getRemoteHostNameBasic()))
  +        {
  +            updateRemoteHostName();
  +            return getRemoteHostName();
  +        }
  +        return remoteHostName;
  +    }
  +    
  +    /**
  +     * Returns the remoteHostName.
  +     * @return String
  +     */
  +    private String getRemoteHostNameBasic()
  +    {
  +        return fieldRemoteHostName;
  +    }    
  +
  +    /**
  +     * Sets the remoteAddress.
  +     * @param remoteAddress The remoteAddress to set
  +     */
  +    protected void setRemoteAddress(String remoteAddress)
  +    {
  +        fieldRemoteAddress = remoteAddress;
  +    }
  +    
  +    /**
  +     * Updates the remoteAddress.
  +     */
  +    protected void updateRemoteAddress()
  +        throws MessagingException, UnknownHostException
  +    {
  +        setRemoteAddress(computeRemoteAddress());
  +    }    
  +
  +    /**
  +     * Sets the remoteHostName.
  +     * @param remoteHostName The remoteHostName to set
  +     */
  +    protected void setRemoteHostName(String remoteHostName)
  +    {
  +        fieldRemoteHostName = remoteHostName;
  +    }
  +    
  +    /**
  +     * Updates the remoteHostName.
  +     */
  +    protected void updateRemoteHostName()
  +        throws MessagingException, UnknownHostException
  +    {
  +        setRemoteHostName(computeRemoteHostName());
  +    }    
  +
  +    /**
  +     * Returns the rFC2822RECEIVEDHeaderFields.
  +     * @return String
  +     */
  +    public static String getRFC2822RECEIVEDHeaderFields()
  +    {
  +        return fieldRFC2822RECEIVEDHeaderFields;
       }
   
   }
  
  
  
  1.1.2.4   +38 -10    james-server/src/java/org/apache/james/fetchmail/Attic/ParsedConfiguration.java
  
  Index: ParsedConfiguration.java
  ===================================================================
  RCS file: /home/cvs/james-server/src/java/org/apache/james/fetchmail/Attic/ParsedConfiguration.java,v
  retrieving revision 1.1.2.3
  retrieving revision 1.1.2.4
  diff -u -r1.1.2.3 -r1.1.2.4
  --- ParsedConfiguration.java	23 Sep 2003 19:04:35 -0000	1.1.2.3
  +++ ParsedConfiguration.java	20 Oct 2003 03:43:26 -0000	1.1.2.4
  @@ -256,6 +256,12 @@
       private boolean fieldRejectUserUndefined;
       
       /**
  +     * The index of the received header to use to compute the remote address
  +     * and remote host name for a message. This is 0 based and defaults to -1.
  +     */
  +    private int fieldRemoteReceivedHeaderIndex;    
  +    
  +    /**
        * Reject messages for which a recipient could not be determined.
        */
       private boolean fieldRejectRecipientNotFound;
  @@ -324,7 +330,7 @@
        * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
        */
       protected void configure(Configuration conf) throws ConfigurationException
  -    {   
  +    {
           setHost(conf.getChild("host").getValue());
   
           setFetchTaskName(conf.getAttribute("name"));
  @@ -335,11 +341,13 @@
   
           Configuration recipientNotFound = conf.getChild("recipientnotfound");
           setDeferRecipientNotFound(
  -            recipientNotFound.getAttributeAsBoolean("defer"));         
  +            recipientNotFound.getAttributeAsBoolean("defer"));
           setRejectRecipientNotFound(
  -            recipientNotFound.getAttributeAsBoolean("reject"));     
  -        setLeaveRecipientNotFound(recipientNotFound.getAttributeAsBoolean("leaveonserver"));
  -        setMarkRecipientNotFoundSeen(recipientNotFound.getAttributeAsBoolean("markseen"));          
  +            recipientNotFound.getAttributeAsBoolean("reject"));
  +        setLeaveRecipientNotFound(
  +            recipientNotFound.getAttributeAsBoolean("leaveonserver"));
  +        setMarkRecipientNotFoundSeen(
  +            recipientNotFound.getAttributeAsBoolean("markseen"));
   
           Configuration defaultDomainName = conf.getChild("defaultdomain", false);
           if (null != defaultDomainName)
  @@ -361,8 +369,7 @@
   
           Configuration blacklist = conf.getChild("blacklist");
           setBlacklist(blacklist.getValue(""));
  -        setRejectBlacklisted(
  -            blacklist.getAttributeAsBoolean("reject"));     
  +        setRejectBlacklisted(blacklist.getAttributeAsBoolean("reject"));
           setLeaveBlacklisted(blacklist.getAttributeAsBoolean("leaveonserver"));
           setMarkBlacklistedSeen(blacklist.getAttributeAsBoolean("markseen"));
   
  @@ -372,12 +379,15 @@
               userundefined.getAttributeAsBoolean("leaveonserver"));
           setMarkUserUndefinedSeen(
               userundefined.getAttributeAsBoolean("markseen"));
  -            
  -        Configuration undeliverable = conf.getChild("undeliverable");      
  +
  +        Configuration undeliverable = conf.getChild("undeliverable");
           setLeaveUndeliverable(
               undeliverable.getAttributeAsBoolean("leaveonserver"));
           setMarkUndeliverableSeen(
  -            undeliverable.getAttributeAsBoolean("markseen"));                       
  +            undeliverable.getAttributeAsBoolean("markseen"));
  +
  +        setRemoteReceivedHeaderIndex(
  +            conf.getChild("remoteReceivedHeaderIndex").getValueAsInteger(-1));
   
           if (getLogger().isDebugEnabled())
           {
  @@ -972,6 +982,24 @@
       protected void setDeferRecipientNotFound(boolean deferRecipientNotFound)
       {
           fieldDeferRecipientNotFound = deferRecipientNotFound;
  +    }
  +
  +    /**
  +     * Returns the remoteReceivedHeaderIndex.
  +     * @return int
  +     */
  +    public int getRemoteReceivedHeaderIndex()
  +    {
  +        return fieldRemoteReceivedHeaderIndex;
  +    }
  +
  +    /**
  +     * Sets the remoteReceivedHeaderIndex.
  +     * @param remoteReceivedHeaderIndex The remoteReceivedHeaderIndex to set
  +     */
  +    protected void setRemoteReceivedHeaderIndex(int remoteReceivedHeaderIndex)
  +    {
  +        fieldRemoteReceivedHeaderIndex = remoteReceivedHeaderIndex;
       }
   
   }
  
  
  
  1.1.2.3   +9 -0      james-server/src/java/org/apache/james/fetchmail/Attic/ProcessorAbstract.java
  
  Index: ProcessorAbstract.java
  ===================================================================
  RCS file: /home/cvs/james-server/src/java/org/apache/james/fetchmail/Attic/ProcessorAbstract.java,v
  retrieving revision 1.1.2.2
  retrieving revision 1.1.2.3
  diff -u -r1.1.2.2 -r1.1.2.3
  --- ProcessorAbstract.java	21 Sep 2003 20:03:35 -0000	1.1.2.2
  +++ ProcessorAbstract.java	20 Oct 2003 03:43:26 -0000	1.1.2.3
  @@ -203,6 +203,15 @@
       {
           return getAccount().getRecipient();
       }
  +    
  +    /**
  +     * Method getRemoteReceivedHeaderIndex.
  +     * @return int
  +     */
  +    protected int getRemoteReceivedHeaderIndex()
  +    {
  +        return getConfiguration().getRemoteReceivedHeaderIndex();    
  +    }
   
   
       /**
  
  
  
  1.1.2.4   +6 -2      james-server/src/java/org/apache/james/fetchmail/Attic/StoreProcessor.java
  
  Index: StoreProcessor.java
  ===================================================================
  RCS file: /home/cvs/james-server/src/java/org/apache/james/fetchmail/Attic/StoreProcessor.java,v
  retrieving revision 1.1.2.3
  retrieving revision 1.1.2.4
  diff -u -r1.1.2.3 -r1.1.2.4
  --- StoreProcessor.java	23 Sep 2003 19:04:35 -0000	1.1.2.3
  +++ StoreProcessor.java	20 Oct 2003 03:43:26 -0000	1.1.2.4
  @@ -143,7 +143,9 @@
           }
           catch (MessagingException ex)
           {
  -            getLogger().error(ex.getMessage());
  +            getLogger().error(
  +                "A MessagingException has terminated processing of this Folder",
  +                ex);
           }
           finally
           {
  @@ -154,7 +156,9 @@
               }
               catch (MessagingException ex)
               {
  -                getLogger().error(ex.getMessage());
  +                getLogger().error(
  +                    "A MessagingException occured while closing the Store",
  +                    ex);
               }
               logMessageBuffer =
                   new StringBuffer("Finished fetching mail from server '");
  
  
  
  No                   revision
  No                   revision
  1.1.2.3   +36 -0     james-server/src/xdocs/Attic/fetchmail_configuration_2_2.xml
  
  Index: fetchmail_configuration_2_2.xml
  ===================================================================
  RCS file: /home/cvs/james-server/src/xdocs/Attic/fetchmail_configuration_2_2.xml,v
  retrieving revision 1.1.2.2
  retrieving revision 1.1.2.3
  diff -u -r1.1.2.2 -r1.1.2.3
  --- fetchmail_configuration_2_2.xml	23 Sep 2003 19:04:35 -0000	1.1.2.2
  +++ fetchmail_configuration_2_2.xml	20 Oct 2003 03:43:27 -0000	1.1.2.3
  @@ -130,6 +130,7 @@
   <li><strong><a href="#javaMailProviderName">javaMailProviderName</a></strong> (1, 1)</li>
   <li><strong><a href="#recipientnotfound">recipientnotfound</a></strong> (1, 1)</li>
   <li><strong><a href="#recursesubfolders">recursesubfolders</a></strong> (1, 1)</li>
  +<li><strong><a href="#remoteReceivedHeaderIndex">remoteReceivedHeaderIndex</a></strong> (0, 1)</li>
   <li><strong><a href="#remoterecipient">remoterecipient</a></strong> (1, 1)</li>
   <li><strong><a href="#undeliverable">undeliverable</a></strong> (1, 1)</li>
   <li><strong><a href="#userundefined">userundefined</a></strong> (1, 1)</li>
  @@ -419,6 +420,41 @@
   <p>
   <source>
   &lt;recursesubfolders&gt;false&lt;/recursesubfolders&gt;
  +</source>
  +</p>
  +</subsection>
  +
  +<subsection name="remoteReceivedHeaderIndex">
  +<p>The <strong>remoteReceivedHeaderIndex</strong> tag declares the zero based
  +index of the RFC2822 compliant RECEIVED header used to determine the address and
  +host name of the remote MTA that sent a fetched message.</p>
  +
  +<p>Typically, the first (index = 0) RECEIVED header is for the local MTA that 
  +delivered the message to the message store and the second (index = 1) RECEIVED
  +header is for the remote MTA that delivered the message to the local MTA. When
  +this configuration applies, the <strong>remoteReceivedHeaderIndex</strong> should
  +be set to <strong>1</strong>.
  +</p>
  +
  +<p>To verify the correct setting, examine the RECEIVED headers for messages
  +delivered to the configured message store and locate the first one containing a
  +remote domain in the'from' field. Remembering that zero based indexing is used,
  +if this the second header, use an index of 1, if this is the third header, use an
  +index of 2, and so forth.</p>
  +
  +<p>Matchers such as InSpammerBlacklist use the remote address and/or remote host
  +name to identify illegitimate remote MTAs. If you do not use such matchers, the
  +<strong>remoteReceivedHeaderIndex</strong> tag may be omitted or the default
  +value of -1 can be specified. This causes the remote address to be set to
  +<code>127.0.0.1</code> and the remote host name to be set to
  +<code>localhost</code>. Matchers almost always considered these values to be
  +legitimate.</p>
  +
  +<p>The tag value is an integer whose meaning is described above.</p>
  +
  +<p>
  +<source>
  +&lt;remoteReceivedHeaderIndex&gt;1&lt;/remoteReceivedHeaderIndex&gt;
   </source>
   </p>
   </subsection>
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org