noel        2003/02/04 20:31:40

  Added:       src/java/org/apache/james/fetchmail FetchMail.java
                        FetchScheduler.java FetchScheduler.xinfo
                        ReaderInputStream.java
  Log:
  Added FetchMail service
  
  Revision  Changes    Path
  1.1                  jakarta-james/src/java/org/apache/james/fetchmail/FetchMail.java
  
  Index: FetchMail.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.fetchmail;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.net.SocketException;
  import java.util.Enumeration;
  import java.util.Vector;
  import java.util.*;
  import java.io.*;
  import javax.mail.*;
  import javax.mail.event.*;
  import javax.mail.internet.*;
  import javax.activation.*;
  
  import org.apache.avalon.cornerstone.services.scheduler.Target;
  import org.apache.avalon.framework.component.ComponentException;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.component.Composable;
  import org.apache.avalon.framework.component.DefaultComponentManager;
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.commons.net.pop3.POP3Client;
  import org.apache.commons.net.pop3.POP3MessageInfo;
  import org.apache.james.services.MailServer;
  import org.apache.mailet.*;
  import org.apache.james.core.MailImpl;
  
  /**
   *
   * A class which fetches mail from a single account and inserts it
   * into the incoming spool
   *
   * $Id: FetchMail.java,v 1.1 2003/02/05 04:31:40 noel Exp $
   *
   */
  public class FetchMail extends AbstractLogEnabled implements Configurable, Target {
      /**
       * The MailServer service
       */
      private MailServer server;
      /**
       * The user to send the fetched mail to
       */
      private MailAddress recipient;
  
      /**
       * Don't parse header looking for recipient
       */
      private boolean ignoreOriginalRecipient;
      /**
       * The unique, identifying name for this task
       */
      private String fetchTaskName;
      /**
       * The POP3 server host name for this fetch task
       */
      private String popHost;
      /**
       * The POP3 user name for this fetch task
       */
      private String popUser;
      /**
       * The POP3 user password for this fetch task
       */
      private String popPass;
  
      /**
       * Flag to determine if you want to leave messages on server
       * If so unseen messages will be marked as seen
       */
      private boolean popLeaveOnServer = false;
  
  
      /**
       * The name of the javamail provider we want to user (pop3,imap,nntp,etc...)
       *
       */
      private String javaMailProviderName = "pop3";
  
      /**
       * The name of the folder to fetch from the javamail provider
       *
       */
      private String javaMailFolderName = "INBOX";
  
  
      /**
       * @see 
org.apache.avalon.cornerstone.services.scheduler.Target#targetTriggered(String)
       */
      private boolean fetching = false;
  
  
      public void targetTriggered(String arg0) {
  
          //
          // if we are already fetching then just return
          if (fetching) return;
          fetching = true;
  
  
          if (getLogger().isDebugEnabled()) {
              getLogger().debug(fetchTaskName + " fetcher starting fetch");
          }
  
          Store store = null;
          Session session = null;
          Folder folder = null;
  
  
          // Get a Properties object
          Properties props = System.getProperties();
  
          // Get a Session object
          session = Session.getDefaultInstance(props, null);
          //  session.setDebug(debug);
  
          // Get a Store object
          try {
              store = session.getStore(javaMailProviderName);
  
              // Connect
              if (popHost != null || popUser != null || popPass != null)
                  store.connect(popHost, popUser, popPass);
              else
                  store.connect();
  
              // Open the Folder
              folder = store.getFolder(javaMailFolderName);
              if (folder == null) {
                  getLogger().debug(fetchTaskName + " No default folder");
              }
  
  
              //    // try to open read/write and if that fails try read-only
              try {
                  folder.open(Folder.READ_WRITE);
              } catch (MessagingException ex) {
                  try {
                      folder.open(Folder.READ_ONLY);
                  } catch (MessagingException ex2) {
                      getLogger().debug(fetchTaskName + " Failed to open folder!");
                      store.close();
                  }
              }
  
              int totalMessages = folder.getMessageCount();
              if (totalMessages == 0) {
                  getLogger().debug(fetchTaskName + " Empty folder");
                  folder.close(false);
                  store.close();
                  fetching = false;
                  return;
              }
  
              Message[] msgs = folder.getMessages();
              Message[] received = new Message[folder.getUnreadMessageCount()];
  
              // Use a suitable FetchProfile
              FetchProfile fp = new FetchProfile();
              fp.add(FetchProfile.Item.ENVELOPE);
              fp.add(FetchProfile.Item.CONTENT_INFO);
              fp.add(FetchProfile.Item.FLAGS);
              fp.add("X-Mailer");
  
              folder.fetch(msgs, fp);
  
              int j = 0;
              for (int i = 0; i < msgs.length; i++) {
                  Flags flags = msgs[i].getFlags();
                  MimeMessage message = (MimeMessage) msgs[i];
  
                  if (!msgs[i].isSet(Flags.Flag.SEEN)) {
  
                      //
                      // saved recieved messages for furthe processing...
                      received[j++] = msgs[i];
                      Collection recipients = new ArrayList(1);
  
                      try {
                          if (!ignoreOriginalRecipient) {
                              String er = getEnvelopeRecipient(message);
                              if (er != null) {
                                  recipients.add(new MailAddress(er));
                                  getLogger().info("Using original envelope recipient 
as new envelope recipient");
                              } else {
                                  Address[] to = message.getAllRecipients();
                                  if (to.length == 1) {
                                      recipients.add(new
                                              MailAddress((InternetAddress) to[0]));
                                      getLogger().info("Using To: header address as 
new envelope recipient");
                                  } else {
                                      getLogger().info("Using configured recipient as 
new envelope recipient");
                                      recipients.add(recipient);
                                  }
                              }
                          } else {
                              getLogger().info("Using configured recipient as new 
envelope recipient");
                              recipients.add(recipient);
                          }
                      } catch (ParseException pe) {
                          recipients.add(recipient);
                      }
  
                      MailImpl mail = new MailImpl(server.getId(), new
                              MailAddress((InternetAddress) message.getFrom()[0]), 
recipients, message);
  
                      // Lets see if this mail has been bouncing by counting
                      // the   X-fetched-from headers
                      // if it is then move it to the ERROR repository
                      Enumeration enum = message.getMatchingHeaderLines(new
                              String[]{"X-fetched-from"});
                      int count = 1;
                      while (enum.hasMoreElements()) {
                          Object o = enum.nextElement();
                          count++;
                      }
                      if (count > 3) {
                          mail.setState(mail.ERROR);
                          mail.setErrorMessage("This mail from FetchMail task " + 
fetchTaskName + " seems to be bounceing!");
                          getLogger().error("A message from FetchMail task " + 
fetchTaskName + " seems to be bounceing! Moved to Error repository");
                      }
  
                      // Send to spooler
                      try {
                          server.sendMail(mail);
                          getLogger().debug("Spooled message to " +
                                  recipients.toString());
  
                          //
                          // logging if needed
                          getLogger().debug("Sent message " + msgs[i].toString());
  
                      } catch (MessagingException innerE) {
                          getLogger().error("can't insert message " + 
msgs[i].toString());
                      } /*catch (IOException ioE) {
                      getLogger().error("can't convert message to a mime message " + 
ioE.getMessage());
                      }*/
                  }
              }
              if (popLeaveOnServer) {
                  Flags f = new Flags();
                  f.add(Flags.Flag.SEEN);
                  folder.setFlags(received, f, true);
                  folder.close(false);
              } else {
                  Flags f = new Flags();
                  f.add(Flags.Flag.DELETED);
  
                  folder.setFlags(received, f, true);
                  folder.close(true);
              }
  
              store.close();
          } catch (MessagingException ex) {
              getLogger().debug(fetchTaskName + ex.getMessage());
          }
          fetching = false;
      }
  
      /**
       * @see 
org.apache.avalon.framework.component.Composable#compose(ComponentManager)
       */
      public void compose(final ComponentManager componentManager) throws 
ComponentException {
          try {
              server = (MailServer) componentManager.lookup(MailServer.ROLE);
          } catch (ClassCastException cce) {
              StringBuffer errorBuffer =
                      new StringBuffer(128).append("Component 
").append(MailServer.ROLE).append(
                              "does not implement the required interface.");
              throw new ComponentException(errorBuffer.toString());
          }
      }
  
  
      /**
       * Try and parse the "for" parameter from a Received header
       * Maybe not the most accurate parsing in the world but it should do
       * I opted not to use ORO (maybe I should have)
       */
      private String getEnvelopeRecipient(MimeMessage msg) {
          try {
              Enumeration enum = msg.getMatchingHeaderLines(new String[]{"Received"});
              while (enum.hasMoreElements()) {
                  String received = (String) enum.nextElement();
  
                  int nextSearchAt = 0;
                  int i = 0;
                  int start = 0;
                  int end = 0;
                  boolean hasBracket = false;
                  boolean usableAddress = false;
                  while (!usableAddress && (i != -1)) {
                      hasBracket = false;
                      i = received.indexOf("for ", nextSearchAt);
                      if (i > 0) {
                          start = i + 4;
                          end = 0;
                          nextSearchAt = start;
                          for (int c = start; c < received.length(); c++) {
                              char ch = received.charAt(c);
                              switch (ch) {
                                  case '<':
                                      hasBracket = true;
                                      continue;
                                  case '@':
                                      usableAddress = true;
                                      continue;
                                  case ' ':
                                      end = c;
                                      break;
                                  case ';':
                                      end = c;
                                      break;
                              }
                              if (end > 0)
                                  break;
                          }
                      }
                  }
                  if (usableAddress) {
                      // lets try and grab the email address
                      String mailFor = received.substring(start, end);
  
                      // strip the <> around the address if there are any
                      if (mailFor.startsWith("<") && mailFor.endsWith(">"))
                          mailFor = mailFor.substring(1, (mailFor.length() - 1));
  
                      return mailFor;
                  }
              }
          } catch (MessagingException me) {
              getLogger().info("No Recieved headers found");
          }
          return null;
      }
  
      /**
       * @see 
org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
       */
      public void configure(Configuration conf) throws ConfigurationException {
          this.popHost = conf.getChild("host").getValue();
          this.popUser = conf.getChild("user").getValue();
          this.popPass = conf.getChild("password").getValue();
          this.fetchTaskName = conf.getAttribute("name");
          this.javaMailProviderName = 
conf.getChild("javaMailProviderName").getValue();
          this.javaMailFolderName = conf.getChild("javaMailFolderName").getValue();
          try {
              this.recipient = new MailAddress(conf.getChild("recipient").getValue());
          } catch (ParseException pe) {
              throw new ConfigurationException("Invalid recipient address specified");
          }
          this.ignoreOriginalRecipient = 
conf.getChild("recipient").getAttributeAsBoolean("ignorercpt-header");
          this.popLeaveOnServer = conf.getChild("leaveonserver").getValueAsBoolean();
          if (getLogger().isDebugEnabled()) {
              getLogger().info("Configured FetchMail fetch task " + fetchTaskName);
          }
      }
  }
  
  
  
  1.1                  
jakarta-james/src/java/org/apache/james/fetchmail/FetchScheduler.java
  
  Index: FetchScheduler.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.fetchmail;
  
  import org.apache.avalon.cornerstone.services.scheduler.PeriodicTimeTrigger;
  import org.apache.avalon.cornerstone.services.scheduler.TimeScheduler;
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.component.Component;
  import org.apache.avalon.framework.component.ComponentException;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.component.Composable;
  import org.apache.avalon.framework.component.DefaultComponentManager;
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.james.services.MailServer;
  
  import java.util.ArrayList;
  import java.util.Iterator;
  
  /**
   *  A class to instantiate and schedule a set of mail fetching tasks
   *
   * $Id: FetchScheduler.java,v 1.1 2003/02/05 04:31:40 noel Exp $
   *
   *  @see org.apache.james.fetchmail.FetchMail#configure(Configuration) FetchMail
   *  
   */
  public class FetchScheduler
      extends AbstractLogEnabled
      implements Component, Composable, Configurable, Initializable, Disposable {
  
      /**
       * Configuration object for this service
       */
      private Configuration conf;
  
      /**
       * The component manager that allows access to the system services
       */
      private ComponentManager compMgr;
  
      /**
       * The scheduler service that is used to trigger fetch tasks.
       */
      private TimeScheduler scheduler;
  
      /**
       * Whether this service is enabled.
       */
      private volatile boolean enabled = false;
  
      private ArrayList theFetchTaskNames = new ArrayList();
  
      /**
       * @see 
org.apache.avalon.framework.component.Composable#compose(ComponentManager)
       */
      public void compose(ComponentManager comp) throws ComponentException {
          compMgr = comp;
      }
  
      /**
       * @see 
org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
       */
      public void configure(Configuration conf) throws ConfigurationException {
          this.conf = conf;
      }
  
      /**
       * @see org.apache.avalon.framework.activity.Initializable#initialize()
       */
      public void initialize() throws Exception {
          enabled = conf.getAttributeAsBoolean("enabled", false);
          if (enabled) {
              scheduler = (TimeScheduler) compMgr.lookup(TimeScheduler.ROLE);
              Configuration[] fetchConfs = conf.getChildren("fetch");
              for (int i = 0; i < fetchConfs.length; i++) {
                  FetchMail fetcher = new FetchMail();
                  Configuration fetchConf = fetchConfs[i];
                  String fetchTaskName = fetchConf.getAttribute("name");
                  fetcher.enableLogging(getLogger().getChildLogger(fetchTaskName));
                  fetcher.compose(compMgr);
                  fetcher.configure(fetchConf);
                  Integer interval = new 
Integer(fetchConf.getChild("interval").getValue());
                  PeriodicTimeTrigger fetchTrigger = new PeriodicTimeTrigger(0, 
interval.intValue());
                  scheduler.addTrigger(fetchTaskName, fetchTrigger, fp);
                  theFetchTaskNames.add(fetchTaskName);
              }
              getLogger().info("FetchMail Started");
          } else {
              getLogger().info("FetchMail Disabled");
          }
      }
  
      /**
       * @see org.apache.avalon.framework.activity.Disposable#dispose()
       */
      public void dispose() {
          if (enabled) {
              getLogger().info( "FetchMail dispose..." );
              Iterator nameIterator = theFetchTaskNames.iterator();
              while (nameIterator.hasNext()) {
                  scheduler.removeTrigger((String)nameIterator.next());
              }
              getLogger().info( "FetchMail ...dispose end" );
          }
     }
  }
  
  
  
  1.1                  
jakarta-james/src/java/org/apache/james/fetchmail/FetchScheduler.xinfo
  
  Index: FetchScheduler.xinfo
  ===================================================================
  <?xml version="1.0"?>
  
  <blockinfo>
  
    <!-- section to describe block -->
    <block>
      <version>1.0</version>
    </block>
  
    <!-- services that are offered by this block -->
    <services>
      <service name="org.apache.avalon.framework.component.Component" version="1.0"/>
    </services>
  
    <dependencies>
      <dependency>
        <service name="org.apache.james.services.MailServer" version="1.0"/>
      </dependency>
      <dependency> 
        <service name="org.apache.avalon.cornerstone.services.scheduler.TimeScheduler" 
version="1.0"/>
      </dependency> 
    </dependencies>  
  </blockinfo>
  
  
  
  1.1                  
jakarta-james/src/java/org/apache/james/fetchmail/ReaderInputStream.java
  
  Index: ReaderInputStream.java
  ===================================================================
  /**
   * ReaderInputStream.java
   * 
   * Copyright (C) 24-Sep-2002 The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file. 
   *
   */
  package org.apache.james.fetchmail;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.Reader;
  /**
   * 
   * Simple class to allow a cast from a java.io.Reader to a java.io.InputStream
   * 
   * $Id: ReaderInputStream.java,v 1.1 2003/02/05 04:31:40 noel Exp $
   * 
   */
  public class ReaderInputStream extends InputStream {
      private Reader reader = null;
      public ReaderInputStream(Reader reader) {
          this.reader = reader;
      }
      /**
       * @see java.io.InputStream#read()
       */
      public int read() throws IOException {
          return reader.read();
      }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to