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 no...@apache.org on 2010/03/10 20:13:37 UTC
svn commit: r921519 [1/2] - in /james/server/trunk:
core-library/src/main/java/org/apache/james/
mailets/src/main/java/org/apache/james/transport/mailets/
mailets/src/test/java/org/apache/james/transport/mailets/
mailets/src/test/java/org/apache/james/...
Author: norman
Date: Wed Mar 10 19:13:36 2010
New Revision: 921519
URL: http://svn.apache.org/viewvc?rev=921519&view=rev
Log:
Introduce ActiveMQRemoteDelivery and JMSRemoteDelivery which replace the old RemoteDelivery Mailet and use JMS and Camel. TODO fix junit tests (JAMES-977)
Added:
james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/AbstractRemoteDelivery.java
james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/ActiveMQRemoteDelivery.java
james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/JMSRemoteDelivery.java
james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/RemoteDeliverySocketFactory.java
james/server/trunk/spoolmanager/src/test/java/org/apache/james/transport/mailets/RemoteDeliveryTest.java
- copied, changed from r919816, james/server/trunk/mailets/src/test/java/org/apache/james/transport/mailets/RemoteDeliveryTest.java
james/server/trunk/spoolmanager/src/test/java/org/apache/james/transport/mailets/StandardRemoteDeliveryTestable.java
- copied, changed from r919816, james/server/trunk/mailets/src/test/java/org/apache/james/transport/mailets/StandardRemoteDeliveryTestable.java
james/server/trunk/spoolmanager/src/test/java/org/apache/james/transport/remotedeliverytester/
- copied from r919816, james/server/trunk/mailets/src/test/java/org/apache/james/transport/remotedeliverytester/
Removed:
james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
james/server/trunk/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDeliverySocketFactory.java
james/server/trunk/mailets/src/test/java/org/apache/james/transport/mailets/RemoteDeliveryTest.java
james/server/trunk/mailets/src/test/java/org/apache/james/transport/mailets/StandardRemoteDeliveryTestable.java
james/server/trunk/mailets/src/test/java/org/apache/james/transport/remotedeliverytester/
Modified:
james/server/trunk/core-library/src/main/java/org/apache/james/Constants.java
james/server/trunk/spoolmanager/src/test/java/org/apache/james/transport/remotedeliverytester/AbstractRemoteDeliveryTest.java
james/server/trunk/spoolmanager/src/test/java/org/apache/james/transport/remotedeliverytester/RemoteDeliveryTestable.java
james/server/trunk/spoolmanager/src/test/java/org/apache/james/transport/remotedeliverytester/Tester.java
james/server/trunk/spring-deployment/src/main/config/james/spoolmanager.xml
james/server/trunk/spring-deployment/src/main/config/james/spring-beans.xml
Modified: james/server/trunk/core-library/src/main/java/org/apache/james/Constants.java
URL: http://svn.apache.org/viewvc/james/server/trunk/core-library/src/main/java/org/apache/james/Constants.java?rev=921519&r1=921518&r2=921519&view=diff
==============================================================================
--- james/server/trunk/core-library/src/main/java/org/apache/james/Constants.java (original)
+++ james/server/trunk/core-library/src/main/java/org/apache/james/Constants.java Wed Mar 10 19:13:36 2010
@@ -33,11 +33,11 @@ public class Constants {
/**
* The version of James.
*/
- public static final String SOFTWARE_VERSION = "@@VERSION@@";
+ public static final String SOFTWARE_VERSION = "3.0-M1";
/**
* The name of the software (i.e. James).
*/
- public static final String SOFTWARE_NAME = "@@NAME@@";
+ public static final String SOFTWARE_NAME = "Apache-James Mail Server";
}
Added: james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/AbstractRemoteDelivery.java
URL: http://svn.apache.org/viewvc/james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/AbstractRemoteDelivery.java?rev=921519&view=auto
==============================================================================
--- james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/AbstractRemoteDelivery.java (added)
+++ james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/AbstractRemoteDelivery.java Wed Mar 10 19:13:36 2010
@@ -0,0 +1,1748 @@
+/****************************************************************
+ * 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.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.ConnectException;
+import java.net.InetAddress;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import javax.annotation.Resource;
+import javax.mail.Address;
+import javax.mail.MessagingException;
+import javax.mail.SendFailedException;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+import javax.mail.internet.MimePart;
+import javax.mail.internet.ParseException;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.james.api.dnsservice.DNSService;
+import org.apache.james.api.dnsservice.TemporaryResolutionException;
+import org.apache.james.services.MailServer;
+import org.apache.james.transport.camel.InMemoryMail;
+import org.apache.james.transport.camel.JamesCamelConstants;
+import org.apache.james.util.TimeConverter;
+import org.apache.mailet.HostAddress;
+import org.apache.mailet.Mail;
+import org.apache.mailet.MailAddress;
+import org.apache.mailet.MailetContext;
+import org.apache.mailet.base.GenericMailet;
+import org.apache.oro.text.regex.MalformedPatternException;
+import org.apache.oro.text.regex.MatchResult;
+import org.apache.oro.text.regex.Pattern;
+import org.apache.oro.text.regex.Perl5Compiler;
+import org.apache.oro.text.regex.Perl5Matcher;
+
+/**
+ * <p>
+ * Receives a MessageContainer from JamesSpoolManager and takes care of delivery
+ * the message to remote hosts. If for some reason mail can't be delivered store
+ * it in the "outgoing" Repository and set an Alarm. After the next "delayTime"
+ * the Alarm will wake the servlet that will try to send it again. After
+ * "maxRetries" the mail will be considered undeliverable and will be returned
+ * to sender.
+ * </p>
+ * <p>
+ * TO DO (in priority):
+ * </p>
+ * <ol>
+ * <li>Support a gateway (a single server where all mail will be delivered)
+ * (DONE)</li>
+ * <li>Provide better failure messages (DONE)</li>
+ * <li>More efficiently handle numerous recipients</li>
+ * <li>Migrate to use Phoenix for the delivery threads</li>
+ * </ol>
+ * <p>
+ * You really want to read the JavaMail documentation if you are working in
+ * here, and you will want to view the list of JavaMail attributes, which are
+ * documented <a href='http://java.sun.com/products/javamail/javadocs/com/sun/mail/smtp/package-summary.html''>here</a
+ * > as well as other places.
+ * </p>
+ *
+ * @version CVS $Revision: 915502 $ $Date: 2010-02-23 21:27:49 +0100 (Di, 23 Feb
+ * 2010) $
+ */
+public abstract class AbstractRemoteDelivery extends GenericMailet implements CamelContextAware {
+
+ /** Default Delay Time (Default is 6*60*60*1000 Milliseconds (6 hours)). */
+ private static final long DEFAULT_DELAY_TIME = 21600000;
+
+ /** Pattern to match [attempts*]delay[units]. */
+ private static final String PATTERN_STRING = "\\s*([0-9]*\\s*[\\*])?\\s*([0-9]+)\\s*([a-z,A-Z]*)\\s*";
+
+ /** Compiled pattern of the above String. */
+ private static Pattern PATTERN = null;
+
+ /** The DNSService */
+ private DNSService dnsServer;
+
+ /**
+ * Static initializer.
+ * <p>
+ * Compiles pattern for processing delaytime entries.
+ * <p>
+ * Initializes MULTIPLIERS with the supported unit quantifiers
+ */
+ static {
+ try {
+ Perl5Compiler compiler = new Perl5Compiler();
+ PATTERN = compiler.compile(PATTERN_STRING,
+ Perl5Compiler.READ_ONLY_MASK);
+ } catch (MalformedPatternException mpe) {
+ // this should not happen as the pattern string is hardcoded.
+ mpe.printStackTrace(System.err);
+ }
+ }
+
+ /** Flag to define verbose logging messages. */
+ private boolean isDebug = false;
+
+ /** List of Delay Times. Controls frequency of retry attempts. */
+ private long[] delayTimes;
+
+ /** Maximum no. of retries (Defaults to 5). */
+ private int maxRetries = 5;
+
+ /** Default number of ms to timeout on smtp delivery */
+ private long smtpTimeout = 180000;
+
+ /** If false then ANY address errors will cause the transmission to fail */
+ private boolean sendPartial = false;
+
+ /**
+ * The amount of time JavaMail will wait before giving up on a socket
+ * connect()
+ */
+ private int connectionTimeout = 60000;
+
+ /** The server(s) to send all email to */
+ private Collection<String> gatewayServer = null;
+
+ /** Auth for gateway server */
+ private String authUser = null;
+
+ /** Password for gateway server */
+ private String authPass = null;
+
+ /**
+ * JavaMail delivery socket binds to this local address. If null the
+ * JavaMail default will be used.
+ */
+ private String bindAddress = null;
+
+ /**
+ * True, if the bind configuration parameter is supplied,
+ * RemoteDeliverySocketFactory will be used in this case.
+ */
+ private boolean isBindUsed = false;
+
+ /** the processor for creating Bounces */
+ private String bounceProcessor = null;
+
+ /** Default properties for the JavaMail Session */
+ private Properties defprops = new Properties();
+
+ /** The retry count dnsProblemErrors */
+ private int dnsProblemRetry = 0;
+
+ private MailServer mailServer;
+
+ private ProducerTemplate producerTemplate;
+
+ private CamelContext context;
+
+ private String outgoingQueue;
+
+ private String outgoingRetryQueue;
+
+ @Resource(name = "producerTemplate")
+ public void setProducerTemplate(ProducerTemplate producerTemplate) {
+ this.producerTemplate = producerTemplate;
+ }
+
+ @Resource(name = "dnsserver")
+ public void setDNSService(DNSService dnsService) {
+ this.dnsServer = dnsService;
+ }
+
+ @Resource(name = "James")
+ public void setMailServer(MailServer mailServer) {
+ this.mailServer = mailServer;
+ }
+
+ /**
+ * Initializes all arguments based on configuration values specified in the
+ * James configuration file.
+ *
+ * @throws MessagingException
+ * on failure to initialize attributes.
+ */
+ public void init() throws MessagingException {
+ // Set isDebug flag.
+ isDebug = (getInitParameter("debug") == null) ? false : new Boolean(
+ getInitParameter("debug")).booleanValue();
+
+ // Create list of Delay Times.
+ ArrayList<Delay> delayTimesList = new ArrayList<Delay>();
+ try {
+ if (getInitParameter("delayTime") != null) {
+
+ // parses delayTimes specified in config file.
+ final Perl5Matcher delayTimeMatcher = new Perl5Matcher();
+ String delayTimesParm = getInitParameter("delayTime");
+
+ // Split on commas
+ StringTokenizer st = new StringTokenizer(delayTimesParm, ",");
+ while (st.hasMoreTokens()) {
+ String delayTime = st.nextToken();
+ delayTimesList.add(new Delay(delayTimeMatcher, delayTime));
+ }
+ } else {
+ // Use default delayTime.
+ delayTimesList.add(new Delay());
+ }
+ } catch (Exception e) {
+ log("Invalid delayTime setting: " + getInitParameter("delayTime"));
+ }
+
+ try {
+ // Get No. of Max Retries.
+ if (getInitParameter("maxRetries") != null) {
+ maxRetries = Integer.parseInt(getInitParameter("maxRetries"));
+ }
+
+ // Check consistency of 'maxRetries' with delayTimesList attempts.
+ int totalAttempts = calcTotalAttempts(delayTimesList);
+
+ // If inconsistency found, fix it.
+ if (totalAttempts > maxRetries) {
+ log("Total number of delayTime attempts exceeds maxRetries specified. "
+ + " Increasing maxRetries from "
+ + maxRetries
+ + " to "
+ + totalAttempts);
+ maxRetries = totalAttempts;
+ } else {
+ int extra = maxRetries - totalAttempts;
+ if (extra != 0) {
+ log("maxRetries is larger than total number of attempts specified. "
+ + "Increasing last delayTime with "
+ + extra
+ + " attempts ");
+
+ // Add extra attempts to the last delayTime.
+ if (delayTimesList.size() != 0) {
+ // Get the last delayTime.
+ Delay delay = (Delay) delayTimesList.get(delayTimesList
+ .size() - 1);
+
+ // Increase no. of attempts.
+ delay.setAttempts(delay.getAttempts() + extra);
+ log("Delay of " + delay.getDelayTime()
+ + " msecs is now attempted: "
+ + delay.getAttempts() + " times");
+ } else {
+ throw new MessagingException(
+ "No delaytimes, cannot continue");
+ }
+ }
+ }
+ delayTimes = expandDelays(delayTimesList);
+
+ } catch (Exception e) {
+ log("Invalid maxRetries setting: " + getInitParameter("maxRetries"));
+ }
+
+ outgoingQueue = getInitParameter("outgoingQueue");
+ if (outgoingQueue == null) {
+ outgoingQueue = "outgoing";
+ }
+
+ outgoingRetryQueue = getInitParameter("outgoingRetryQueue");
+ if (outgoingRetryQueue == null) {
+ outgoingRetryQueue = "outgoing.retry";
+ }
+
+ try {
+ if (getInitParameter("timeout") != null) {
+ smtpTimeout = Integer.parseInt(getInitParameter("timeout"));
+ }
+ } catch (Exception e) {
+ log("Invalid timeout setting: " + getInitParameter("timeout"));
+ }
+
+ try {
+ if (getInitParameter("connectiontimeout") != null) {
+ connectionTimeout = Integer
+ .parseInt(getInitParameter("connectiontimeout"));
+ }
+ } catch (Exception e) {
+ log("Invalid timeout setting: " + getInitParameter("timeout"));
+ }
+
+ sendPartial = (getInitParameter("sendpartial") == null) ? false
+ : new Boolean(getInitParameter("sendpartial")).booleanValue();
+
+ bounceProcessor = getInitParameter("bounceProcessor");
+
+ String gateway = getInitParameter("gateway");
+ String gatewayPort = getInitParameter("gatewayPort");
+
+ if (gateway != null) {
+ gatewayServer = new ArrayList<String>();
+ StringTokenizer st = new StringTokenizer(gateway, ",");
+ while (st.hasMoreTokens()) {
+ String server = st.nextToken().trim();
+ if (server.indexOf(':') < 0 && gatewayPort != null) {
+ server += ":";
+ server += gatewayPort;
+ }
+
+ if (isDebug)
+ log("Adding SMTP gateway: " + server);
+ gatewayServer.add(server);
+ }
+ authUser = getInitParameter("gatewayUsername");
+ // backward compatibility with 2.3.x
+ if (authUser == null) {
+ authUser = getInitParameter("gatewayusername");
+ }
+ authPass = getInitParameter("gatewayPassword");
+ }
+
+ bindAddress = getInitParameter("bind");
+ isBindUsed = bindAddress != null;
+ try {
+ if (isBindUsed)
+ RemoteDeliverySocketFactory.setBindAdress(bindAddress);
+ } catch (UnknownHostException e) {
+ log("Invalid bind setting (" + bindAddress + "): " + e.toString());
+ }
+
+ // deal with <mail.*> attributes, passing them to javamail
+ Iterator<String> i = getInitParameterNames();
+ while (i.hasNext()) {
+ String name = i.next();
+ if (name.startsWith("mail.")) {
+ defprops.put(name, getInitParameter(name));
+ }
+
+ }
+
+ String dnsRetry = getInitParameter("maxDnsProblemRetries");
+ if (dnsRetry != null && !dnsRetry.equals("")) {
+ dnsProblemRetry = Integer.parseInt(dnsRetry);
+ }
+
+ try {
+ getCamelContext().addRoutes(new RemoteDeliveryRouteBuilder());
+ } catch (Exception e) {
+ throw new MessagingException("Unable to add camel route");
+ }
+ }
+
+ /**
+ * Calculates Total no. of attempts for the specified delayList.
+ *
+ * @param delayList
+ * list of 'Delay' objects
+ * @return total no. of retry attempts
+ */
+ private int calcTotalAttempts(ArrayList<Delay> delayList) {
+ int sum = 0;
+ Iterator<Delay> i = delayList.iterator();
+ while (i.hasNext()) {
+ Delay delay = i.next();
+ sum += delay.getAttempts();
+ }
+ return sum;
+ }
+
+ /**
+ * This method expands an ArrayList containing Delay objects into an array
+ * holding the only delaytime in the order.
+ * <p>
+ * So if the list has 2 Delay objects the first having attempts=2 and
+ * delaytime 4000 the second having attempts=1 and delaytime=300000 will be
+ * expanded into this array:
+ * <p>
+ * long[0] = 4000
+ * <p>
+ * long[1] = 4000
+ * <p>
+ * long[2] = 300000
+ * <p>
+ *
+ * @param list
+ * the list to expand
+ * @return the expanded list
+ **/
+ private long[] expandDelays(ArrayList<Delay> list) {
+ long[] delays = new long[calcTotalAttempts(list)];
+ Iterator<Delay> i = list.iterator();
+ int idx = 0;
+ while (i.hasNext()) {
+ Delay delay = i.next();
+ for (int j = 0; j < delay.getAttempts(); j++) {
+ delays[idx++] = delay.getDelayTime();
+ }
+ }
+ return delays;
+ }
+
+ /**
+ * This method returns, given a retry-count, the next delay time to use.
+ *
+ * @param retry_count
+ * the current retry_count.
+ * @return the next delay time to use, given the retry count
+ **/
+ private long getNextDelay(int retry_count) {
+ if (retry_count > delayTimes.length) {
+ return DEFAULT_DELAY_TIME;
+ }
+ return delayTimes[retry_count - 1];
+ }
+
+ /**
+ * This class is used to hold a delay time and its corresponding number of
+ * retries.
+ **/
+ private final static class Delay {
+ private int attempts = 1;
+
+ private long delayTime = DEFAULT_DELAY_TIME;
+
+ /**
+ * This constructor expects Strings of the form
+ * "[attempt\*]delaytime[unit]".
+ * <p>
+ * The optional attempt is the number of tries this delay should be used
+ * (default = 1). The unit, if present, must be one of
+ * (msec,sec,minute,hour,day). The default value of unit is 'msec'.
+ * <p>
+ * The constructor multiplies the delaytime by the relevant multiplier
+ * for the unit, so the delayTime instance variable is always in msec.
+ *
+ * @param initString
+ * the string to initialize this Delay object from
+ **/
+ public Delay(final Perl5Matcher delayTimeMatcher, String initString)
+ throws MessagingException {
+ // Default unit value to 'msec'.
+ String unit = "msec";
+
+ if (delayTimeMatcher.matches(initString, PATTERN)) {
+ MatchResult res = delayTimeMatcher.getMatch();
+
+ // The capturing groups will now hold:
+ // at 1: attempts * (if present)
+ // at 2: delaytime
+ // at 3: unit (if present)
+ if (res.group(1) != null && !res.group(1).equals("")) {
+ // We have an attempt *
+ String attemptMatch = res.group(1);
+
+ // Strip the * and whitespace.
+ attemptMatch = attemptMatch.substring(0,
+ attemptMatch.length() - 1).trim();
+ attempts = Integer.parseInt(attemptMatch);
+ }
+
+ delayTime = Long.parseLong(res.group(2));
+
+ if (!res.group(3).equals("")) {
+ // We have a value for 'unit'.
+ unit = res.group(3).toLowerCase(Locale.US);
+ }
+ } else {
+ throw new MessagingException(initString + " does not match "
+ + PATTERN_STRING);
+ }
+
+ // calculate delayTime.
+ try {
+ delayTime = TimeConverter.getMilliSeconds(delayTime, unit);
+ } catch (NumberFormatException e) {
+ throw new MessagingException(e.getMessage());
+ }
+ }
+
+ /**
+ * This constructor makes a default Delay object with attempts = 1 and
+ * delayTime = DEFAULT_DELAY_TIME.
+ **/
+ public Delay() {
+ }
+
+ /**
+ * @return the delayTime for this Delay
+ **/
+ public long getDelayTime() {
+ return delayTime;
+ }
+
+ /**
+ * @return the number attempts this Delay should be used.
+ **/
+ public int getAttempts() {
+ return attempts;
+ }
+
+ /**
+ * Set the number attempts this Delay should be used.
+ **/
+ public void setAttempts(int value) {
+ attempts = value;
+ }
+
+ /**
+ * Pretty prints this Delay
+ **/
+ public String toString() {
+ String message = getAttempts() + "*" + getDelayTime() + "msecs";
+ return message;
+ }
+ }
+
+ public String getMailetInfo() {
+ return "RemoteDelivery Mailet";
+ }
+
+ /**
+ * For this message, we take the list of recipients, organize these into
+ * distinct servers, and duplicate the message for each of these servers,
+ * and then call the deliver (messagecontainer) method for each
+ * server-specific messagecontainer ... that will handle storing it in the
+ * outgoing queue if needed.
+ *
+ * @param mail
+ * org.apache.mailet.Mail
+ */
+ public void service(Mail mail) throws MessagingException {
+ // Do I want to give the internal key, or the message's Message ID
+ if (isDebug) {
+ log("Remotely delivering mail " + mail.getName());
+ }
+ Collection<MailAddress> recipients = mail.getRecipients();
+
+ if (gatewayServer == null) {
+ // Must first organize the recipients into distinct servers (name
+ // made case insensitive)
+ Hashtable<String, Collection<MailAddress>> targets = new Hashtable<String, Collection<MailAddress>>();
+ for (Iterator<MailAddress> i = recipients.iterator(); i.hasNext();) {
+ MailAddress target = i.next();
+ String targetServer = target.getDomain().toLowerCase(Locale.US);
+ Collection<MailAddress> temp = targets.get(targetServer);
+ if (temp == null) {
+ temp = new ArrayList<MailAddress>();
+ targets.put(targetServer, temp);
+ }
+ temp.add(target);
+ }
+
+ // We have the recipients organized into distinct servers... put
+ // them into the
+ // delivery store organized like this... this is ultra inefficient I
+ // think...
+
+ // Store the new message containers, organized by server, in the
+ // outgoing mail repository
+ String name = mail.getName();
+ for (Iterator<String> i = targets.keySet().iterator(); i.hasNext();) {
+ String host = i.next();
+ Collection<MailAddress> rec = targets.get(host);
+ if (isDebug) {
+ StringBuilder logMessageBuffer = new StringBuilder(128)
+ .append("Sending mail to ").append(rec).append(
+ " on host ").append(host);
+ log(logMessageBuffer.toString());
+ }
+ Mail m = new InMemoryMail(mail);
+ m.setRecipients(rec);
+ StringBuilder nameBuffer = new StringBuilder(128).append(name)
+ .append("-to-").append(host);
+ m.setName(nameBuffer.toString());
+
+ producerTemplate.sendBody("activemq:queue:"
+ + outgoingQueue, m);
+ // workRepository.store(mail);
+ // Set it to try to deliver (in a separate thread) immediately
+ // (triggered by storage)
+ }
+ } else {
+ // Store the mail unaltered for processing by the gateway server(s)
+ if (isDebug) {
+ StringBuilder logMessageBuffer = new StringBuilder(128).append(
+ "Sending mail to ").append(mail.getRecipients())
+ .append(" via ").append(gatewayServer);
+ log(logMessageBuffer.toString());
+ }
+
+ producerTemplate.sendBody("activemq:queue:"
+ + outgoingQueue , new InMemoryMail(mail));
+
+ // Set it to try to deliver (in a separate thread) immediately
+ // (triggered by storage)
+ // workRepository.store(mail);
+ }
+ mail.setState(Mail.GHOST);
+ }
+
+ /**
+ * Processor which handles the delivery of messages. If the delivery should
+ * get done again in the future it will set the
+ * {@link JamesCamelConstants.JAMES_RETRY_DELIVERY} header to true. The next
+ * delivery time is set in milliseconds in the
+ * {@link JamesCamelConstants.JAMES_NEXT_DELIVERY} header
+ *
+ *
+ */
+ public final class DeliveryProcessor implements Processor {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.camel.Processor#process(org.apache.camel.Exchange)
+ */
+ public void process(Exchange arg0) throws Exception {
+
+ Message inMessage = arg0.getIn();
+ // Checks the pool and delivers a mail message
+ Properties props = new Properties();
+ // Not needed for production environment
+ props.put("mail.debug", "false");
+ // Reactivated: javamail 1.3.2 should no more have problems with
+ // "250 OK"
+ // messages (WAS "false": Prevents problems encountered with 250 OK
+ // Messages)
+ props.put("mail.smtp.ehlo", "true");
+ // By setting this property to true the transport is allowed to
+ // send 8 bit data to the server (if it supports the 8bitmime
+ // extension).
+ // 2006/03/01 reverted to false because of a javamail bug converting
+ // to 8bit
+ // messages created by an inputstream.
+ props.setProperty("mail.smtp.allow8bitmime", "true");
+ // Sets timeout on going connections
+ props.put("mail.smtp.timeout", smtpTimeout + "");
+
+ props.put("mail.smtp.connectiontimeout", connectionTimeout + "");
+ props.put("mail.smtp.sendpartial", String.valueOf(sendPartial));
+
+ // Set the hostname we'll use as this server
+ props.put("mail.smtp.localhost", mailServer.getHelloName());
+
+ if (isBindUsed) {
+ // undocumented JavaMail 1.2 feature, smtp transport will use
+ // our socket factory, which will also set the local address
+ props.put("mail.smtp.socketFactory.class",
+ RemoteDeliverySocketFactory.class.getClass());
+ // Don't fallback to the standard socket factory on error, do
+ // throw an exception
+ props.put("mail.smtp.socketFactory.fallback", "false");
+ }
+
+ if (authUser != null) {
+ props.put("mail.smtp.auth", "true");
+ }
+
+ props.putAll(defprops);
+
+ Session session = obtainSession(props);
+
+ Mail mail = inMessage.getBody(Mail.class);
+ String key = mail.getName();
+ if (isDebug) {
+ String message = Thread.currentThread().getName()
+ + " will process mail " + key;
+ log(message);
+ }
+
+ // Deliver message
+ if (deliver(mail, session)) {
+ inMessage
+ .removeHeader(JamesCamelConstants.JAMES_RETRY_DELIVERY);
+
+ // Message was successfully delivered/fully failed...
+ // delete it
+ // LifecycleUtil.dispose(mail);
+ // workRepository.remove(key);
+ } else {
+
+ // Test the time...
+ int retries = 0;
+
+ try {
+ retries = Integer.parseInt(mail.getErrorMessage());
+ } catch (NumberFormatException e) {
+ // Something strange was happen with the errorMessage..
+ // Ignore the Exception and try
+ // to deliver it now!
+ }
+
+ long delay = getNextDelay(retries);
+ long timeToProcess = delay + mail.getLastUpdated().getTime();
+
+ inMessage.setHeader(JamesCamelConstants.JAMES_RETRY_DELIVERY,
+ true);
+ inMessage.setHeader(JamesCamelConstants.JAMES_NEXT_DELIVERY,
+ timeToProcess);
+ }
+
+ }
+
+ /**
+ * We can assume that the recipients of this message are all going to
+ * the same mail server. We will now rely on the DNS server to do DNS MX
+ * record lookup and try to deliver to the multiple mail servers. If it
+ * fails, it should throw an exception.
+ *
+ * Creation date: (2/24/00 11:25:00 PM)
+ *
+ * @param mail
+ * org.apache.james.core.MailImpl
+ * @param session
+ * javax.mail.Session
+ * @return boolean Whether the delivery was successful and the message
+ * can be deleted
+ */
+ private boolean deliver(Mail mail, Session session) {
+ try {
+ if (isDebug) {
+ log("Attempting to deliver " + mail.getName());
+ }
+ MimeMessage message = mail.getMessage();
+
+ // Create an array of the recipients as InternetAddress objects
+ Collection<MailAddress> recipients = mail.getRecipients();
+ InternetAddress addr[] = new InternetAddress[recipients.size()];
+ int j = 0;
+ for (Iterator<MailAddress> i = recipients.iterator(); i
+ .hasNext(); j++) {
+ MailAddress rcpt = i.next();
+ addr[j] = rcpt.toInternetAddress();
+ }
+
+ if (addr.length <= 0) {
+ log("No recipients specified... not sure how this could have happened.");
+ return true;
+ }
+
+ // Figure out which servers to try to send to. This collection
+ // will hold all the possible target servers
+ Iterator<HostAddress> targetServers = null;
+ if (gatewayServer == null) {
+ MailAddress rcpt = (MailAddress) recipients.iterator()
+ .next();
+ String host = rcpt.getDomain();
+
+ // Lookup the possible targets
+ try {
+ targetServers = dnsServer.getSMTPHostAddresses(host);
+ } catch (TemporaryResolutionException e) {
+ log("Temporary problem looking up mail server for host: "
+ + host);
+ StringBuilder exceptionBuffer = new StringBuilder(128)
+ .append(
+ "Temporary problem looking up mail server for host: ")
+ .append(host)
+ .append(
+ ". I cannot determine where to send this message.");
+
+ // temporary problems
+ return failMessage(mail, new MessagingException(
+ exceptionBuffer.toString()), false);
+ }
+ if (!targetServers.hasNext()) {
+ log("No mail server found for: " + host);
+ StringBuilder exceptionBuffer = new StringBuilder(128)
+ .append(
+ "There are no DNS entries for the hostname ")
+ .append(host)
+ .append(
+ ". I cannot determine where to send this message.");
+
+ int retry = 0;
+ try {
+ retry = Integer.parseInt(mail.getErrorMessage());
+ } catch (NumberFormatException e) {
+ // Unable to parse retryCount
+ }
+ if (retry == 0 || retry > dnsProblemRetry) {
+ // The domain has no dns entry.. Return a permanent
+ // error
+ return failMessage(mail, new MessagingException(
+ exceptionBuffer.toString()), true);
+ } else {
+ return failMessage(mail, new MessagingException(
+ exceptionBuffer.toString()), false);
+ }
+ }
+ } else {
+ targetServers = getGatewaySMTPHostAddresses(gatewayServer);
+ }
+
+ MessagingException lastError = null;
+
+ while (targetServers.hasNext()) {
+ try {
+ HostAddress outgoingMailServer = targetServers.next();
+ StringBuilder logMessageBuffer = new StringBuilder(256)
+ .append("Attempting delivery of ").append(
+ mail.getName()).append(" to host ")
+ .append(outgoingMailServer.getHostName())
+ .append(" at ").append(
+ outgoingMailServer.getHost()).append(
+ " for addresses ").append(
+ Arrays.asList(addr));
+ log(logMessageBuffer.toString());
+
+ Properties props = session.getProperties();
+ if (mail.getSender() == null) {
+ props.put("mail.smtp.from", "<>");
+ } else {
+ String sender = mail.getSender().toString();
+ props.put("mail.smtp.from", sender);
+ }
+
+ // Many of these properties are only in later JavaMail
+ // versions
+ // "mail.smtp.ehlo" //default true
+ // "mail.smtp.auth" //default false
+ // "mail.smtp.dsn.ret" //default to nothing... appended
+ // as RET= after MAIL FROM line.
+ // "mail.smtp.dsn.notify" //default to
+ // nothing...appended as NOTIFY= after RCPT TO line.
+
+ Transport transport = null;
+ try {
+ transport = session
+ .getTransport(outgoingMailServer);
+ try {
+ if (authUser != null) {
+ transport.connect(outgoingMailServer
+ .getHostName(), authUser, authPass);
+ } else {
+ transport.connect();
+ }
+ } catch (MessagingException me) {
+ // Any error on connect should cause the mailet
+ // to attempt
+ // to connect to the next SMTP server associated
+ // with this
+ // MX record. Just log the exception. We'll
+ // worry about
+ // failing the message at the end of the loop.
+ log(me.getMessage());
+ continue;
+ }
+ // if the transport is a SMTPTransport (from sun)
+ // some
+ // performance enhancement can be done.
+ if (transport.getClass().getName().endsWith(
+ ".SMTPTransport")) {
+ boolean supports8bitmime = false;
+ try {
+ Method supportsExtension = transport
+ .getClass()
+ .getMethod(
+ "supportsExtension",
+ new Class[] { String.class });
+ supports8bitmime = ((Boolean) supportsExtension
+ .invoke(transport,
+ new Object[] { "8BITMIME" }))
+ .booleanValue();
+ } catch (NoSuchMethodException nsme) {
+ // An SMTPAddressFailedException with no
+ // getAddress method.
+ } catch (IllegalAccessException iae) {
+ } catch (IllegalArgumentException iae) {
+ } catch (InvocationTargetException ite) {
+ // Other issues with getAddress invokation.
+ }
+
+ // if the message is alredy 8bit or binary and
+ // the
+ // server doesn't support the 8bit extension it
+ // has
+ // to be converted to 7bit. Javamail api doesn't
+ // perform
+ // that conversion, but it is required to be a
+ // rfc-compliant smtp server.
+
+ // Temporarily disabled. See JAMES-638
+ if (!supports8bitmime) {
+ try {
+ convertTo7Bit(message);
+ } catch (IOException e) {
+ // An error has occured during the 7bit
+ // conversion.
+ // The error is logged and the message
+ // is sent anyway.
+
+ log(
+ "Error during the conversion to 7 bit.",
+ e);
+ }
+ }
+ } else {
+ // If the transport is not the one
+ // developed by Sun we are not sure of how it
+ // handles the 8 bit mime stuff,
+ // so I convert the message to 7bit.
+ try {
+ convertTo7Bit(message);
+ } catch (IOException e) {
+ log(
+ "Error during the conversion to 7 bit.",
+ e);
+ }
+ }
+ transport.sendMessage(message, addr);
+ } finally {
+ if (transport != null) {
+ try {
+ // James-899: transport.close() sends QUIT
+ // to the server; if that fails
+ // (e.g. because the server has already
+ // closed the connection) the message
+ // should be considered to be delivered
+ // because the error happened outside
+ // of the mail transaction (MAIL, RCPT,
+ // DATA).
+ transport.close();
+ } catch (MessagingException e) {
+ log("Warning: could not close the SMTP transport after sending mail ("
+ + mail.getName()
+ + ") to "
+ + outgoingMailServer.getHostName()
+ + " at "
+ + outgoingMailServer.getHost()
+ + " for "
+ + mail.getRecipients()
+ + "; probably the server has already closed the "
+ + "connection. Message is considered to be delivered. Exception: "
+ + e.getMessage());
+ }
+ transport = null;
+ }
+ }
+ logMessageBuffer = new StringBuilder(256).append(
+ "Mail (").append(mail.getName()).append(
+ ") sent successfully to ").append(
+ outgoingMailServer.getHostName())
+ .append(" at ").append(
+ outgoingMailServer.getHost()).append(
+ " for ").append(mail.getRecipients());
+ log(logMessageBuffer.toString());
+ return true;
+ } catch (SendFailedException sfe) {
+ logSendFailedException(sfe);
+
+ if (sfe.getValidSentAddresses() != null) {
+ Address[] validSent = sfe.getValidSentAddresses();
+ if (validSent.length > 0) {
+ StringBuilder logMessageBuffer = new StringBuilder(
+ 256).append("Mail (").append(
+ mail.getName()).append(
+ ") sent successfully for ").append(
+ Arrays.asList(validSent));
+ log(logMessageBuffer.toString());
+ }
+ }
+
+ /*
+ * SMTPSendFailedException introduced in JavaMail 1.3.2,
+ * and provides detailed protocol reply code for the
+ * operation
+ */
+ if (sfe.getClass().getName().endsWith(
+ ".SMTPSendFailedException")) {
+ try {
+ int returnCode = ((Integer) invokeGetter(sfe,
+ "getReturnCode")).intValue();
+ // if 5xx, terminate this delivery attempt by
+ // re-throwing the exception.
+ if (returnCode >= 500 && returnCode <= 599)
+ throw sfe;
+ } catch (ClassCastException cce) {
+ } catch (IllegalArgumentException iae) {
+ }
+ }
+
+ if (sfe.getValidUnsentAddresses() != null
+ && sfe.getValidUnsentAddresses().length > 0) {
+ if (isDebug)
+ log("Send failed, "
+ + sfe.getValidUnsentAddresses().length
+ + " valid addresses remain, continuing with any other servers");
+ lastError = sfe;
+ continue;
+ } else {
+ // There are no valid addresses left to send, so
+ // rethrow
+ throw sfe;
+ }
+ } catch (MessagingException me) {
+ // MessagingException are horribly difficult to figure
+ // out what actually happened.
+ StringBuilder exceptionBuffer = new StringBuilder(256)
+ .append("Exception delivering message (")
+ .append(mail.getName()).append(") - ").append(
+ me.getMessage());
+ log(exceptionBuffer.toString());
+ if ((me.getNextException() != null)
+ && (me.getNextException() instanceof java.io.IOException)) {
+ // This is more than likely a temporary failure
+
+ // If it's an IO exception with no nested exception,
+ // it's probably
+ // some socket or weird I/O related problem.
+ lastError = me;
+ continue;
+ }
+ // This was not a connection or I/O error particular to
+ // one
+ // SMTP server of an MX set. Instead, it is almost
+ // certainly
+ // a protocol level error. In this case we assume that
+ // this
+ // is an error we'd encounter with any of the SMTP
+ // servers
+ // associated with this MX record, and we pass the
+ // exception
+ // to the code in the outer block that determines its
+ // severity.
+ throw me;
+ }
+ } // end while
+ // If we encountered an exception while looping through,
+ // throw the last MessagingException we caught. We only
+ // do this if we were unable to send the message to any
+ // server. If sending eventually succeeded, we exit
+ // deliver() though the return at the end of the try
+ // block.
+ if (lastError != null) {
+ throw lastError;
+ }
+ } catch (SendFailedException sfe) {
+ logSendFailedException(sfe);
+
+ Collection<MailAddress> recipients = mail.getRecipients();
+
+ boolean deleteMessage = false;
+
+ /*
+ * If you send a message that has multiple invalid addresses,
+ * you'll get a top-level SendFailedException that that has the
+ * valid, valid-unsent, and invalid address lists, with all of
+ * the server response messages will be contained within the
+ * nested exceptions. [Note: the content of the nested
+ * exceptions is implementation dependent.]
+ *
+ * sfe.getInvalidAddresses() should be considered permanent.
+ * sfe.getValidUnsentAddresses() should be considered temporary.
+ *
+ * JavaMail v1.3 properly populates those collections based upon
+ * the 4xx and 5xx response codes to RCPT TO. Some servers, such
+ * as Yahoo! don't respond to the RCPT TO, and provide a 5xx
+ * reply after DATA. In that case, we will pick up the failure
+ * from SMTPSendFailedException.
+ */
+
+ /*
+ * SMTPSendFailedException introduced in JavaMail 1.3.2, and
+ * provides detailed protocol reply code for the operation
+ */
+ try {
+ if (sfe.getClass().getName().endsWith(
+ ".SMTPSendFailedException")) {
+ int returnCode = ((Integer) invokeGetter(sfe,
+ "getReturnCode")).intValue();
+ // If we got an SMTPSendFailedException, use its RetCode
+ // to determine default permanent/temporary failure
+ deleteMessage = (returnCode >= 500 && returnCode <= 599);
+ } else {
+ // Sometimes we'll get a normal SendFailedException with
+ // nested SMTPAddressFailedException, so use the latter
+ // RetCode
+ MessagingException me = sfe;
+ Exception ne;
+ while ((ne = me.getNextException()) != null
+ && ne instanceof MessagingException) {
+ me = (MessagingException) ne;
+ if (me.getClass().getName().endsWith(
+ ".SMTPAddressFailedException")) {
+ int returnCode = ((Integer) invokeGetter(me,
+ "getReturnCode")).intValue();
+ deleteMessage = (returnCode >= 500 && returnCode <= 599);
+ }
+ }
+ }
+ } catch (IllegalStateException ise) {
+ // unexpected exception (not a compatible javamail
+ // implementation)
+ } catch (ClassCastException cce) {
+ // unexpected exception (not a compatible javamail
+ // implementation)
+ }
+
+ // log the original set of intended recipients
+ if (isDebug)
+ log("Recipients: " + recipients);
+
+ if (sfe.getInvalidAddresses() != null) {
+ Address[] address = sfe.getInvalidAddresses();
+ if (address.length > 0) {
+ recipients.clear();
+ for (int i = 0; i < address.length; i++) {
+ try {
+ recipients.add(new MailAddress(address[i]
+ .toString()));
+ } catch (ParseException pe) {
+ // this should never happen ... we should have
+ // caught malformed addresses long before we
+ // got to this code.
+ log("Can't parse invalid address: "
+ + pe.getMessage());
+ }
+ }
+ if (isDebug)
+ log("Invalid recipients: " + recipients);
+ deleteMessage = failMessage(mail, sfe, true);
+ }
+ }
+
+ if (sfe.getValidUnsentAddresses() != null) {
+ Address[] address = sfe.getValidUnsentAddresses();
+ if (address.length > 0) {
+ recipients.clear();
+ for (int i = 0; i < address.length; i++) {
+ try {
+ recipients.add(new MailAddress(address[i]
+ .toString()));
+ } catch (ParseException pe) {
+ // this should never happen ... we should have
+ // caught malformed addresses long before we
+ // got to this code.
+ log("Can't parse unsent address: "
+ + pe.getMessage());
+ }
+ }
+ if (isDebug)
+ log("Unsent recipients: " + recipients);
+ if (sfe.getClass().getName().endsWith(
+ ".SMTPSendFailedException")) {
+ int returnCode = ((Integer) invokeGetter(sfe,
+ "getReturnCode")).intValue();
+ deleteMessage = failMessage(mail, sfe,
+ returnCode >= 500 && returnCode <= 599);
+ } else {
+ deleteMessage = failMessage(mail, sfe, false);
+ }
+ }
+ }
+
+ return deleteMessage;
+ } catch (MessagingException ex) {
+ // We should do a better job checking this... if the failure is
+ // a general
+ // connect exception, this is less descriptive than more
+ // specific SMTP command
+ // failure... have to lookup and see what are the various
+ // Exception
+ // possibilities
+
+ // Unable to deliver message after numerous tries... fail
+ // accordingly
+
+ // We check whether this is a 5xx error message, which
+ // indicates a permanent failure (like account doesn't exist
+ // or mailbox is full or domain is setup wrong).
+ // We fail permanently if this was a 5xx error
+ return failMessage(mail, ex, ('5' == ex.getMessage().charAt(0)));
+ } catch (Exception ex) {
+ // Generic exception = permanent failure
+ return failMessage(mail, ex, true);
+ }
+
+ /*
+ * If we get here, we've exhausted the loop of servers without
+ * sending the message or throwing an exception. One case where this
+ * might happen is if we get a MessagingException on each
+ * transport.connect(), e.g., if there is only one server and we get
+ * a connect exception.
+ */
+ return failMessage(mail, new MessagingException(
+ "No mail server(s) available at this time."), false);
+ }
+
+ /**
+ * 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
+ */
+ private String exceptionToLogString(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(" ( " + ia + " - ["
+ + ex.getMessage().replaceAll("\\n", "")
+ + "] )");
+ 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(exception.getInvalidAddresses());
+ invalidAddr = true;
+ }
+ if (exception.getValidUnsentAddresses().length > 0) {
+ if (invalidAddr == true)
+ sb.append(" ");
+ sb.append(exception.getValidUnsentAddresses());
+ }
+ sb.append(" - [");
+ sb.append(exception.getMessage().replaceAll("\\n", ""));
+ sb.append("] )");
+ }
+ return sb.toString();
+ }
+ return null;
+ }
+
+ /**
+ * Utility method used to invoke getters for javamail implementation
+ * specific classes.
+ *
+ * @param target
+ * the object whom method will be invoked
+ * @param getter
+ * the no argument method name
+ * @return the result object
+ * @throws IllegalStateException
+ * on invocation error
+ */
+ private Object invokeGetter(Object target, String getter) {
+ try {
+ Method getAddress = target.getClass().getMethod(getter, null);
+ return getAddress.invoke(target, null);
+ } 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");
+ }
+
+ /*
+ * private method to log the extended SendFailedException introduced in
+ * JavaMail 1.3.2.
+ */
+ private void logSendFailedException(SendFailedException sfe) {
+ if (isDebug) {
+ MessagingException me = sfe;
+ if (me.getClass().getName()
+ .endsWith(".SMTPSendFailedException")) {
+ try {
+ String command = (String) invokeGetter(sfe,
+ "getCommand");
+ Integer returnCode = (Integer) invokeGetter(sfe,
+ "getReturnCode");
+ log("SMTP SEND FAILED:");
+ log(sfe.toString());
+ log(" Command: " + command);
+ log(" RetCode: " + returnCode);
+ log(" Response: " + sfe.getMessage());
+ } catch (IllegalStateException ise) {
+ // Error invoking the getAddress method
+ log("Send failed: " + me.toString());
+ } catch (ClassCastException cce) {
+ // The getAddress method returned something different
+ // than InternetAddress
+ log("Send failed: " + me.toString());
+ }
+ } else {
+ log("Send failed: " + me.toString());
+ }
+ Exception ne;
+ while ((ne = me.getNextException()) != null
+ && ne instanceof MessagingException) {
+ me = (MessagingException) ne;
+ if (me.getClass().getName().endsWith(
+ ".SMTPAddressFailedException")
+ || me.getClass().getName().endsWith(
+ ".SMTPAddressSucceededException")) {
+ try {
+ String action = me.getClass().getName().endsWith(
+ ".SMTPAddressFailedException") ? "FAILED"
+ : "SUCCEEDED";
+ InternetAddress address = (InternetAddress) invokeGetter(
+ me, "getAddress");
+ String command = (String) invokeGetter(me,
+ "getCommand");
+ Integer returnCode = (Integer) invokeGetter(me,
+ "getReturnCode");
+ log("ADDRESS " + action + ":");
+ log(me.toString());
+ log(" Address: " + address);
+ log(" Command: " + command);
+ log(" RetCode: " + returnCode);
+ log(" Response: " + me.getMessage());
+ } catch (IllegalStateException ise) {
+ // Error invoking the getAddress method
+ } catch (ClassCastException cce) {
+ // A method returned something different than
+ // expected
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Converts a message to 7 bit.
+ *
+ * @param part
+ */
+ private void convertTo7Bit(MimePart part) throws MessagingException,
+ IOException {
+ if (part.isMimeType("multipart/*")) {
+ MimeMultipart parts = (MimeMultipart) part.getContent();
+ int count = parts.getCount();
+ for (int i = 0; i < count; i++) {
+ convertTo7Bit((MimePart) parts.getBodyPart(i));
+ }
+ } else if ("8bit".equals(part.getEncoding())) {
+ // The content may already be in encoded the form (likely with
+ // mail created from a
+ // stream). In that case, just changing the encoding to
+ // quoted-printable will mangle
+ // the result when this is transmitted. We must first convert
+ // the content into its
+ // native format, set it back, and only THEN set the transfer
+ // encoding to force the
+ // content to be encoded appropriately.
+
+ // if the part doesn't contain text it will be base64 encoded.
+ String contentTransferEncoding = part.isMimeType("text/*") ? "quoted-printable"
+ : "base64";
+ part.setContent(part.getContent(), part.getContentType());
+ part.setHeader("Content-Transfer-Encoding",
+ contentTransferEncoding);
+ part.addHeader("X-MIME-Autoconverted", "from 8bit to "
+ + contentTransferEncoding + " by "
+ + getMailetContext().getServerInfo());
+ }
+ }
+
+ /**
+ * Insert the method's description here. Creation date: (2/25/00 1:14:18
+ * AM)
+ *
+ * @param mail
+ * org.apache.james.core.MailImpl
+ * @param ex
+ * javax.mail.MessagingException
+ * @param permanent
+ * @return boolean Whether the message failed fully and can be deleted
+ */
+ private boolean failMessage(Mail mail, Exception ex, boolean permanent) {
+ StringWriter sout = new StringWriter();
+ PrintWriter out = new PrintWriter(sout, true);
+ if (permanent) {
+ out.print("Permanent");
+ } else {
+ out.print("Temporary");
+ }
+
+ String exceptionLog = exceptionToLogString(ex);
+
+ StringBuilder logBuffer = new StringBuilder(64).append(
+ " exception delivering mail (").append(mail.getName());
+
+ if (exceptionLog != null) {
+ logBuffer.append(". ");
+ logBuffer.append(exceptionLog);
+ }
+
+ logBuffer.append(": ");
+ out.print(logBuffer.toString());
+ if (isDebug)
+ ex.printStackTrace(out);
+ log(sout.toString());
+ if (!permanent) {
+ if (!mail.getState().equals(Mail.ERROR)) {
+ mail.setState(Mail.ERROR);
+ mail.setErrorMessage("0");
+ mail.setLastUpdated(new Date());
+ }
+
+ int retries = 0;
+ try {
+ retries = Integer.parseInt(mail.getErrorMessage());
+ } catch (NumberFormatException e) {
+ // Something strange was happen with the errorMessage..
+ }
+
+ if (retries < maxRetries) {
+ logBuffer = new StringBuilder(128).append(
+ "Storing message ").append(mail.getName()).append(
+ " into outgoing after ").append(retries).append(
+ " retries");
+ log(logBuffer.toString());
+ ++retries;
+ mail.setErrorMessage(retries + "");
+ mail.setLastUpdated(new Date());
+ return false;
+ } else {
+ logBuffer = new StringBuilder(128).append(
+ "Bouncing message ").append(mail.getName()).append(
+ " after ").append(retries).append(" retries");
+ log(logBuffer.toString());
+ }
+ }
+
+ if (mail.getSender() == null) {
+ log("Null Sender: no bounce will be generated for "
+ + mail.getName());
+ return true;
+ }
+
+ if (bounceProcessor != null) {
+ // do the new DSN bounce
+ // setting attributes for DSN mailet
+ mail.setAttribute("delivery-error", ex);
+ mail.setState(bounceProcessor);
+ // re-insert the mail into the spool for getting it passed to
+ // the dsn-processor
+ MailetContext mc = getMailetContext();
+ try {
+ mc.sendMail(mail);
+ } catch (MessagingException e) {
+ // we shouldn't get an exception, because the mail was
+ // already processed
+ log("Exception re-inserting failed mail: ", e);
+ }
+ } else {
+ // do an old style bounce
+ bounce(mail, ex);
+ }
+ return true;
+ }
+
+ private void bounce(Mail mail, Exception ex) {
+ StringWriter sout = new StringWriter();
+ PrintWriter out = new PrintWriter(sout, true);
+ String machine = "[unknown]";
+ try {
+ machine = dnsServer.getLocalHost().getHostName();
+
+ } catch (Exception e) {
+ machine = "[address unknown]";
+ }
+ StringBuilder bounceBuffer = new StringBuilder(128).append(
+ "Hi. This is the James mail server at ").append(machine)
+ .append(".");
+ out.println(bounceBuffer.toString());
+ 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 (Iterator<MailAddress> i = mail.getRecipients().iterator(); i
+ .hasNext();) {
+ out.println(i.next());
+ }
+ 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();
+
+ log("Sending failure message " + mail.getName());
+ try {
+ getMailetContext().bounce(mail, sout.toString());
+ } catch (MessagingException me) {
+ log("Encountered unexpected messaging exception while bouncing message: "
+ + me.getMessage());
+ } catch (Exception e) {
+ log("Encountered unexpected exception while bouncing message: "
+ + e.getMessage());
+ }
+ }
+
+ /**
+ * Returns the javamail Session object.
+ *
+ * @param props
+ * @param authenticator
+ * @return
+ */
+ protected Session obtainSession(Properties props) {
+ return Session.getInstance(props);
+ }
+
+ /**
+ * Returns an Iterator over org.apache.mailet.HostAddress, a specialized
+ * subclass of javax.mail.URLName, which provides location information
+ * for servers that are specified as mail handlers for the given
+ * hostname. If no host is found, the Iterator returned will be empty
+ * and the first call to hasNext() will return false. The Iterator is a
+ * nested iterator: the outer iteration is over each gateway, and the
+ * inner iteration is over potentially multiple A records for each
+ * gateway.
+ *
+ * @see org.apache.james.DNSServer#getSMTPHostAddresses(String)
+ * @since v2.2.0a16-unstable
+ * @param gatewayServers
+ * - Collection of host[:port] Strings
+ * @return an Iterator over HostAddress instances, sorted by priority
+ */
+ private Iterator<HostAddress> getGatewaySMTPHostAddresses(
+ final Collection<String> gatewayServers) {
+ return new Iterator<HostAddress>() {
+ private Iterator<String> gateways = gatewayServers.iterator();
+ private Iterator<HostAddress> addresses = null;
+
+ public boolean hasNext() {
+ /*
+ * Make sure that when next() is called, that we can provide
+ * a HostAddress. This means that we need to have an inner
+ * iterator, and verify that it has addresses. We could, for
+ * example, run into a situation where the next gateway
+ * didn't have any valid addresses.
+ */
+ if (!hasNextAddress() && gateways.hasNext()) {
+ do {
+ String server = (String) gateways.next();
+ String port = "25";
+
+ int idx = server.indexOf(':');
+ if (idx > 0) {
+ port = server.substring(idx + 1);
+ server = server.substring(0, idx);
+ }
+
+ final String nextGateway = server;
+ final String nextGatewayPort = port;
+ try {
+ final InetAddress[] ips = dnsServer
+ .getAllByName(nextGateway);
+ addresses = new Iterator<HostAddress>() {
+ private InetAddress[] ipAddresses = ips;
+ int i = 0;
+
+ public boolean hasNext() {
+ return i < ipAddresses.length;
+ }
+
+ public HostAddress next() {
+ return new org.apache.mailet.HostAddress(
+ nextGateway,
+ "smtp://"
+ + (ipAddresses[i++])
+ .getHostAddress()
+ + ":" + nextGatewayPort);
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException(
+ "remove not supported by this iterator");
+ }
+ };
+ } catch (java.net.UnknownHostException uhe) {
+ log("Unknown gateway host: "
+ + uhe.getMessage().trim());
+ log("This could be a DNS server error or configuration error.");
+ }
+ } while (!hasNextAddress() && gateways.hasNext());
+ }
+
+ return hasNextAddress();
+ }
+
+ private boolean hasNextAddress() {
+ return addresses != null && addresses.hasNext();
+ }
+
+ public HostAddress next() {
+ return (addresses != null) ? addresses.next() : null;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException(
+ "remove not supported by this iterator");
+ }
+ };
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.camel.CamelContextAware#getCamelContext()
+ */
+ public CamelContext getCamelContext() {
+ return context;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.apache.camel.CamelContextAware#setCamelContext(org.apache.camel.
+ * CamelContext)
+ */
+ public void setCamelContext(CamelContext context) {
+ this.context = context;
+ }
+
+ /**
+ * RouteBuilder which builds the Camel Route for the whole RemoteDelivery
+ * Process.
+ *
+ *
+ *
+ */
+ private final class RemoteDeliveryRouteBuilder extends RouteBuilder {
+
+ @Override
+ public void configure() throws Exception {
+ from(getOutgoingQueueEndpoint(outgoingQueue))
+ .inOnly()
+ .transacted()
+ .process(new DeliveryProcessor())
+ .choice()
+ .when(header(JamesCamelConstants.JAMES_RETRY_DELIVERY).isNotNull()).to(getOutgoingRetryQueueEndpoint(outgoingRetryQueue)).otherwise().stop().end();
+
+ fromF("pollingjms:queue?delay=30000&consumer.endpointUri=%s", getOutgoingRetryQueueEndpoint(outgoingRetryQueue))
+ .inOnly()
+ .transacted()
+ .process(new DeliveryProcessor())
+ .choice()
+ .when(header(JamesCamelConstants.JAMES_RETRY_DELIVERY).isNotNull()).toF(getOutgoingRetryQueueEndpoint(outgoingRetryQueue)).otherwise().stop().end();
+ }
+
+ }
+
+ /**
+ * Return the Endpoint for the outgoing queue with the given name
+ *
+ * @param outgoingQueue
+ * @return endpointUri
+ */
+ protected abstract String getOutgoingQueueEndpoint(String outgoingQueue);
+
+
+ /**
+ * Return the Endpoint for the outgoing retry queue with the given name
+ *
+ * @param outgoingRetryQueue
+ * @return endpointUri
+ */
+ protected abstract String getOutgoingRetryQueueEndpoint(String outgoingRetryQueue);
+
+
+}
Added: james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/ActiveMQRemoteDelivery.java
URL: http://svn.apache.org/viewvc/james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/ActiveMQRemoteDelivery.java?rev=921519&view=auto
==============================================================================
--- james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/ActiveMQRemoteDelivery.java (added)
+++ james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/ActiveMQRemoteDelivery.java Wed Mar 10 19:13:36 2010
@@ -0,0 +1,39 @@
+/****************************************************************
+ * 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 implementation which use ActiveMQ for the outgoing spooling / queue
+ *
+ *
+ */
+public class ActiveMQRemoteDelivery extends AbstractRemoteDelivery{
+
+ @Override
+ protected String getOutgoingQueueEndpoint(String outgoingQueue) {
+ return "activemq:queue:"+ outgoingQueue;
+ }
+
+ @Override
+ protected String getOutgoingRetryQueueEndpoint(String outgoingRetryQueue) {
+ return "activemq:queue:"+ outgoingRetryQueue;
+
+ }
+
+}
Added: james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/JMSRemoteDelivery.java
URL: http://svn.apache.org/viewvc/james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/JMSRemoteDelivery.java?rev=921519&view=auto
==============================================================================
--- james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/JMSRemoteDelivery.java (added)
+++ james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/JMSRemoteDelivery.java Wed Mar 10 19:13:36 2010
@@ -0,0 +1,41 @@
+/****************************************************************
+ * 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 implementation which use JMS for the outgoing spooling / queue.
+ *
+ * If you use ActiveMQ you should use {@link ActiveMQRemoteDelivery}
+ *
+ *
+ */
+public class JMSRemoteDelivery extends AbstractRemoteDelivery{
+
+ @Override
+ protected String getOutgoingQueueEndpoint(String outgoingQueue) {
+ return "jms:queue:"+ outgoingQueue;
+ }
+
+ @Override
+ protected String getOutgoingRetryQueueEndpoint(String outgoingRetryQueue) {
+ return "jms:queue:"+ outgoingRetryQueue;
+
+ }
+
+}
Added: james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/RemoteDeliverySocketFactory.java
URL: http://svn.apache.org/viewvc/james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/RemoteDeliverySocketFactory.java?rev=921519&view=auto
==============================================================================
--- james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/RemoteDeliverySocketFactory.java (added)
+++ james/server/trunk/spoolmanager/src/main/java/org/apache/james/transport/mailets/RemoteDeliverySocketFactory.java Wed Mar 10 19:13:36 2010
@@ -0,0 +1,137 @@
+/****************************************************************
+ * 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 javax.net.SocketFactory;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+/**
+ * It is used by RemoteDelivery in order to make possible to bind the client
+ * socket to a specific ip address.
+ *
+ * This is not a nice solution because the ip address must be shared by all
+ * RemoteDelivery instances. It would be better to modify JavaMail
+ * (current version 1.3) to support a corresonding property, e.g.
+ * mail.smtp.bindAdress.
+ *
+ * This used to not extend javax.net.SocketFactory descendant, because
+ * 1. it was not necessary because JavaMail 1.2 uses reflection when accessing
+ * this class;
+ * 2. it was not desirable because it would require java 1.4.
+ *
+ * But since James 2.3.0a1:
+ * 1. we require Java 1.4 so the dependency on SocketFactory is
+ * not really an issue;
+ * 2. Javamail 1.4 cast the object returned by getDefault to SocketFactory and
+ * fails to create the socket if we don't extend SocketFactory.
+ *
+ * Note: Javamail 1.4 should correctly support mail.smtp.localaddr so we could
+ * probably get rid of this class and simply add that property to the Session.
+ */
+public class RemoteDeliverySocketFactory extends SocketFactory {
+
+ /**
+ * @param addr the ip address or host name the delivery socket will bind to
+ */
+ static void setBindAdress(String addr) throws UnknownHostException {
+ if (addr == null) bindAddress = null;
+ else bindAddress = InetAddress.getByName(addr);
+ }
+
+ /**
+ * the same as the similarly named javax.net.SocketFactory operation.
+ */
+ public static SocketFactory getDefault() {
+ return new RemoteDeliverySocketFactory();
+ }
+
+ /**
+ * the same as the similarly named javax.net.SocketFactory operation.
+ * Just to be safe, it is not used by JavaMail 1.3.
+ * This is the only method used by JavaMail 1.4.
+ */
+ public Socket createSocket() throws IOException {
+ Socket s = new Socket();
+ s.bind(new InetSocketAddress(bindAddress, 0));
+ return s;
+ }
+
+ /**
+ * the same as the similarly named javax.net.SocketFactory operation.
+ * This is the one which is used by JavaMail 1.3.
+ * This is not used by JavaMail 1.4.
+ */
+ public Socket createSocket(String host, int port)
+ throws IOException, UnknownHostException {
+ return new Socket(host, port, bindAddress, 0);
+ }
+
+ /**
+ * the same as the similarly named javax.net.SocketFactory operation.
+ * Just to be safe, it is not used by JavaMail 1.3.
+ * This is not used by JavaMail 1.4.
+ */
+ public Socket createSocket(String host,
+ int port,
+ InetAddress clientHost,
+ int clientPort)
+ throws IOException,
+ UnknownHostException {
+ return new Socket(host, port,
+ clientHost == null ? bindAddress : clientHost, clientPort);
+ }
+
+ /**
+ * the same as the similarly named javax.net.SocketFactory operation.
+ * Just to be safe, it is not used by JavaMail 1.3.
+ * This is not used by JavaMail 1.4.
+ */
+ public Socket createSocket(InetAddress host, int port) throws IOException {
+ return new Socket(host, port, bindAddress, 0);
+ }
+
+ /**
+ * the same as the similarly named javax.net.SocketFactory operation.
+ * Just to be safe, it is not used by JavaMail 1.3.
+ * This is not used by JavaMail 1.4.
+ */
+ public Socket createSocket(InetAddress address,
+ int port,
+ InetAddress clientAddress,
+ int clientPort)
+ throws IOException {
+ return new Socket(address, port,
+ clientAddress == null ? bindAddress : clientAddress,
+ clientPort);
+ }
+
+ /**
+ * it should be set by setBindAdress(). Null means the socket is bind to
+ * the default address.
+ */
+ private static InetAddress bindAddress;
+}
Copied: james/server/trunk/spoolmanager/src/test/java/org/apache/james/transport/mailets/RemoteDeliveryTest.java (from r919816, james/server/trunk/mailets/src/test/java/org/apache/james/transport/mailets/RemoteDeliveryTest.java)
URL: http://svn.apache.org/viewvc/james/server/trunk/spoolmanager/src/test/java/org/apache/james/transport/mailets/RemoteDeliveryTest.java?p2=james/server/trunk/spoolmanager/src/test/java/org/apache/james/transport/mailets/RemoteDeliveryTest.java&p1=james/server/trunk/mailets/src/test/java/org/apache/james/transport/mailets/RemoteDeliveryTest.java&r1=919816&r2=921519&rev=921519&view=diff
==============================================================================
--- james/server/trunk/mailets/src/test/java/org/apache/james/transport/mailets/RemoteDeliveryTest.java (original)
+++ james/server/trunk/spoolmanager/src/test/java/org/apache/james/transport/mailets/RemoteDeliveryTest.java Wed Mar 10 19:13:36 2010
@@ -36,6 +36,6 @@ public class RemoteDeliveryTest extends
}
public Properties getParameters() {
- return getStandardParameters();
+ return null;//getStandardParameters();
}
}
Copied: james/server/trunk/spoolmanager/src/test/java/org/apache/james/transport/mailets/StandardRemoteDeliveryTestable.java (from r919816, james/server/trunk/mailets/src/test/java/org/apache/james/transport/mailets/StandardRemoteDeliveryTestable.java)
URL: http://svn.apache.org/viewvc/james/server/trunk/spoolmanager/src/test/java/org/apache/james/transport/mailets/StandardRemoteDeliveryTestable.java?p2=james/server/trunk/spoolmanager/src/test/java/org/apache/james/transport/mailets/StandardRemoteDeliveryTestable.java&p1=james/server/trunk/mailets/src/test/java/org/apache/james/transport/mailets/StandardRemoteDeliveryTestable.java&r1=919816&r2=921519&rev=921519&view=diff
==============================================================================
--- james/server/trunk/mailets/src/test/java/org/apache/james/transport/mailets/StandardRemoteDeliveryTestable.java (original)
+++ james/server/trunk/spoolmanager/src/test/java/org/apache/james/transport/mailets/StandardRemoteDeliveryTestable.java Wed Mar 10 19:13:36 2010
@@ -19,8 +19,7 @@
package org.apache.james.transport.mailets;
-import org.apache.james.api.dnsservice.DNSService;
-import org.apache.james.services.store.Store;
+
import org.apache.james.transport.remotedeliverytester.RemoteDeliveryTestable;
import org.apache.james.transport.remotedeliverytester.Tester;
@@ -31,7 +30,7 @@ import java.util.Properties;
/**
* RemoteDelivery extension to publish test-aware interfaces
*/
-public class StandardRemoteDeliveryTestable extends RemoteDelivery implements RemoteDeliveryTestable {
+public class StandardRemoteDeliveryTestable extends ActiveMQRemoteDelivery implements RemoteDeliveryTestable {
public boolean logEnabled = true;
private Tester tester;
@@ -42,7 +41,8 @@ public class StandardRemoteDeliveryTesta
protected Session obtainSession(Properties props) {
if (tester != null) return tester.obtainSession(props);
- else return super.obtainSession(props);
+ //else return super.obtainSession(props);
+ return null;
}
public void log(String message, Throwable t) {
@@ -53,11 +53,5 @@ public class StandardRemoteDeliveryTesta
if (logEnabled) super.log(message);
}
- public void setDNSService(DNSService dnsServer) {
- super.setDNSService(dnsServer);
- }
-
- public void setStore(Store mailStore) {
- super.setStore(mailStore);
- }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org