1197a308e0810c543f7cdbbcd132b3cfb696d664
[org.ibex.mail.git] / src / org / ibex / mail / Address.java
1 // Copyright 2000-2005 the Contributors, as shown in the revision logs.
2 // Licensed under the Apache Public Source License 2.0 ("the License").
3 // You may not use this file except in compliance with the License.
4
5 package org.ibex.mail;
6 import org.ibex.crypto.*;
7 import org.ibex.js.*;
8 import org.ibex.util.*;
9 import org.ibex.mail.protocol.*;
10 import java.util.*;
11 import java.net.*;
12 import java.io.*;
13
14 // FIXME this should be more forgiving
15 public class Address extends JSReflection implements Serializable {
16     public final String user;
17     public final String host;
18     public final String description;
19     public static Address parse(String s) { try { return s==null?null:new Address(s); } catch (Malformed _) { return null; } }
20     public Address(String user, String host, String description) {this.user=user;this.host=host;this.description=description;}
21     public Address(String s0) throws Address.Malformed {
22         boolean good = false;
23         try {
24             String s = s0.trim();
25             if (s.indexOf('<') == -1) {
26                 if (s.indexOf(' ') == -1) {
27                     description = "";
28                 } else {
29                     description = s.substring(s.indexOf(' ')).trim();
30                     s = s.substring(0, s.indexOf(' '));
31                 }
32             } else {
33                 if (s.indexOf('>') == -1) { throw new Malformed("found open-angle-bracket (<) but not close-angle-bracket (>)"); }
34                 description = s.substring(0, s.indexOf('<')) + s.substring(s.indexOf('>') + 1);
35                 s = s.substring(s.indexOf('<') + 1, s.indexOf('>'));
36             }
37             if (s.trim().length() == 0) {
38                 user = null;
39                 host = null;
40                 good = true;
41             } else if (s.indexOf('@') == -1) { throw new Malformed("no @-sign in email address \""+s0+"\"");
42             } else {
43                 user = s.substring(0, s.indexOf('@'));
44                 host = s.substring(s.indexOf('@')+1);
45                 good = true;
46             }
47         } finally {
48             if (!good) Log.error(Address.class, "problem parsing: \""+s0+"\"");
49         }
50     }
51     public String toString() { return (user == null && host == null) ? "" : (user + "@" + host); }
52     public String coerceToString() { return toString(); }
53     public String toString(boolean desc) {
54         return desc && description != null && description.length() > 0 ? (description+" <" + toString() + ">") : toString(); }
55     public static class Malformed extends Message.Malformed { public Malformed(String s) { super(s); } }
56
57     /** in case of flaky DNS */
58     private static HashSet<String> local = new HashSet<String>();
59     public boolean isLocal() {
60         synchronized(local) {
61             if (local.contains(host)) return true;
62             InetAddress[] mx = SMTP.getMailExchangerIPs(host);
63             for(int i=0; i<mx.length; i++) {
64                 try { if (NetworkInterface.getByInetAddress(mx[i]) != null) {
65                     local.add(host);
66                     return true;
67                 } } catch (Exception e) { /* DELIBERATE */ }
68             }
69         }
70         Log.warn(this, "returning false for " + this + ".isLocal()");
71         return false;
72     }
73
74     public static Address[] list(String spec) {
75         if (spec == null) return new Address[] { };
76         StringTokenizer st = new StringTokenizer((String)spec, ",");
77         Address[] ret = new Address[st.countTokens()];
78         for(int i=0; i<ret.length; i++) {
79             String s = st.nextToken();
80             ret[i] = Address.parse(s);
81             if (ret[i] == null) Log.warn(Address.class, "Warning: address " + s + " is unparseable");
82         }
83         return ret;
84     }
85 }