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 12:11:33 UTC
svn commit: r1097059 - in
/james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets:
ClassifyBounce.java HeadersToHTTP.java SerialiseToHTTP.java
Author: eric
Date: Wed Apr 27 10:11:33 2011
New Revision: 1097059
URL: http://svn.apache.org/viewvc?rev=1097059&view=rev
Log:
Add submit emails to URLs contributed by Renen Watermeyer. Tks a bunch! (MAILET-39)
Added:
james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java
james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java
james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java
Added: james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java
URL: http://svn.apache.org/viewvc/james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java?rev=1097059&view=auto
==============================================================================
--- james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java (added)
+++ james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java Wed Apr 27 10:11:33 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/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java
URL: http://svn.apache.org/viewvc/james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java?rev=1097059&view=auto
==============================================================================
--- james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java (added)
+++ james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java Wed Apr 27 10:11:33 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/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java
URL: http://svn.apache.org/viewvc/james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java?rev=1097059&view=auto
==============================================================================
--- james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java (added)
+++ james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java Wed Apr 27 10:11:33 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
Re: Move mailets from server to standard-mailets [WAS: Re: svn
commit: r1097059 - in /james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets:
ClassifyBounce.java HeadersToHTTP.java SerialiseToHTTP.java]
Posted by Robert Burrell Donkin <ro...@gmail.com>.
On Mon, May 2, 2011 at 8:53 AM, Stefano Bagnara <ap...@bago.org> wrote:
> 2011/5/2 Eric Charles <er...@apache.org>:
>> I quickly checked for other mailets that could be moved.
>> There's just the last RecipientToLowerCase that does not depend on server.
>>
>> I will move it also.
>
> Great :-)
+1
:-)
> This way we have a clear view of what mailets are unsupported by the
> current mailet api and better can see what changes to do to mailet api
> in order to move more of them out of server tree.
+1
Adding interfaces directly into mailet-api may cause unfortunate
compatibility issues in the medium term. I'm less concerned about
future compatibility for mailet-base, so I've been thinking about
using that for the time being. In particular, the existing AI mailets
use the older SQL resources framework. For the moment, I've forked a
version into that project but might make more sense to move into
mailet-base.
Opinions?
Robert
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
Re: Move mailets from server to standard-mailets [WAS: Re: svn
commit: r1097059 - in /james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets:
ClassifyBounce.java HeadersToHTTP.java SerialiseToHTTP.java]
Posted by Stefano Bagnara <ap...@bago.org>.
2011/5/2 Eric Charles <er...@apache.org>:
> I quickly checked for other mailets that could be moved.
> There's just the last RecipientToLowerCase that does not depend on server.
>
> I will move it also.
Great :-)
This way we have a clear view of what mailets are unsupported by the
current mailet api and better can see what changes to do to mailet api
in order to move more of them out of server tree.
Stefano
> Tks,
> - Eric
>
> On 27/04/2011 13:20, Stefano Bagnara wrote:
>>>
>>> Well, 2 mailets (HeadersToHttp and SerializeToHttp) have dependencies on
>>> > commons-httpclient. The 3rd mailet (BounceClassifier) has no external
>>> > dependency
>>> >
>>> > For now, apache-standard-mailets modules only depends on
>>> > apache-mailet-base
>>> > and javax.mail, nothing more.
>>> >
>>> > Should I move the 3 mailets and introduce external dependency in
>>> > standar-mailets, or only move the BounceClassifier ?
>>
>> I'd move all of them.
>>
>> Stefano
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
> For additional commands, e-mail: server-dev-help@james.apache.org
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
Move mailets from server to standard-mailets [WAS: Re: svn commit:
r1097059 - in /james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets:
ClassifyBounce.java HeadersToHTTP.java SerialiseToHTTP.java]
Posted by Eric Charles <er...@apache.org>.
I quickly checked for other mailets that could be moved.
There's just the last RecipientToLowerCase that does not depend on server.
I will move it also.
Tks,
- Eric
On 27/04/2011 13:20, Stefano Bagnara wrote:
>> Well, 2 mailets (HeadersToHttp and SerializeToHttp) have dependencies on
>> > commons-httpclient. The 3rd mailet (BounceClassifier) has no external
>> > dependency
>> >
>> > For now, apache-standard-mailets modules only depends on apache-mailet-base
>> > and javax.mail, nothing more.
>> >
>> > Should I move the 3 mailets and introduce external dependency in
>> > standar-mailets, or only move the BounceClassifier ?
> I'd move all of them.
>
> Stefano
>
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
Re: svn commit: r1097059 - in /james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets:
ClassifyBounce.java HeadersToHTTP.java SerialiseToHTTP.java
Posted by Eric Charles <er...@apache.org>.
On 27/04/2011 13:20, Stefano Bagnara wrote:
> I'd move all of them.
>
> Stefano
>
Done :)
- Eric
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
Re: svn commit: r1097059 - in /james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets:
ClassifyBounce.java HeadersToHTTP.java SerialiseToHTTP.java
Posted by Stefano Bagnara <ap...@bago.org>.
2011/4/27 Eric Charles <er...@apache.org>:
> Well, 2 mailets (HeadersToHttp and SerializeToHttp) have dependencies on
> commons-httpclient. The 3rd mailet (BounceClassifier) has no external
> dependency
>
> For now, apache-standard-mailets modules only depends on apache-mailet-base
> and javax.mail, nothing more.
>
> Should I move the 3 mailets and introduce external dependency in
> standar-mailets, or only move the BounceClassifier ?
I'd move all of them.
Stefano
> On 27/04/2011 12:14, Stefano Bagnara wrote:
>>
>> 2011/4/27<er...@apache.org>:
>>>
>>> Author: eric
>>> Date: Wed Apr 27 10:11:33 2011
>>> New Revision: 1097059
>>>
>>> URL: http://svn.apache.org/viewvc?rev=1097059&view=rev
>>> Log:
>>> Add submit emails to URLs contributed by Renen Watermeyer. Tks a bunch!
>>> (MAILET-39)
>>
>> If the mailets have no dependencies on James Server internals (so they
>> depends only in mailet api) then we should put them in a "mailet"
>> product and not in server.
>> So I would prefer to see these mailets in the mailet-standard project.
>>
>> Stefano
>>
>>> Added:
>>>
>>> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java
>>>
>>> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java
>>>
>>> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java
>>>
>>> Added:
>>> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java
>>> URL:
>>> http://svn.apache.org/viewvc/james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java?rev=1097059&view=auto
>>>
>>> ==============================================================================
>>> ---
>>> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java
>>> (added)
>>> +++
>>> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java
>>> Wed Apr 27 10:11:33 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/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java
>>> URL:
>>> http://svn.apache.org/viewvc/james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java?rev=1097059&view=auto
>>>
>>> ==============================================================================
>>> ---
>>> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java
>>> (added)
>>> +++
>>> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java
>>> Wed Apr 27 10:11:33 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/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java
>>> URL:
>>> http://svn.apache.org/viewvc/james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java?rev=1097059&view=auto
>>>
>>> ==============================================================================
>>> ---
>>> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java
>>> (added)
>>> +++
>>> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java
>>> Wed Apr 27 10:11:33 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
>>>
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
>> For additional commands, e-mail: server-dev-help@james.apache.org
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
> For additional commands, e-mail: server-dev-help@james.apache.org
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
Re: svn commit: r1097059 - in /james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets:
ClassifyBounce.java HeadersToHTTP.java SerialiseToHTTP.java
Posted by Eric Charles <er...@apache.org>.
Well, 2 mailets (HeadersToHttp and SerializeToHttp) have dependencies on
commons-httpclient. The 3rd mailet (BounceClassifier) has no external
dependency
For now, apache-standard-mailets modules only depends on
apache-mailet-base and javax.mail, nothing more.
Should I move the 3 mailets and introduce external dependency in
standar-mailets, or only move the BounceClassifier ?
Tks,
- Eric
On 27/04/2011 12:14, Stefano Bagnara wrote:
> 2011/4/27<er...@apache.org>:
>> Author: eric
>> Date: Wed Apr 27 10:11:33 2011
>> New Revision: 1097059
>>
>> URL: http://svn.apache.org/viewvc?rev=1097059&view=rev
>> Log:
>> Add submit emails to URLs contributed by Renen Watermeyer. Tks a bunch! (MAILET-39)
>
> If the mailets have no dependencies on James Server internals (so they
> depends only in mailet api) then we should put them in a "mailet"
> product and not in server.
> So I would prefer to see these mailets in the mailet-standard project.
>
> Stefano
>
>> Added:
>> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java
>> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java
>> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java
>>
>> Added: james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java
>> URL: http://svn.apache.org/viewvc/james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java?rev=1097059&view=auto
>> ==============================================================================
>> --- james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java (added)
>> +++ james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java Wed Apr 27 10:11:33 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/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java
>> URL: http://svn.apache.org/viewvc/james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java?rev=1097059&view=auto
>> ==============================================================================
>> --- james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java (added)
>> +++ james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java Wed Apr 27 10:11:33 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/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java
>> URL: http://svn.apache.org/viewvc/james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java?rev=1097059&view=auto
>> ==============================================================================
>> --- james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java (added)
>> +++ james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java Wed Apr 27 10:11:33 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
>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
> For additional commands, e-mail: server-dev-help@james.apache.org
>
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
Re: svn commit: r1097059 - in /james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets:
ClassifyBounce.java HeadersToHTTP.java SerialiseToHTTP.java
Posted by Stefano Bagnara <ap...@bago.org>.
2011/4/27 <er...@apache.org>:
> Author: eric
> Date: Wed Apr 27 10:11:33 2011
> New Revision: 1097059
>
> URL: http://svn.apache.org/viewvc?rev=1097059&view=rev
> Log:
> Add submit emails to URLs contributed by Renen Watermeyer. Tks a bunch! (MAILET-39)
If the mailets have no dependencies on James Server internals (so they
depends only in mailet api) then we should put them in a "mailet"
product and not in server.
So I would prefer to see these mailets in the mailet-standard project.
Stefano
> Added:
> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java
> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java
> james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java
>
> Added: james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java
> URL: http://svn.apache.org/viewvc/james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java?rev=1097059&view=auto
> ==============================================================================
> --- james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java (added)
> +++ james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/ClassifyBounce.java Wed Apr 27 10:11:33 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/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java
> URL: http://svn.apache.org/viewvc/james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java?rev=1097059&view=auto
> ==============================================================================
> --- james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java (added)
> +++ james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/HeadersToHTTP.java Wed Apr 27 10:11:33 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/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java
> URL: http://svn.apache.org/viewvc/james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java?rev=1097059&view=auto
> ==============================================================================
> --- james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java (added)
> +++ james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/SerialiseToHTTP.java Wed Apr 27 10:11:33 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
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org