pretty much working
authoradam <adam@megacz.com>
Sat, 8 May 2004 07:58:23 +0000 (07:58 +0000)
committeradam <adam@megacz.com>
Sat, 8 May 2004 07:58:23 +0000 (07:58 +0000)
darcs-hash:20040508075823-5007d-60116e47fa0248d791988e50fdde37c82ba0bc9c.gz

doc/README
mail.jar
src/org/ibex/mail/Message.java
src/org/ibex/mail/protocol/SMTP.java
src/org/ibex/mail/target/FileSystem.java
src/org/ibex/mail/target/Script.java

index e26737a..df2113d 100644 (file)
@@ -50,13 +50,13 @@ The following properties are available from ibex.mail:
                     dcc
                     vipul
                     spamAssassin
+                    vacation
 
              target.
                     dead            -- drops the message on the floor; it vanishes without a trace
                     dir[path]       -- uses the directory [path] as a naive file-based storage area
                     send            -- sends the outgoing message via smtp
                     bounce(message) -- bounces the message
-                    vacation
                     darcs(repo)
                     procmail(procmailrc)
                     lmtp(path)
index 418b89d..4d7e3e2 100644 (file)
Binary files a/mail.jar and b/mail.jar differ
index 85ab516..0e0b13a 100644 (file)
@@ -42,6 +42,8 @@ public class Message extends JSReflection {
     public void dump(OutputStream os) throws IOException {
         Writer w = new OutputStreamWriter(os);
         w.write(allHeaders);
+        w.write("X-IbexMail-EnvelopeFrom: " + envelopeFrom + "\r\n");
+        w.write("X-IbexMail-EnvelopeTo: "); for(int i=0; i<envelopeTo.length; i++) w.write(envelopeTo[i] + " "); w.write("\r\n");
         w.write("\r\n");
         w.write(body);
         w.flush();
@@ -117,10 +119,10 @@ public class Message extends JSReflection {
             }
             if (s.indexOf(':') == -1) throw new Malformed("Header line does not contain colon: " + s);
             key = s.substring(0, s.indexOf(':'));
-            for(int i=0; i<s.length(); i++)
-                if (s.charAt(i) < 33 || s.charAt(i) > 126)
-                    throw new Malformed("Header key contains invalid character \"" + s.charAt(i) + "\"");
-            String val = s.substring(0, s.indexOf(':'));
+            for(int i=0; i<key.length(); i++)
+                if (key.charAt(i) < 33 || key.charAt(i) > 126)
+                    throw new Malformed("Header key \""+key+"\" contains invalid character \"" + key.charAt(i) + "\"");
+            String val = s.substring(s.indexOf(':') + 1).trim();
             while(Character.isSpace(val.charAt(0))) val = val.substring(1);
             if (key.startsWith("Resent-")) {
                 if (key.startsWith("Resent-From")) resent.addElement(new Hashtable());
@@ -135,9 +137,9 @@ public class Message extends JSReflection {
         }
 
         this.date      = (Date)headers.get("Date");
-        this.to        = new Address((String)headers.get("To"));
-        this.from      = new Address((String)headers.get("From"));
-        this.replyto   = new Address((String)headers.get("Reply-To"));
+        this.to        = new Address((String)headers.get("To"));  // FIXME what if null?
+        this.from      = headers.get("From") == null     ? envelopeFrom : new Address((String)headers.get("From"));
+        this.replyto   = headers.get("Reply-To") == null ? null : new Address((String)headers.get("Reply-To"));
         this.subject   = (String)headers.get("Subject");
         this.messageid = (String)headers.get("Message-Id");
         if (headers.get("Cc") != null) {
index b764b7e..dad7a06 100644 (file)
@@ -155,25 +155,18 @@ public class SMTP extends MessageProtocol {
             try {
                 conn.setSoTimeout(5 * 60 * 1000);
                 StringBuffer logMessage = new StringBuffer();
-                String conversationId = getConversation();
-                Log.setThreadAnnotation("[conversation/" + conversationId + "] ");
+                String cid = getConversation();
+                Log.setThreadAnnotation("[conversation " + cid + "] ");
                 InetSocketAddress remote = (InetSocketAddress)conn.getRemoteSocketAddress();
-                Log.info(this, "connection from " + remote.getHostName() + ":" + remote.getPort() +
-                         " (" + remote.getAddress() + ")");
-                PrintWriter logf =
-                    new PrintWriter(new OutputStreamWriter(new FileOutputStream(convdir + File.separatorChar + conversationId)));
+                Log.info(this, "connection from "+remote.getHostName()+":"+remote.getPort()+" ("+remote.getAddress()+")");
+                PrintWriter logf = new PrintWriter(new OutputStreamWriter(new FileOutputStream(convdir+File.separatorChar+cid)));
                 try {
                     return handleRequest(new LoggedLineReader(new InputStreamReader(conn.getInputStream()), logf),
                                          new LoggedPrintWriter(new OutputStreamWriter(conn.getOutputStream()), logf));
-                } catch(Throwable t) {
-                    Log.warn(this, t);
-                } finally {
-                    logf.close();
-                    Log.setThreadAnnotation("");
+                } catch(Throwable t) { Log.warn(this, t);
+                } finally {            logf.close(); Log.setThreadAnnotation("");
                 }
-            } catch (Exception e) {
-                Log.error(this, e);
-            }
+            } catch (Exception e) { Log.error(this, e); }
             return false;
         }
         
@@ -294,7 +287,13 @@ public class SMTP extends MessageProtocol {
             } else {
                 ret = new InetAddress[attr.size()];
                 NamingEnumeration ne = attr.getAll();
-                for(int i=0; ne.hasMore(); i++) ret[i] = (InetAddress)ne.next();
+                for(int i=0; ne.hasMore(); i++) {
+                    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);
+                }
             }
         } catch (Exception e) {
             Log.warn(SMTP.class, "couldn't find MX host for " + hostName + " due to");
index ab277a2..8be7d8f 100644 (file)
@@ -8,7 +8,7 @@ import java.util.*;
 import java.text.*;
 
 // FIXME: appallingly inefficient
-public class FileSystem {
+public class FileSystem extends Target {
 
     private static final String STORAGE_ROOT =
         System.getProperty("ibex.mail.root", File.separatorChar + "var" + File.separatorChar + "org.ibex.mail");
@@ -23,6 +23,7 @@ public class FileSystem {
         }
     }
 
+    public void accept(Message m) throws IOException { add(m); }
     public FileSystem slash(String name) throws IOException {
         throw new Error(this.getClass().getName() + " does not support the slash() method"); }
     public int[] list() { throw new Error(this.getClass().getName() + " does not support the list() method"); }
@@ -35,6 +36,28 @@ public class FileSystem {
     public Message[] query(int maxResults) {
         throw new Error(this.getClass().getName() + " does not support the query() method"); }
 
+    public static class Mailbox extends FileSystem {
+        String user;
+        private static Hashtable cache = new Hashtable();
+        public static Mailbox getForUser(String user) {
+            Mailbox ret = (Mailbox)cache.get(user);
+            if (ret == null) ret = new Mailbox(user);
+            return ret;
+        }
+        Mailbox(String user) { this.user = user; }
+        public FileSystem slash(String name) throws IOException {
+            throw new Error(this.getClass().getName() + " does not support the slash() method"); }
+        public synchronized int add(Message message) throws IOException {
+            FileOutputStream fos = new FileOutputStream("/var/mail/" + user, true);
+            PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos));
+            pw.println("From " + message.envelopeFrom);
+            pw.flush();
+            message.dump(fos);
+            fos.close();
+            return -1;
+        }
+    }
+
     /** a fast-write, slow-read place to stash all messages we touch -- in case of a major f*ckup */
     public static class Transcript extends FileSystem {
         private String path;
index 65746b3..4e06040 100644 (file)
@@ -55,6 +55,15 @@ public class Script extends Target {
     // FIXME: this should extend org.ibex.core.Ibex
     public static class ScriptEnv extends JS {
 
+        private static PropertyFile prefs;
+        static {
+            try {
+                prefs = new PropertyFile(new File("/etc/org.ibex.mail.properties"));
+            } catch (IOException e) {
+                Log.error(ScriptEnv.class, e);
+            }
+        }
+
         /** lets us put multi-level get/put/call keys all in the same method */
         private class Sub extends JS {
             String key;
@@ -80,6 +89,10 @@ public class Script extends Target {
             if (name.equals("log.info")) { return METHOD; }
             if (name.equals("log.warn")) { return METHOD; }
             if (name.equals("log.error")) { return METHOD; }
+            if (name.equals("mail")) { return getSub("mail"); }
+            if (name.equals("mail.my")) { return getSub("mail.my"); }
+            if (name.equals("mail.my.prefs")) { return prefs; }
+            if (name.equals("mail.my.mailbox")) { return FileSystem.Mailbox.getForUser("megacz"); }
             return super.get(name);
         }