📄 remotedelivery.java
字号:
try { if (isDebug) { StringBuffer logMessageBuffer = new StringBuffer(128) .append(Thread.currentThread().getName()) .append(" will process mail ") .append(key); log(logMessageBuffer.toString()); } if (deliver(mail, session)) { //Message was successfully delivered/fully failed... delete it ContainerUtil.dispose(mail); outgoing.remove(key); } else { //Something happened that will delay delivery. Store any updates outgoing.store(mail); ContainerUtil.dispose(mail); // This is an update, we have to unlock and notify or this mail // is kept locked by this thread outgoing.unlock(key); // We do not notify because we updated an already existing mail // and we are now free to handle more mails. // Furthermore this mail should not be processed now because we // have a retry time scheduling. } //Clear the object handle to make sure it recycles this object. mail = null; } catch (Exception e) { // Prevent unexpected exceptions from causing looping by removing // message from outgoing. // DO NOT CHNANGE THIS to catch Error! For example, if there were an OutOfMemory condition // caused because something else in the server was abusing memory, we would not want to // start purging the outgoing spool! ContainerUtil.dispose(mail); outgoing.remove(key); throw e; } } catch (Throwable e) { if (!destroyed) log("Exception caught in RemoteDelivery.run()", e); } } } finally { // Restore the thread state to non-interrupted. Thread.interrupted(); } } /** * @param list holding Delay objects * @return the total attempts for all delays **/ private int calcTotalAttempts (ArrayList list) { int sum = 0; Iterator i = list.iterator(); while (i.hasNext()) { Delay 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 list) { long[] delays = new long [calcTotalAttempts(list)]; Iterator i = list.iterator(); int idx = 0; while (i.hasNext()) { Delay 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 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) (default = msec) * The constructor multiplies the delaytime by the relevant multiplier for the unit, * so the delayTime instance variable is always in msec. * @param init_string the string to initialize this Delay object from **/ public Delay (String init_string) throws MessagingException { String unit = "msec"; //default unit if (delayTimeMatcher.matches (init_string, 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 attempt_match = res.group(1); //strip the * and whitespace attempt_match = attempt_match.substring (0,attempt_match.length()-1).trim(); attempts = Integer.parseInt (attempt_match); } delayTime = Long.parseLong (res.group(2)); if (!res.group(3).equals ("")) { //we have a unit unit = res.group(3).toLowerCase(Locale.US); } } else { throw new MessagingException(init_string+" does not match "+PATTERN_STRING); } if (MULTIPLIERS.get (unit)!=null) { int multiplier = ((Integer)MULTIPLIERS.get (unit)).intValue(); delayTime *= multiplier; } else { throw new MessagingException("Unknown unit: "+unit); } } /** * This constructor makes a default Delay object, ie. 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 () { StringBuffer buf = new StringBuffer(15); buf.append (getAttempts ()); buf.append ('*'); buf.append (getDelayTime()); buf.append ("msec"); return buf.toString(); } } /* * 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 getGatewaySMTPHostAddresses(final Collection gatewayServers) { return new Iterator() { private Iterator gateways = gatewayServers.iterator(); private Iterator 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 = org.apache.james.dnsserver.DNSServer.getAllByName(nextGateway); addresses = new Iterator() { private InetAddress[] ipAddresses = ips; int i = 0; public boolean hasNext() { return i < ipAddresses.length; } public Object 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 Object next() { return (addresses != null) ? addresses.next() : null; } public void remove() { throw new UnsupportedOperationException ("remove not supported by this iterator"); } }; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -