noel 2003/02/20 17:35:45
Modified: src/conf james-config.xml
src/java/org/apache/james/fetchmail FetchMail.java
FetchScheduler.java
Log:
Merged changes from Leo: (1) Added the ability to recurse into subfolders, (2)
Performance/efficiency improvements, (3) leaveonserver now works properly, (4) added
support for fetchall which fetch's all messages read or not (similar to Linux
fetchmail), (5) Added back the X-header X-fetch-from, (6) Bug fixes.
Revision Changes Path
1.47 +9 -1 jakarta-james/src/conf/james-config.xml
Index: james-config.xml
===================================================================
RCS file: /home/cvs/jakarta-james/src/conf/james-config.xml,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -r1.46 -r1.47
--- james-config.xml 15 Feb 2003 04:29:24 -0000 1.46
+++ james-config.xml 21 Feb 2003 01:35:45 -0000 1.47
@@ -130,6 +130,14 @@
<!-- If "true" will leave the messages on the server -->
<!-- and mark them as SEEN if "false" will delete the messages -->
<leaveonserver>false</leaveonserver>
+
+ <!-- Retrieve both old (seen) and new messages from mailserver. The
default -->
+ <!-- is to fetch only messages the server has not marked as seen -->
+ <fetchall>false</fetchall>
+
+ <!-- If the folder javaMailFolderName contains subfolders do you -->
+ <!-- want to recurse into the subfolders as well? true = yes, false =
no -->
+ <recursesubfolders>false</recursesubfolders>
</fetch>
</fetchmail>
1.4 +206 -150 jakarta-james/src/java/org/apache/james/fetchmail/FetchMail.java
Index: FetchMail.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/fetchmail/FetchMail.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- FetchMail.java 8 Feb 2003 04:12:25 -0000 1.3
+++ FetchMail.java 21 Feb 2003 01:35:45 -0000 1.4
@@ -7,19 +7,8 @@
*/
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.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
@@ -28,11 +17,19 @@
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;
+import org.apache.james.services.MailServer;
+import org.apache.mailet.MailAddress;
+
+import javax.mail.*;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.ParseException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Properties;
/**
*
@@ -56,29 +53,42 @@
* Don't parse header looking for recipient
*/
private boolean ignoreOriginalRecipient;
+
/**
* The unique, identifying name for this task
*/
private String fetchTaskName;
+
+ /**
+ * The server host name for this fetch task
+ */
+ private String sHost;
/**
- * The POP3 server host name for this fetch task
+ * The user name for this fetch task
*/
- private String popHost;
+ private String sUser;
+
/**
- * The POP3 user name for this fetch task
+ * The user password for this fetch task
*/
- private String popUser;
+ private String sPass;
+
/**
- * The POP3 user password for this fetch task
+ * Keep retrieved messages on the remote mailserver. Normally, messages
+ * are deleted from the folder on the mailserver after they have been retrieved
*/
- private String popPass;
+ private boolean bKeep = false;
/**
- * Flag to determine if you want to leave messages on server
- * If so unseen messages will be marked as seen
+ * Retrieve both old (seen) and new messages from the mailserver. The default
+ * is to fetch only messages the server has not marked as seen.
*/
- private boolean popLeaveOnServer = false;
+ private boolean bAll = false;
+ /**
+ * Recurse folders if available?
+ */
+ private boolean bRecurse = false;
/**
* The name of the javamail provider we want to user (pop3,imap,nntp,etc...)
@@ -99,47 +109,83 @@
private boolean fetching = false;
- public void targetTriggered(String arg0) {
+ public boolean processMessage(Session session, MimeMessage message, MimeMessage
received) {
- //
- // if we are already fetching then just return
- if (fetching) return;
- fetching = true;
+ Collection recipients = new ArrayList(1);
+ try {
- if (getLogger().isDebugEnabled()) {
- getLogger().debug(fetchTaskName + " fetcher starting fetch");
- }
-
- Store store = null;
- Session session = null;
- Folder folder = null;
+ 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);
+ }
- // 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);
+ //
+ // set the X-fetched-from header
+ received.addHeader("X-fetched-from", fetchTaskName);
+
+ MailImpl mail = new MailImpl(server.getId(), new
+ MailAddress((InternetAddress) received.getFrom()[0]),
recipients, received);
- // 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");
+ // 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");
+ return false;
}
+ server.sendMail(mail);
+ getLogger().debug("Spooled message to " +
+ recipients.toString());
+
+ //
+ // logging if needed
+ getLogger().debug("Sent message " + message.toString());
+ return true;
+ } catch (ParseException pe) {
+ recipients.add(recipient);
+ } catch (MessagingException innerE) {
+ getLogger().error("can't insert message " + message.toString());
+ }
+ return false;
+ }
+ public boolean processFolder(Session session, Folder folder) {
+
+ boolean ret = false;
+
+ try {
+
+ //
// try to open read/write and if that fails try read-only
try {
folder.open(Folder.READ_WRITE);
@@ -148,117 +194,125 @@
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;
- }
+// int totalMessages = folder.getMessageCount();
+// if (totalMessages == 0) {
+// getLogger().debug(fetchTaskName + " Empty folder");
+// folder.close(false);
+// fetching = false;
+// return false;
+// }
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);
+ MimeMessage[] received = new MimeMessage[folder.getMessageCount()];
int j = 0;
- for (int i = 0; i < msgs.length; i++) {
+ for (int i = 0; i < msgs.length; i++, j++) {
Flags flags = msgs[i].getFlags();
MimeMessage message = (MimeMessage) msgs[i];
- if (!msgs[i].isSet(Flags.Flag.SEEN)) {
+ //
+ // saved recieved messages for further processing...
+ received[j] = new MimeMessage(/*session,*/ message);
+
+ received[j].addHeader("X-fetched-folder", folder.getFullName());
+
+ if (bAll) {
+ ret = processMessage(session, message, received[j]);
+ } else if (message.isSet(Flags.Flag.SEEN)) {
+ ret = processMessage(session, message, received[j]);
+ }
- //
- // 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);
+ if (ret) {
+ //
+ // need to get the flags again just in case processMessage
+ // has changed the flags....
+ Flags f = received[j].getFlags();
+
+ if (!bKeep) {
+
+ message.setFlag(Flags.Flag.DELETED, true);
+ } else {
+ f.add(Flags.Flag.SEEN);
- // 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");
+ received[j].setFlags(f, true);
+ }
+ }
+ }
+ folder.close(true);
+
+ //
+ // see if this folder contains subfolders and recurse is true
+ if (bRecurse) {
+ if ((folder.getType() & folder.HOLDS_FOLDERS) != 0) {
+ //
+ // folder contains subfolders...
+ Folder folders[] = folder.list();
+
+ for (int k = 0; k < folders.length; k++) {
+ processFolder(session, folders[k]);
}
- // 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);
+ return true;
+ } catch (MessagingException mex) {
+ getLogger().debug(mex.toString());
+
+ } /*catch (IOException ioex) {
+ getLogger().debug(ioex.toString());
+ } */
+ fetching = false;
+ return false;
+ }
+
+
+ public void targetTriggered(String arg0) {
+ Store store = null;
+ Session session = null;
+ Folder folder = null;
+
+ // Get a Properties object
+ Properties props = System.getProperties();
+
- folder.setFlags(received, f, true);
- folder.close(true);
+ //
+ // if we are already fetching then just return
+ if (fetching) return;
+ fetching = true;
+
+
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(fetchTaskName + " fetcher starting fetch");
+ }
+
+
+ // Get a Session object
+ session = Session.getDefaultInstance(props, null);
+ // session.setDebug(debug);
+
+ // Get a Store object
+ try {
+ store = session.getStore(javaMailProviderName);
+
+ // Connect
+ if (sHost != null || sUser != null || sPass != null)
+ store.connect(sHost, sUser, sPass);
+ else
+ store.connect();
+
+ // Open the Folder
+ folder = store.getFolder(javaMailFolderName);
+ if (folder == null) {
+ getLogger().debug(fetchTaskName + " No default folder");
}
+
+ processFolder(session, folder);
+
store.close();
} catch (MessagingException ex) {
getLogger().debug(fetchTaskName + ex.getMessage());
@@ -347,9 +401,9 @@
* @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.sHost = conf.getChild("host").getValue();
+ this.sUser = conf.getChild("user").getValue();
+ this.sPass = conf.getChild("password").getValue();
this.fetchTaskName = conf.getAttribute("name");
this.javaMailProviderName =
conf.getChild("javaMailProviderName").getValue();
this.javaMailFolderName = conf.getChild("javaMailFolderName").getValue();
@@ -359,7 +413,9 @@
throw new ConfigurationException("Invalid recipient address specified");
}
this.ignoreOriginalRecipient =
conf.getChild("recipient").getAttributeAsBoolean("ignorercpt-header");
- this.popLeaveOnServer = conf.getChild("leaveonserver").getValueAsBoolean();
+ this.bAll = conf.getChild("fetchall").getValueAsBoolean();
+ this.bKeep = conf.getChild("leaveonserver").getValueAsBoolean();
+ this.bRecurse = conf.getChild("recursesubfolders").getValueAsBoolean();
if (getLogger().isDebugEnabled()) {
getLogger().info("Configured FetchMail fetch task " + fetchTaskName);
}
1.5 +2 -1
jakarta-james/src/java/org/apache/james/fetchmail/FetchScheduler.java
Index: FetchScheduler.java
===================================================================
RCS file:
/home/cvs/jakarta-james/src/java/org/apache/james/fetchmail/FetchScheduler.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- FetchScheduler.java 8 Feb 2003 04:12:25 -0000 1.4
+++ FetchScheduler.java 21 Feb 2003 01:35:45 -0000 1.5
@@ -89,6 +89,7 @@
fetcher.configure(fetchConf);
Integer interval = new
Integer(fetchConf.getChild("interval").getValue());
PeriodicTimeTrigger fetchTrigger = new PeriodicTimeTrigger(0,
interval.intValue());
+
scheduler.addTrigger(fetchTaskName, fetchTrigger, fetcher );
theFetchTaskNames.add(fetchTaskName);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]