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 er...@apache.org on 2011/04/27 13:45:34 UTC

svn commit: r1097086 - in /james/mailet/standard/trunk: ./ src/main/java/org/apache/james/transport/mailets/

Author: eric
Date: Wed Apr 27 11:45:34 2011
New Revision: 1097086

URL: http://svn.apache.org/viewvc?rev=1097086&view=rev
Log:
Add submit emails to URLs contributed by Renen Watermeyer in standard mailets module (MAILET-39)

Added:
    james/mailet/standard/trunk/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java
    james/mailet/standard/trunk/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java
    james/mailet/standard/trunk/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java
Modified:
    james/mailet/standard/trunk/pom.xml

Modified: james/mailet/standard/trunk/pom.xml
URL: http://svn.apache.org/viewvc/james/mailet/standard/trunk/pom.xml?rev=1097086&r1=1097085&r2=1097086&view=diff
==============================================================================
--- james/mailet/standard/trunk/pom.xml (original)
+++ james/mailet/standard/trunk/pom.xml Wed Apr 27 11:45:34 2011
@@ -75,6 +75,11 @@
       <version>1.4.3</version>
     </dependency>
     <dependency>
+      <groupId>commons-httpclient</groupId>
+      <artifactId>commons-httpclient</artifactId>
+      <version>3.0.1</version>
+    </dependency>
+    <dependency>
       <groupId>org.apache.james</groupId>
       <artifactId>apache-mailet-base</artifactId>
       <version>1.2-SNAPSHOT</version>

