JAMES-1877 Extract a message composer
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/80039f14 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/80039f14 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/80039f14 Branch: refs/heads/master Commit: 80039f140dff5e26ae4bfc605faf27a6702433cd Parents: 63bb307 Author: Benoit Tellier <[email protected]> Authored: Thu Dec 1 14:11:45 2016 +0700 Committer: Benoit Tellier <[email protected]> Committed: Tue Jan 10 15:12:48 2017 +0700 ---------------------------------------------------------------------- .../mailets/remoteDelivery/MessageComposer.java | 212 +++++++++++++++++++ 1 file changed, 212 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/80039f14/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/MessageComposer.java ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/MessageComposer.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/MessageComposer.java new file mode 100644 index 0000000..a57b496 --- /dev/null +++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/remoteDelivery/MessageComposer.java @@ -0,0 +1,212 @@ +/**************************************************************** + * 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.remoteDelivery; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.ConnectException; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.Arrays; + +import javax.mail.MessagingException; +import javax.mail.SendFailedException; +import javax.mail.internet.InternetAddress; + +import org.apache.mailet.Mail; +import org.apache.mailet.MailAddress; + +public class MessageComposer { + + private final RemoteDeliveryConfiguration configuration; + + public MessageComposer(RemoteDeliveryConfiguration configuration) { + this.configuration = configuration; + } + + public String composeForBounce(Mail mail, Exception ex) { + StringWriter sout = new StringWriter(); + PrintWriter out = new PrintWriter(sout, true); + String machine; + try { + machine = configuration.getHeloNameProvider().getHeloName(); + + } catch (Exception e) { + machine = "[address unknown]"; + } + String bounceBuffer = "Hi. This is the James mail server at " + machine + "."; + out.println(bounceBuffer); + out.println("I'm afraid I wasn't able to deliver your message to the following addresses."); + out.println("This is a permanent error; I've given up. Sorry it didn't work out. Below"); + out.println("I include the list of recipients and the reason why I was unable to deliver"); + out.println("your message."); + out.println(); + for (MailAddress mailAddress : mail.getRecipients()) { + out.println(mailAddress); + } + if (ex instanceof MessagingException) { + if (((MessagingException) ex).getNextException() == null) { + out.println(ex.getMessage().trim()); + } else { + Exception ex1 = ((MessagingException) ex).getNextException(); + if (ex1 instanceof SendFailedException) { + out.println("Remote mail server told me: " + ex1.getMessage().trim()); + } else if (ex1 instanceof UnknownHostException) { + out.println("Unknown host: " + ex1.getMessage().trim()); + out.println("This could be a DNS server error, a typo, or a problem with the recipient's mail server."); + } else if (ex1 instanceof ConnectException) { + // Already formatted as "Connection timed out: connect" + out.println(ex1.getMessage().trim()); + } else if (ex1 instanceof SocketException) { + out.println("Socket exception: " + ex1.getMessage().trim()); + } else { + out.println(ex1.getMessage().trim()); + } + } + } + out.println(); + return sout.toString(); + } + + /** + * Try to return a usefull logString created of the Exception which was + * given. Return null if nothing usefull could be done + * + * @param e The MessagingException to use + * @return logString + */ + public String fromException(Exception e) { + if (e.getClass().getName().endsWith(".SMTPSendFailedException")) { + return "RemoteHost said: " + e.getMessage(); + } else if (e instanceof SendFailedException) { + SendFailedException exception = (SendFailedException) e; + + // No error + if (exception.getInvalidAddresses().length == 0 && exception.getValidUnsentAddresses().length == 0) + return null; + + Exception ex; + StringBuilder sb = new StringBuilder(); + boolean smtpExFound = false; + sb.append("RemoteHost said:"); + + if (e instanceof MessagingException) + while ((ex = ((MessagingException) e).getNextException()) != null && ex instanceof MessagingException) { + e = ex; + if (ex.getClass().getName().endsWith(".SMTPAddressFailedException")) { + try { + InternetAddress ia = (InternetAddress) invokeGetter(ex, "getAddress"); + sb.append(" ( ").append(ia).append(" - [").append(ex.getMessage().replaceAll("\\n", "")).append("] )"); + smtpExFound = true; + } catch (IllegalStateException ise) { + // Error invoking the getAddress method + } catch (ClassCastException cce) { + // The getAddress method returned something + // different than InternetAddress + } + } + } + if (!smtpExFound) { + boolean invalidAddr = false; + sb.append(" ( "); + + if (exception.getInvalidAddresses().length > 0) { + sb.append(Arrays.toString(exception.getInvalidAddresses())); + invalidAddr = true; + } + if (exception.getValidUnsentAddresses().length > 0) { + if (invalidAddr) + sb.append(" "); + sb.append(Arrays.toString(exception.getValidUnsentAddresses())); + } + sb.append(" - ["); + sb.append(exception.getMessage().replaceAll("\\n", "")); + sb.append("] )"); + } + return sb.toString(); + } + return null; + } + + /** + * Utility method for getting the error message from the (nested) exception. + * + * @param me MessagingException + * @return error message + */ + public String getErrorMsg(Exception ex) { + if (ex instanceof MessagingException) { + return getNestedExceptionMessage((MessagingException) ex); + } else { + return ex.getMessage(); + } + } + + public String getNestedExceptionMessage(MessagingException me) { + if (me.getNextException() == null) { + return me.getMessage().trim(); + } else { + Exception ex1 = me.getNextException(); + return ex1.getMessage().trim(); + } + } + + public String composeFailLogMessage(Mail mail, Exception ex, boolean permanent) { + StringWriter sout = new StringWriter(); + PrintWriter out = new PrintWriter(sout, true); + out.print(permanentAsString(permanent) + " exception delivering mail (" + mail.getName() + ")" + retrieveExceptionLog(ex) + ": " ); + if (configuration.isDebug()) { + ex.printStackTrace(out); + } + return sout.toString(); + } + + private String permanentAsString(boolean permanent) { + if (permanent) { + return "Permanent"; + } + return "Temporary"; + } + + private String retrieveExceptionLog(Exception ex) { + String exceptionLog = fromException(ex); + if (exceptionLog != null) { + return ". " + exceptionLog; + } + return ""; + } + + private Object invokeGetter(Object target, String getter) { + try { + Method getAddress = target.getClass().getMethod(getter); + return getAddress.invoke(target); + } catch (NoSuchMethodException nsme) { + // An SMTPAddressFailedException with no getAddress method. + } catch (IllegalAccessException iae) { + } catch (IllegalArgumentException iae) { + } catch (InvocationTargetException ite) { + // Other issues with getAddress invokation. + } + return new IllegalStateException("Exception invoking " + getter + " on a " + target.getClass() + " object"); + } + +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
