X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fibex%2Fmail%2FSMTP.java;h=db5da88316c902bfdb151e79b9160d29408b05e6;hb=558689ac3d54223a7226aee1159c0dc7e16deb3c;hp=64677a0da11aaadefee509f2b6e36c8cd77b8e49;hpb=851c38287e9874500c8268439fa411af27897e52;p=org.ibex.mail.git diff --git a/src/org/ibex/mail/SMTP.java b/src/org/ibex/mail/SMTP.java index 64677a0..db5da88 100644 --- a/src/org/ibex/mail/SMTP.java +++ b/src/org/ibex/mail/SMTP.java @@ -11,8 +11,6 @@ import java.net.*; import java.io.*; import java.util.*; import java.text.*; -import javax.naming.*; -import javax.naming.directory.*; // FIXME: inbound throttling/ratelimiting @@ -53,6 +51,8 @@ public class SMTP { public static final int GRAYLIST_MINWAIT = 1000 * 60 * 60; // one hour public static final int GRAYLIST_MAXWAIT = 1000 * 60 * 60 * 24 * 5; // five days + public static final int RETRY_TIME = 1000 * 60 * 30; + public static final Graylist graylist; public static final Whitelist whitelist; static { @@ -197,7 +197,8 @@ public class SMTP { command = command.substring(10).trim(); from = command.equals("<>") ? null : new Address(command); conn.println("250 " + from + " is syntactically correct"); - // FEATURE: perform SMTP validation on the address, reject if invalid + // Don't perform SAV; discouraged here + // http://blog.fastmail.fm/2007/12/05/sending-email-servers-best-practice/ } else if (c.startsWith("RCPT TO:")) { // some clients are broken and put RCPT first; we will tolerate this command = command.substring(8).trim(); @@ -332,7 +333,7 @@ public class SMTP { Log.warn(SMTP.Outgoing.class, "aieeee, null envelopeTo: " + m.summary()); return false; } - InetAddress[] mx = getMailExchangerIPs(m.envelopeTo.host); + InetAddress[] mx = DNSUtil.getMailExchangerIPs(m.envelopeTo.host); if (mx.length == 0) { if (!noBounces) { enqueue(m.bounce("could not resolve " + m.envelopeTo.host)); @@ -369,14 +370,23 @@ public class SMTP { Connection conn = null; try { conn = new Connection(new Socket(mx, 25), InetAddress.getLocalHost().getHostName()); + InetAddress localAddress = conn.getSocket().getLocalAddress(); + String reverse = DNSUtil.reverseLookup(localAddress); + Log.info(SMTP.Outgoing.class, + "outbound connection to " + mx + " uses " + localAddress + " [reverse: " + reverse + "]"); + InetAddress relookup = InetAddress.getByName(reverse); + if (!relookup.equals(localAddress)) + Log.error(SMTP.Outgoing.class, + "Warning: local machine fails forward-confirmed-reverse; " + + reverse + " resolves to " + localAddress); conn.setNewline("\r\n"); conn.setTimeout(60 * 1000); check(conn.readln(), conn); // banner try { - conn.println("EHLO " + conn.vhost); + conn.println("EHLO " + reverse); check(conn.readln(), conn); } catch (SMTPException smtpe) { - conn.println("HELO " + conn.vhost); + conn.println("HELO " + reverse); check(conn.readln(), conn); } String envelopeFrom = m.envelopeFrom==null ? "" : m.envelopeFrom.toString(); @@ -444,6 +454,8 @@ public class SMTP { private int serial = serials++; private Mailbox.Iterator it; + private static Map nextTry = Collections.synchronizedMap(new HashMap()); + public Outgoing() { synchronized(Outgoing.class) { threads.add(this); @@ -468,7 +480,12 @@ public class SMTP { } if (!good) break; try { - if (attempt(it.cur())) it.delete(); + String messageid = it.cur().messageid; + if (nextTry.get(messageid) == null || System.currentTimeMillis() > nextTry.get(messageid)) { + boolean ok = attempt(it.cur()); + if (ok) it.delete(); + else nextTry.put(messageid, System.currentTimeMillis() + RETRY_TIME); + } } catch (Exception e) { Log.error(SMTP.Outgoing.class, e); } @@ -497,42 +514,4 @@ public class SMTP { } } - public static InetAddress[] getMailExchangerIPs(String hostName) { - InetAddress[] ret; - try { - Hashtable env = new Hashtable(); - env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory"); - DirContext ictx = new InitialDirContext(env); - Attributes attrs = ictx.getAttributes(hostName, new String[] { "MX" }); - Attribute attr = attrs.get("MX"); - if (attr == null) { - ret = new InetAddress[1]; - try { - ret[0] = InetAddress.getByName(hostName); - if (ret[0].equals(IP.getIP(127,0,0,1)) || ret[0].isLoopbackAddress()) throw new UnknownHostException(); - return ret; - } catch (UnknownHostException uhe) { - Log.warn(SMTP.class, "no MX hosts or A record for " + hostName); - return new InetAddress[0]; - } - } else { - ret = new InetAddress[attr.size()]; - NamingEnumeration ne = attr.getAll(); - for(int i=0; ne.hasMore();) { - String mx = (String)ne.next(); - // FIXME we should be sorting here - mx = mx.substring(mx.indexOf(" ") + 1); - if (mx.charAt(mx.length() - 1) == '.') mx = mx.substring(0, mx.length() - 1); - InetAddress ia = InetAddress.getByName(mx); - if (ia.equals(IP.getIP(127,0,0,1)) || ia.isLoopbackAddress()) continue; - ret[i++] = ia; - } - } - } catch (Exception e) { - Log.warn(SMTP.class, "couldn't find MX host for " + hostName + " due to"); - Log.warn(SMTP.class, e); - return new InetAddress[0]; - } - return ret; - } }