Added: james/mailet/standard/trunk/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java
URL: http://svn.apache.org/viewvc/james/mailet/standard/trunk/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java?rev=1097086&view=auto
==============================================================================
--- james/mailet/standard/trunk/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java (added)
+++ james/mailet/standard/trunk/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java Wed Apr 27 11:45:34 2011
@@ -0,0 +1,315 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.transport.mailets;
+
+import java.io.IOException;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.mail.BodyPart;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Multipart;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.GenericMailet;
+
+
+/**
+ * Assesses the message to determine if it was a hard or soft bounce, and if it was a soft bounce, something of its nature..
+ *
+ * Sample configuration:
+ *
+ * <mailet match="All" class="ClassifyBounce">
+ *   <headerName>X-MailetHeader</headerName>
+ * </mailet>
+ *
+ */
+public class ClassifyBounce extends GenericMailet {
+
+    /**
+     * The name of the header to be added.
+     */
+    private String headerName;
+
+    /**
+     * Initialize the mailet.
+     */
+    public void init() throws MessagingException {
+        headerName = getInitParameter("headerName");
+        
+        // Check if needed config values are used
+        if (headerName == null || headerName.equals("")) {
+            throw new MessagingException("Please configure a header name to contain the classification (if any).");
+        }
+    }
+
+    /**
+     * Takes the message and adds a header to it.
+     *
+     * @param mail the mail being processed
+     *
+     * @throws MessagingException if an error arises during message processing
+     */
+    public void service(Mail mail) {
+        try {
+            MimeMessage message = mail.getMessage () ;
+            Classifier classifier = this.new Classifier(message);
+            String classification = classifier.getClassification();
+            //if ( !classification.equals("Normal") ) {
+	            message.setHeader(headerName, classification);
+	            message.saveChanges();
+            //}
+        } catch (javax.mail.MessagingException me) {
+            log ("Error classifying message: " + me.getMessage());
+        }
+    }
+
+    /**
+     * Return a string describing this mailet.
+     *
+     * @return a string describing this mailet
+     */
+    public String getMailetInfo() {
+        return "SetMimeHeader Mailet" ;
+    }
+
+    private class Classifier {
+
+        public Classifier(Message message) throws MessagingException {
+            subject = message.getSubject();
+            try {
+                text = getRawText(message.getContent());
+            } catch (IOException e) {
+                throw(new MessagingException("Unable to extract message body. [" + e.getClass().getName() + "] " + e.getMessage()));
+            }
+        }
+
+        public String getClassification() throws MessagingException {
+            String classification = "Normal";
+            switch(assess()) {
+            case TYPE_DELIVERY_FAILURE: classification = "Delivery failure"; break;
+            case TYPE_MAILBOX_FULL: classification = "Mailbox full"; break;
+            case TYPE_OUT_OF_OFFICE: classification = "Out of the office"; break;
+            }
+            return classification;
+        }
+        
+        private int assess() throws MessagingException {
+            
+            int messageNature = TYPE_NORMAL;
+            
+            boolean outOfOffice = false;
+            boolean mailBoxFull = false;
+            boolean failure = false;
+            
+            outOfOffice = assessMessageSubjectOutOfOffice();
+            if (!outOfOffice) { mailBoxFull = assessMessageSubjectMailboxFull(); }
+            if ((!outOfOffice) && (!mailBoxFull)) { failure = assessMessageSubjectFailure(); }
+            if (!(outOfOffice || mailBoxFull || failure)) {
+                if (assessMessageUnreadable()) {
+                    //get quite a few of these
+                    failure = true;
+                } else {
+                    outOfOffice = assessMessageOutOfOffice();
+                    if (!mailBoxFull) { mailBoxFull = assessMessageMailboxFull(); }
+                    if ((!outOfOffice) && (!mailBoxFull)) { failure = assessMessageFailure(); }
+                }
+            }
+
+            if (failure) { messageNature = TYPE_DELIVERY_FAILURE; }
+            if (mailBoxFull) { messageNature = TYPE_MAILBOX_FULL; }
+            if (outOfOffice) { messageNature = TYPE_OUT_OF_OFFICE; }
+            
+            return messageNature;
+        }
+        
+        private String getRawText(Object o) throws MessagingException, IOException {
+            
+            String s = null;
+            
+            if (o instanceof Multipart){
+                Multipart multi = (Multipart)o;
+                for(int i=0; i < multi.getCount(); i++) {
+                    s = getRawText(multi.getBodyPart(i));
+                    if (s!=null) {
+                        if (s.length()>0) {
+                            break;
+                        }
+                    }
+                }   
+            } else if (o instanceof BodyPart) {
+                BodyPart aBodyContent = (BodyPart)o;    
+                StringTokenizer aTypeTokenizer = new StringTokenizer(aBodyContent.getContentType(), "/");
+                String abstractType = aTypeTokenizer.nextToken();                   
+                if(abstractType.compareToIgnoreCase("MESSAGE")==0) {
+                    Message inlineMessage = (Message)aBodyContent.getContent();     
+                    s = getRawText(inlineMessage.getContent());
+                }
+                if (abstractType.compareToIgnoreCase("APPLICATION")==0) {
+                    s = "Attached File: " + aBodyContent.getFileName(); 
+                }
+                if (abstractType.compareToIgnoreCase("TEXT")==0) {
+                    try {
+                        Object oS = aBodyContent.getContent();
+                        if (oS instanceof String) { 
+                            s = (String)oS;
+                        } else {
+                            throw( new MessagingException("Unkown MIME Type (?): " + oS.getClass() ) );
+                        }
+                    } catch(Exception e) {
+                        throw( new MessagingException("Unable to read message contents (" + e.getMessage() + ")" ) );
+                    }
+                }
+                if (abstractType.compareToIgnoreCase("MULTIPART")==0 ) {
+                    s = getRawText(aBodyContent.getContent());
+                }
+            }
+            
+            if (o instanceof String) {
+                s = (String)o;
+            }
+            
+//          else {
+//              if (m.isMimeType("text/html")) {
+//                  s = m.getContent().toString();
+//              }
+//              if (m.isMimeType("text/plain")) {
+//                  s = m.getContent().toString();
+//              }   
+//          }
+            
+            return s;
+        }
+        
+        private boolean assessMessageUnreadable() throws MessagingException {
+            boolean evil = false;
+            if (subject.compareToIgnoreCase("Delivery Status Notification (Failure)")==0) {
+                evil = findInBody("Unable to read message contents");
+            }
+            return evil;
+        }
+        
+        private boolean assessMessageFailure() {
+            boolean failed = false;
+            if (!failed) { failed = findInBody("User[\\s]+unknown");  }
+            if (!failed) { failed = findInBody("No[\\s]+such[\\s]+user");  }
+            if (!failed) { failed = findInBody("550[\\s]+Invalid[\\s]+recipient");  }
+            if (!failed) { failed = findInBody("550[\\s]+Bogus[\\s]+Address");  }
+            if (!failed) { failed = findInBody("addresses[\\s]+were[\\s]+unknown");  }
+            if (!failed) { failed = findInBody("user[\\s]+is[\\s]+no[\\s]+longer[\\s]+associated[\\s]+with[\\s]+this[\\s]+company");  }
+            if (!failed) { failed = findInBody("Unknown[\\s]+Recipient");  }
+            if (!failed) { failed = findInBody("destination[\\s]+addresses[\\s]+were[\\s]+unknown");  }
+            if (!failed) { failed = findInBody("unknown[\\s]+user");  }
+            if (!failed) { failed = findInBody("recipient[\\s]+name[\\s]+is[\\s]+not[\\s]+recognized");  }
+            if (!failed) { failed = findInBody("not[\\s]+listed[\\s]+in[\\s]+Domino[\\s]+Directory");  }
+            if (!failed) { failed = findInBody("Delivery[\\s]+Status[\\s]+Notification[\\s]+\\Q(\\EFailure\\Q)\\E");  }
+            if (!failed) { failed = findInBody("This[\\s]+is[\\s]+a[\\s]+permanent[\\s]+error");  }
+            if (!failed) { failed = findInBody("This[\\s]+account[\\s]+has[\\s]+been[\\s]+closed");  }
+            if (!failed) { failed = findInBody("addresses[\\s]+had[\\s]+permanent[\\s]+fatal[\\s]+errors");  }
+            return failed;
+        }
+        
+        private boolean assessMessageMailboxFull() {
+            boolean full = false;
+            if (!full) { full = findInBody("Connection[\\s]+timed[\\s]+out"); }
+            if (!full) { full = findInBody("Over[\\s]+quota"); }
+            if (!full) { full = findInBody("size[\\s]+limit"); }
+            if (!full) { full = findInBody("account[\\s]+is[\\s]+full"); }
+            if (!full) { full = findInBody("diskspace[\\s]+quota"); }
+            if (!full) { full = findInBody("rejected[\\s]+for[\\s]+policy[\\s]+reasons"); }
+            if (!full) { full = findInBody("mailbox[\\s]+size[\\s]+limit"); }
+            return full;
+        }
+        
+        private boolean assessMessageOutOfOffice() {
+            boolean out = false;
+            //if ( subject.toLowerCase().startsWith("re:") ) {
+                if (!out) { out = findInBody("out[\\s]+of[\\s]+the[\\s]+office");  }
+                if (!out) { out = findInBody("out[\\s]+of[\\s]+my[\\s]+office");  }
+                if (!out) { out = findInBody("back[\\s]+in[\\s]+the[\\s]+office"); }
+                if (!out) { out = findInBody("I[\\s]+am[\\s]+overseas");  }
+                if (!out) { out = findInBody("I[\\s]+am[\\s]+away");  }
+                if (!out) { out = findInBody("I[\\s]+am[\\s]+on[\\s]+leave");  }
+                if (!out) { out = (findInBody("Auto[\\s]*generated") && findInBody("on[\\s]+leave")); }
+            //}
+            return out;
+        }
+        
+        private boolean assessMessageSubjectOutOfOffice() {
+            boolean out = false;
+            if (!out) { out = findInSubject("Out[\\s]+of[\\s]+office");  }
+            if (!out) { out = findInSubject("Out[\\s]+of[\\s]+my[\\s]+office");  }
+            if (!out) { out = findInSubject("out[\\s]+of[\\s]+the[\\s]+office");  }
+            if (!out) { out = findInSubject("away[\\s]+from[\\s]+my[\\s]+mail");  }
+            if (!out) { out = findInSubject("on[\\s]+leave");  }
+            return out;
+        }
+        
+        private boolean assessMessageSubjectMailboxFull() {
+            boolean full = false;
+            if (!full) { full = ((findInSubject("Email[\\s]+message[\\s]+blocked") && findInSubject("Image[\\s]+File[\\s]+Type")));  }
+            return full;
+        }
+        
+        private boolean assessMessageSubjectFailure() {
+            boolean failed = false;
+            if (!failed) { failed = ((findInSubject("DELIVERY[\\s]+FAILURE") && findInSubject("does[\\s]+not[\\s]+exist")));  }
+            if (!failed) { failed = ((findInSubject("DELIVERY[\\s]+FAILURE") && findInSubject("not[\\s]+listed")));  }
+            if (!failed) { failed = findInSubject("Permanent[\\s]+Delivery[\\s]+Failure");  }
+            if (!failed) { failed = findInSubject("User[\\s]+unknown");  }
+            if (!failed) {  //no idea...
+                String s = subject.toLowerCase();
+                failed = ( s.indexOf("user") > 0  && ( s.indexOf("unknown") > s.indexOf("user") ) );
+            }
+            return failed;
+        }
+            
+        private boolean findInBody(String regExp) {
+            boolean retval = false;
+            if (text!=null) {
+                Pattern pat = Pattern.compile(regExp, Pattern.CASE_INSENSITIVE);
+                Matcher m = pat.matcher(text);
+                retval = m.find();
+            }
+            return retval;
+        }
+        
+        private boolean findInSubject(String regExp) {
+            Pattern pat = Pattern.compile(regExp, Pattern.CASE_INSENSITIVE);
+            Matcher m = pat.matcher(subject);
+            return m.find();
+        }
+
+        private String subject;
+        private String text;
+        
+        public final static int TYPE_NORMAL = 1;
+        public final static int TYPE_SPAM = 2;  // should be trapped elsewhere
+        public final static int TYPE_OUT_OF_OFFICE = 3;
+        public final static int TYPE_DELIVERY_FAILURE = 4;
+        public final static int TYPE_MAILBOX_FULL = 5;
+        public final static int TYPE_OUTBOUND = 6;
+        
+    }
+
+}
+

Added: james/mailet/standard/trunk/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java
URL: http://svn.apache.org/viewvc/james/mailet/standard/trunk/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java?rev=1097086&view=auto
==============================================================================
--- james/mailet/standard/trunk/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java (added)
+++ james/mailet/standard/trunk/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java Wed Apr 27 11:45:34 2011
@@ -0,0 +1,200 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.transport.mailets;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashSet;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.GenericMailet;
+
+/**
+ * Serialise the email and pass it to an HTTP call
+ * 
+ * Sample configuration:
+ * 
+ <mailet match="All" class="HeadersToHTTP">
+   <url>http://192.168.0.252:3000/alarm</url>
+   <parameterKey>Test</parameterKey>
+   <parameterValue>ParameterValue</parameterValue>
+   <passThrough>true</passThrough>
+ </mailet>
+
+ * 
+ */
+public class HeadersToHTTP extends GenericMailet {
+
+	/**
+	 * The name of the header to be added.
+	 */
+	private String url;
+	private String parameterKey = null;
+	private String parameterValue = null;
+	private boolean passThrough = true;
+
+	/**
+	 * Initialize the mailet.
+	 */
+	public void init() throws MessagingException {
+
+		passThrough = (getInitParameter("passThrough", "true").compareToIgnoreCase("true") == 0);
+		String targetUrl = getInitParameter("url");
+		parameterKey = getInitParameter("parameterKey");
+		parameterValue = getInitParameter("parameterValue");
+
+		// Check if needed config values are used
+		if (targetUrl == null || targetUrl.equals("")) {
+			throw new MessagingException("Please configure a targetUrl (\"url\")");
+		} else {
+			try {
+				// targetUrl = targetUrl + ( targetUrl.contains("?") ? "&" :
+				// "?") + parameterKey + "=" + parameterValue;
+				url = new URL(targetUrl).toExternalForm();
+			} catch (MalformedURLException e) {
+				throw new MessagingException(
+						"Unable to contruct URL object from url");
+			}
+		}
+
+		// record the result
+		log("I will attempt to deliver serialised messages to "
+				+ targetUrl
+				+ ". "
+				+ ( ((parameterKey==null) || (parameterKey.length()<1)) ? "I will not add any fields to the post. " : "I will prepend: "	+ parameterKey + "=" + parameterValue + ". ")
+				+ (passThrough ? "Messages will pass through." : "Messages will be ghosted."));
+	}
+
+	/**
+	 * Takes the message, serialises it and sends it to the URL
+	 * 
+	 * @param mail
+	 *            the mail being processed
+	 * 
+	 * @throws MessagingException
+	 *             if an error arises during message processing
+	 */
+	public void service(Mail mail) {
+		try {
+			log(mail.getName() + "HeadersToHTTP: Starting");
+			MimeMessage message = mail.getMessage();
+			HashSet<NameValuePair> pairs = getNameValuePairs(message);
+			log(mail.getName() + "HeadersToHTTP: " + pairs.size() + " named value pairs found");
+			String result = httpPost(pairs);
+			if (passThrough == true) {
+				addHeader(mail, true, result);
+			} else {
+				mail.setState(Mail.GHOST);
+			}
+		} catch (javax.mail.MessagingException me) {
+			log(me.getMessage());
+			addHeader(mail, false, me.getMessage());
+		} catch (IOException e) {
+			log(e.getMessage());
+			addHeader(mail, false, e.getMessage());
+		}
+	}
+
+	private void addHeader(Mail mail, boolean success, String errorMessage) {
+		try {
+			MimeMessage message = mail.getMessage();
+			message.setHeader("X-headerToHTTP", (success ? "Succeeded" : "Failed"));
+			if (!success && errorMessage!=null && errorMessage.length()>0) {
+				message.setHeader("X-headerToHTTPFailure", errorMessage);
+			}
+			message.saveChanges();
+		} catch (MessagingException e) {
+			log(e.getMessage());
+		}
+	}
+
+	private String httpPost(HashSet<NameValuePair> pairs) throws HttpException, IOException {
+
+		HttpClient client = new HttpClient();
+		PostMethod post = new PostMethod(url);
+
+		post.setRequestBody(setToArray(pairs));
+		
+		int statusCode = client.executeMethod(post);
+		String result = statusCode + ": " + post.getStatusLine().toString();
+		log("HeadersToHTTP: " + result);
+		
+		return result;
+		
+	}
+
+	private NameValuePair[] setToArray(HashSet<NameValuePair> pairs) {
+		NameValuePair[] r =  new NameValuePair[pairs.size()];
+		int i = 0;
+		for(NameValuePair p : pairs) {
+			r[i] = p;
+			i = i + 1;
+		}
+		return r;
+	}
+	
+	private HashSet<NameValuePair> getNameValuePairs(MimeMessage message) throws UnsupportedEncodingException, MessagingException {
+
+		// to_address
+		// from
+		// reply to
+		// subject
+		
+		HashSet<NameValuePair> pairs = new HashSet<NameValuePair>();
+		
+    	if (message!=null) {
+	    	if (message.getSender()!=null) {
+	    		pairs.add( new NameValuePair( "from", message.getSender().toString() ) );
+	    	}
+	    	if (message.getReplyTo()!=null) {
+	    		pairs.add( new NameValuePair( "reply_to", message.getReplyTo().toString() ) );
+	    	}
+	    	if (message.getMessageID()!=null) {
+	    		pairs.add( new NameValuePair( "message_id", message.getMessageID() ) );
+	    	}
+	    	if (message.getSubject()!=null) {
+	    		pairs.add( new NameValuePair( "subject", message.getSubject() ) );
+	    	}
+	    	pairs.add( new NameValuePair( "size", Integer.toString(message.getSize()) ) );
+	    }
+
+		pairs.add( new NameValuePair( parameterKey, parameterValue) );
+    			
+    	return pairs;
+    }
+
+	/**
+	 * Return a string describing this mailet.
+	 * 
+	 * @return a string describing this mailet
+	 */
+	public String getMailetInfo() {
+		return "HTTP POST serialised message";
+	}
+
+}

Added: james/mailet/standard/trunk/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java
URL: http://svn.apache.org/viewvc/james/mailet/standard/trunk/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java?rev=1097086&view=auto
==============================================================================
--- james/mailet/standard/trunk/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java (added)
+++ james/mailet/standard/trunk/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java Wed Apr 27 11:45:34 2011
@@ -0,0 +1,213 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.transport.mailets;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.PostMethod;
+
+import org.apache.mailet.base.GenericMailet;
+import org.apache.mailet.Mail;
+
+/**
+ * Serialise the email and pass it to an HTTP call
+ * 
+ * Sample configuration:
+ * 
+ * <mailet match="All" class="SerialiseToHTTP">
+ * 		<name>URL</name> <value>url where serialised message will be posted</value>
+ * 		<name>ParameterKey</name> <value>An arbitrary parameter be added to the post</value>
+ * 		<name>ParameterValue</name> <value>A value for the arbitrary parameter</value>
+ * 		<name>MessageKeyName</name> <value>Field name for the serialised message</value>
+ * 		<name>passThrough</name> <value>true or false</value>
+ * </mailet>
+ * 
+ */
+public class SerialiseToHTTP extends GenericMailet {
+
+	/**
+	 * The name of the header to be added.
+	 */
+	private String url;
+	private String parameterKey = null;
+	private String parameterValue = null;
+	private String messageKeyName = "message";
+	private boolean passThrough = true;
+
+	/**
+	 * Initialize the mailet.
+	 */
+	public void init() throws MessagingException {
+
+		passThrough = (getInitParameter("passThrough", "true").compareToIgnoreCase("true") == 0);
+		String targetUrl = getInitParameter("url");
+		parameterKey = getInitParameter("parameterKey");
+		parameterValue = getInitParameter("parameterValue");
+		String m = getInitParameter("MessageKeyName");
+		if (m != null) {
+			messageKeyName = m;
+		}
+
+		// Check if needed config values are used
+		if (targetUrl == null || targetUrl.equals("")) {
+			throw new MessagingException(
+					"Please configure a targetUrl (\"url\")");
+		} else {
+			try {
+				// targetUrl = targetUrl + ( targetUrl.contains("?") ? "&" :
+				// "?") + parameterKey + "=" + parameterValue;
+				url = new URL(targetUrl).toExternalForm();
+			} catch (MalformedURLException e) {
+				throw new MessagingException(
+						"Unable to contruct URL object from url");
+			}
+		}
+
+		// record the result
+		log("I will attempt to deliver serialised messages to "
+				+ targetUrl
+				+ " as "
+				+ messageKeyName
+				+ ". "
+				+ (parameterKey==null || parameterKey.length()<2 ? "I will not add any fields to the post. " : "I will prepend: "	+ parameterKey + "=" + parameterValue + ". ")
+				+ (passThrough ? "Messages will pass through."
+						: "Messages will be ghosted."));
+	}
+
+	/**
+	 * Takes the message, serialises it and sends it to the URL
+	 * 
+	 * @param mail
+	 *            the mail being processed
+	 * 
+	 * @throws MessagingException
+	 *             if an error arises during message processing
+	 */
+	public void service(Mail mail) {
+		try {
+			MimeMessage message = mail.getMessage();
+			String serialisedMessage = getSerialisedMessage(message);
+			NameValuePair[] nameValuePairs = getNameValuePairs(serialisedMessage);
+			String result = httpPost(nameValuePairs);
+			if (passThrough == true) {
+				addHeader(mail, (result == null || result.length() == 0), result);
+			} else {
+				mail.setState(Mail.GHOST);
+			}
+		} catch (javax.mail.MessagingException me) {
+			log(me.getMessage());
+			addHeader(mail, false, me.getMessage());
+		} catch (IOException e) {
+			log(e.getMessage());
+			addHeader(mail, false, e.getMessage());
+		}
+	}
+
+	private void addHeader(Mail mail, boolean success, String errorMessage) {
+		try {
+			MimeMessage message = mail.getMessage();
+			message.setHeader("X-toHTTP", (success ? "Succeeded" : "Failed"));
+			if (!success && errorMessage!=null && errorMessage.length()>0) {
+				message.setHeader("X-toHTTPFailure", errorMessage);
+			}
+			message.saveChanges();
+		} catch (MessagingException e) {
+			log(e.getMessage());
+		}
+	}
+
+	private String getSerialisedMessage(MimeMessage message)
+			throws IOException, MessagingException {
+		ByteArrayOutputStream os = new ByteArrayOutputStream();
+		message.writeTo(os);
+		return os.toString();
+	}
+
+	private String httpPost(NameValuePair[] data) {
+
+		String response = null;
+		HttpClient client = new HttpClient();
+		PostMethod post = new PostMethod(url);
+
+		if( data.length>1 && data[1]!=null ) {
+			log( data[1].getName() + "::" + data[1].getValue() );
+		}
+		post.setRequestBody(data);
+
+		try {
+			int statusCode = client.executeMethod(post);
+
+			if (statusCode != HttpStatus.SC_OK) {
+				log("POST failed: " + post.getStatusLine());
+				response = post.getStatusLine().toString();
+			}// else {
+			//	byte[] responseBody = post.getResponseBody();
+			//	response = new String(responseBody);
+			//}
+
+		} catch (HttpException e) {
+			log("Fatal protocol violation: " + e.getMessage());
+			response = "Fatal protocol violation: " + e.getMessage();
+		} catch (IOException e) {
+			log("Fatal transport error: " + e.getMessage());
+			response = "Fatal transport error: " + e.getMessage();
+		} finally {
+			post.releaseConnection();
+		}
+
+		return response;
+	}
+
+	private NameValuePair[] getNameValuePairs(String message) throws UnsupportedEncodingException {
+
+    	int l = 1;
+    	if (parameterKey!=null && parameterKey.length()>0) {
+    		l = 2;
+    	}
+    	
+    	NameValuePair[] data = new NameValuePair[l];
+    	data[0] = new NameValuePair( messageKeyName, message);
+    	if (l==2) {
+    		data[1] = new NameValuePair( parameterKey, parameterValue);
+    	}
+    	
+    	return data;
+    }
+
+	/**
+	 * Return a string describing this mailet.
+	 * 
+	 * @return a string describing this mailet
+	 */
+	public String getMailetInfo() {
+		return "HTTP POST serialised message";
+	}
+
+}



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