001    package railo.runtime.net.mail;
002    
003    import railo.commons.lang.StringUtil;
004    import railo.runtime.exp.PageException;
005    import railo.runtime.op.Caster;
006    import railo.runtime.op.Decision;
007    import railo.runtime.type.Array;
008    import railo.runtime.type.Struct;
009    import railo.runtime.type.util.ListUtil;
010    
011    import java.io.UnsupportedEncodingException;
012    import java.net.IDN;
013    import java.util.ArrayList;
014    import java.util.Iterator;
015    
016    import javax.mail.internet.AddressException;
017    import javax.mail.internet.InternetAddress;
018    import javax.mail.internet.MimeUtility;
019    
020    public final class MailUtil {
021    
022            public static String encode(String text,String encoding) throws UnsupportedEncodingException {
023                    //print.ln(StringUtil.changeCharset(text,encoding));
024                    return MimeUtility.encodeText(text,encoding,"Q");
025            }
026            
027            public static String decode(String text) throws UnsupportedEncodingException {
028                    return MimeUtility.decodeText(text);
029            }
030    
031    
032    
033        public static InternetAddress toInternetAddress(Object emails) throws MailException, UnsupportedEncodingException, PageException {
034    
035            if ( emails instanceof String )
036                return parseEmail( emails );
037    
038            InternetAddress[] addresses = toInternetAddresses( emails );
039            if ( addresses != null && addresses.length > 0 )
040                return addresses[0];
041    
042            return null;
043        }
044    
045    
046        public static InternetAddress[] toInternetAddresses(Object emails) throws MailException, UnsupportedEncodingException, PageException {
047    
048            if (emails instanceof String )
049                return fromList((String) emails);
050            
051            else if ( Decision.isArray(emails) ) 
052                return fromArray(Caster.toArray(emails));
053            
054            else if ( Decision.isStruct(emails) ) 
055                return new InternetAddress[]{ fromStruct(Caster.toStruct(emails)) };
056            
057            else
058                throw new MailException("e-mail defintions must be one of the following types [string,array,struct], not ["+emails.getClass().getName()+"]");
059        }
060    
061    
062        private static InternetAddress[] fromArray(Array array) throws MailException, PageException, UnsupportedEncodingException {
063    
064            Iterator it = array.valueIterator();
065            Object el;
066            ArrayList<InternetAddress> pairs = new ArrayList();
067    
068            while(it.hasNext()){
069                el=it.next();
070                if ( Decision.isStruct( el ) ) {
071    
072                    pairs.add( fromStruct(Caster.toStruct(el)) );
073                }
074                else {
075    
076                    InternetAddress addr = parseEmail( Caster.toString(el) );
077                    if ( addr != null )
078                        pairs.add( addr );
079                }
080            }
081    
082            return pairs.toArray( new InternetAddress[ pairs.size() ] );
083        }
084    
085    
086        private static InternetAddress fromStruct( Struct sct ) throws MailException, UnsupportedEncodingException {
087    
088            String name = Caster.toString(sct.get("label",null),null);
089            if ( name == null )
090                name=Caster.toString(sct.get("name",null),null);
091    
092            String email = Caster.toString(sct.get("email",null),null);
093            if ( email == null )
094                email = Caster.toString(sct.get("e-mail",null),null);
095            if ( email == null )
096                email = Caster.toString(sct.get("mail",null),null);
097    
098            if( StringUtil.isEmpty(email) )
099                throw new MailException("missing e-mail definition in struct");
100    
101            if(name==null) name="";
102    
103            return new InternetAddress( email, name );
104        }
105    
106    
107        private static InternetAddress[] fromList( String strEmails ) {
108    
109            if ( StringUtil.isEmpty( strEmails, true ) )
110                return new InternetAddress[0];
111    
112            Array raw = ListUtil.listWithQuotesToArray(strEmails, ",;", "\"");
113    
114            Iterator<Object> it = raw.valueIterator();
115            ArrayList<InternetAddress> al = new ArrayList();
116    
117            while( it.hasNext() ) {
118    
119                InternetAddress addr = parseEmail( it.next() );
120    
121                if( addr != null )
122                    al.add( addr );
123            }
124    
125            return al.toArray( new InternetAddress[ al.size() ] );
126        }
127    
128    
129        /**
130         * returns true if the passed value is a in valid email address format
131         * @param value
132         * @return
133         */
134        public static boolean isValidEmail( Object value ) {
135    
136            return ( parseEmail( value ) != null );
137        }
138    
139    
140        /**
141         * returns an InternetAddress object or null if the parsing fails.  to be be used in multiple places.
142         * @param value
143         * @return
144         */
145        public static InternetAddress parseEmail( Object value ) {
146    
147            String str = Caster.toString( value, "" );
148    
149            if ( str.indexOf( '@' ) > -1 ) {
150    
151                try {
152    
153                    InternetAddress addr = new InternetAddress( str );
154                    fixIDN( addr );
155                    return addr;
156                }
157                catch ( AddressException ex ) {}
158            }
159    
160            return null;
161        }
162    
163    
164        /**
165         * converts IDN to ASCII if needed
166         * @param addr
167         */
168        public static void fixIDN( InternetAddress addr ) {
169    
170            String address = addr.getAddress();
171            int pos = address.indexOf( '@' );
172    
173            if ( pos > 0 && pos < address.length() - 1 ) {
174    
175                String domain = address.substring( pos + 1 );
176    
177                if ( !StringUtil.isAscii( domain ) ) {
178    
179                    domain = IDN.toASCII( domain );
180                    addr.setAddress( address.substring( 0, pos ) + "@" + domain );
181                }
182            }
183        }
184    
185    }