better error handling
authoradam <adam@megacz.com>
Tue, 17 Jan 2006 03:48:29 +0000 (03:48 +0000)
committeradam <adam@megacz.com>
Tue, 17 Jan 2006 03:48:29 +0000 (03:48 +0000)
darcs-hash:20060117034829-5007d-301897ede7f0d78bd46e4becbd55295141f1731b.gz

src/org/ibex/mail/protocol/SMTP.java

index af39827..d03c24e 100644 (file)
@@ -6,6 +6,7 @@ package org.ibex.mail.protocol;
 import org.ibex.mail.*;
 import org.ibex.mail.target.*;
 import org.ibex.util.*;
+import org.ibex.net.*;
 import org.ibex.io.*;
 import java.net.*;
 import java.io.*;
@@ -39,8 +40,13 @@ public class SMTP {
         int code;
         String message;
         public SMTPException(String s) {
-            code = Integer.parseInt(s.substring(0, s.indexOf(' ')));
-            message = s.substring(s.indexOf(' ')+1);
+            try {
+                code = Integer.parseInt(s.substring(0, s.indexOf(' ')));
+                message = s.substring(s.indexOf(' ')+1);
+            } catch (NumberFormatException nfe) {
+                code = -1;
+                message = s;
+            }
         }
         public String toString() { return "SMTP " + code + ": " + message; }
         public String getMessage() { return toString(); }
@@ -89,8 +95,10 @@ public class SMTP {
                         conn.println("250 " + addr + " is on this machine; I will deliver it");
                     } else if (conn.getRemoteAddress().isLoopbackAddress())
                         conn.println("250 you are connected locally, so I will let you send");
-                    else { conn.println("551 sorry, " + addr + " is not on this machine"); }
-                    to.addElement(addr);
+                        to.addElement(addr);
+                    } else {
+                        conn.println("551 sorry, " + addr + " is not on this machine");
+                    }
                 } else if (c.startsWith("DATA")) {
                     //if (from == null) { conn.println("503 MAIL FROM command must precede DATA"); continue; }
                     if (to == null) { conn.println("503 RCPT TO command must precede DATA"); continue; }
@@ -100,7 +108,9 @@ public class SMTP {
                         StringBuffer buf = new StringBuffer();
                         buf.append("Received: from " + conn.getRemoteHostname() + " (" + remotehost + ")\r\n");
                         buf.append("          by "+conn.vhost+" ("+SMTP.class.getName()+") with "+(ehlo?"ESMTP":"SMTP") + "\r\n");
-                        buf.append("          for "); for(int i=0; i<to.size(); i++) buf.append(to.elementAt(i) + " ");
+                        buf.append("          for ");
+                        // FIXME: this is leaking BCC addrs
+                        // for(int i=0; i<to.size(); i++) buf.append(to.elementAt(i) + " ");
                         buf.append("; " + dateFormat.format(new Date()) + "\r\n");
                         while(true) {
                             String s = conn.readln();
@@ -176,6 +186,7 @@ public class SMTP {
         }
 
         private static void check(String s, Connection conn) {
+            if (s==null) return;
             while (s.length() > 3 && s.charAt(3) == '-') s = conn.readln();
             if (s.startsWith("4")||s.startsWith("5")) throw new SMTPException(s);
         }
@@ -197,26 +208,37 @@ public class SMTP {
                     check(conn.readln(), conn);
                 }
                 if (m.envelopeFrom==null) {
+                    Log.warn("", "MAIL FROM:<>");
                     conn.println("MAIL FROM:<>");  check(conn.readln(), conn);
                 } else {
-                    conn.println("MAIL FROM:<" + m.envelopeFrom.user + "@" + m.envelopeFrom.host+">");  check(conn.readln(), conn);
+                    Log.warn("", "MAIL FROM:<" + m.envelopeFrom.toString()+">");
+                    conn.println("MAIL FROM:<" + m.envelopeFrom.toString()+">");  check(conn.readln(), conn);
                 }
-                conn.println("RCPT TO:<"   + m.envelopeTo.user + "@" + m.envelopeTo.host+">");      check(conn.readln(), conn);
+                conn.println("RCPT TO:<"   + m.envelopeTo.toString()+">");      check(conn.readln(), conn);
                 conn.println("DATA");                          check(conn.readln(), conn);
-                Stream stream = m.getStream();
-                boolean inheaders = true;
-                while(true) {
-                    String s = stream.readln();
-                    if (s == null) break;
-                    if (s.length() == 0) inheaders = false;
-                    // quash Return-Path; required by RFC2822
-                    if (inheaders && s.toLowerCase().startsWith("Return-Path:")) continue;
+                Headers head = m.headers;
+                head.remove("return-path");
+                head.remove("bcc");
+                Stream stream = head.getStream();
+                for(String s = stream.readln(); s!=null; s=stream.readln()) {
+                    if (s.startsWith(".")) conn.print(".");
+                    //Log.warn("***",s);
+                    conn.println(s);
+                }
+                //Log.warn("***","");
+                conn.println("");
+                stream = m.getBody().getStream();
+                for(String s = stream.readln(); s!=null; s=stream.readln()) {
                     if (s.startsWith(".")) conn.print(".");
+                    //Log.warn("***",s);
                     conn.println(s);
                 }
                 conn.println(".");
-                check(conn.readln(), conn);
-                Log.warn(SMTP.Outgoing.class, "success: " + mx + " accepted " + m.summary());
+                String resp = conn.readln();
+                if (resp == null)
+                    throw new SMTPException("server " + mx + " closed connection without accepting message");
+                check(resp, conn);
+                Log.warn(SMTP.Outgoing.class, "success: " + mx + " accepted " + m.summary() + "\n["+resp+"]");
                 accepted = true;
                 conn.close();
             } catch (Exception e) {
@@ -224,6 +246,7 @@ public class SMTP {
                 Log.warn(SMTP.Outgoing.class, "    unable to send; error=" + e);
                 Log.warn(SMTP.Outgoing.class, "      message: " + m.summary());
                 Log.warn(SMTP.Outgoing.class, e);
+                if (conn != null) Log.warn(SMTP.Outgoing.class, conn.dumpLog());
                 return false;
             } finally {
                 if (conn != null) conn.close();
@@ -281,12 +304,14 @@ public class SMTP {
             } else {
                 ret = new InetAddress[attr.size()];
                 NamingEnumeration ne = attr.getAll();
-                for(int i=0; ne.hasMore(); i++) {
+                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);
-                    ret[i] = InetAddress.getByName(mx);
+                    InetAddress ia = InetAddress.getByName(mx);
+                    if (ia.equals(IP.getIP(127,0,0,1))) continue;
+                    ret[i++] = ia;
                 }
             }
         } catch (Exception e) {