| 
1582
 | 
     1 package goodjava.mail;
 | 
| 
 | 
     2 
 | 
| 
 | 
     3 import java.io.Reader;
 | 
| 
 | 
     4 import java.io.InputStreamReader;
 | 
| 
 | 
     5 import java.io.Writer;
 | 
| 
 | 
     6 import java.io.OutputStreamWriter;
 | 
| 
 | 
     7 import java.io.IOException;
 | 
| 
 | 
     8 import java.net.Socket;
 | 
| 
1583
 | 
     9 import java.util.Map;
 | 
| 
 | 
    10 import goodjava.util.GoodUtils;
 | 
| 
1582
 | 
    11 
 | 
| 
 | 
    12 
 | 
| 
 | 
    13 public class Smtp {
 | 
| 
 | 
    14 	private final char[] buf = new char[1000];
 | 
| 
 | 
    15 	private final Socket socket;
 | 
| 
 | 
    16 	private final Reader reader;
 | 
| 
 | 
    17 	private final Writer writer;
 | 
| 
 | 
    18 	public final String ehlo;
 | 
| 
 | 
    19 
 | 
| 
1829
 | 
    20 	public Smtp(Socket socket,String helo) throws IOException, MailException {
 | 
| 
1582
 | 
    21 		this.socket = socket;
 | 
| 
 | 
    22 		this.reader = new InputStreamReader(socket.getInputStream());
 | 
| 
 | 
    23 		this.writer = new OutputStreamWriter(socket.getOutputStream());
 | 
| 
 | 
    24 		String s = read();
 | 
| 
 | 
    25 		if( !s.startsWith("220") )
 | 
| 
1584
 | 
    26 			throw new MailException(s);
 | 
| 
1829
 | 
    27 		write( "EHLO " + helo + "\r\n" );
 | 
| 
1582
 | 
    28 		ehlo = read();
 | 
| 
 | 
    29 		if( !ehlo.startsWith("250") )
 | 
| 
1584
 | 
    30 			throw new MailException(ehlo);
 | 
| 
1582
 | 
    31 	}
 | 
| 
 | 
    32 
 | 
| 
1830
 | 
    33 	public Smtp(Socket socket) throws IOException, MailException {
 | 
| 
 | 
    34 		this(socket,"GoodJava");
 | 
| 
 | 
    35 	}
 | 
| 
 | 
    36 
 | 
| 
1584
 | 
    37 	public String authenticate(String username,String password) throws IOException, MailException {
 | 
| 
1583
 | 
    38 		String s = "\0" + username + "\0" + password;
 | 
| 
 | 
    39 		s = GoodUtils.base64Encode(s);
 | 
| 
 | 
    40 		write( "AUTH PLAIN " + s + "\r\n" );
 | 
| 
 | 
    41 		String r = read();
 | 
| 
 | 
    42 		if( !r.startsWith("235") )
 | 
| 
1584
 | 
    43 			throw new MailException(r);
 | 
| 
1583
 | 
    44 		return r;
 | 
| 
 | 
    45 	}
 | 
| 
 | 
    46 
 | 
| 
1584
 | 
    47 	public void send(Message msg) throws IOException, MailException {
 | 
| 
1583
 | 
    48 		for( Map.Entry<String,String> entry : msg.headers.entrySet() ) {
 | 
| 
 | 
    49 			String name = entry.getKey();
 | 
| 
 | 
    50 			String value = entry.getValue();
 | 
| 
 | 
    51 			if( name.equalsIgnoreCase("from") ) {
 | 
| 
 | 
    52 				from(value);
 | 
| 
 | 
    53 			}
 | 
| 
1686
 | 
    54 		}
 | 
| 
 | 
    55 		for( Map.Entry<String,String> entry : msg.headers.entrySet() ) {
 | 
| 
 | 
    56 			String name = entry.getKey();
 | 
| 
 | 
    57 			String value = entry.getValue();
 | 
| 
1583
 | 
    58 			if( name.equalsIgnoreCase("to")
 | 
| 
 | 
    59 				|| name.equalsIgnoreCase("cc")
 | 
| 
 | 
    60 				|| name.equalsIgnoreCase("bcc")
 | 
| 
 | 
    61 			) {
 | 
| 
 | 
    62 				for( String s : value.split(",") ) {
 | 
| 
 | 
    63 					to(s);
 | 
| 
 | 
    64 				}
 | 
| 
 | 
    65 			}
 | 
| 
 | 
    66 		}
 | 
| 
 | 
    67 		data( msg.toText() );
 | 
| 
 | 
    68 	}
 | 
| 
 | 
    69 
 | 
| 
1584
 | 
    70 	public void close() throws IOException, MailException {
 | 
| 
1582
 | 
    71 		write( "QUIT\r\n" );
 | 
| 
 | 
    72 		String s = read();
 | 
| 
 | 
    73 		if( !s.startsWith("221") )
 | 
| 
1584
 | 
    74 			throw new MailException(s);
 | 
| 
1582
 | 
    75 		socket.close();
 | 
| 
 | 
    76 	}
 | 
| 
 | 
    77 
 | 
| 
1584
 | 
    78 	public String from(String address) throws IOException, MailException {
 | 
| 
1582
 | 
    79 		write( "MAIL FROM: " + address + "\r\n" );
 | 
| 
 | 
    80 		String r = read();
 | 
| 
 | 
    81 		if( !r.startsWith("250") )
 | 
| 
1584
 | 
    82 			throw new MailException(r);
 | 
| 
1582
 | 
    83 		return r;
 | 
| 
 | 
    84 	}
 | 
| 
 | 
    85 
 | 
| 
1584
 | 
    86 	public String to(String address) throws IOException, MailException {
 | 
| 
1582
 | 
    87 		write( "RCPT TO: " + address + "\r\n" );
 | 
| 
 | 
    88 		String r = read();
 | 
| 
 | 
    89 		if( !r.startsWith("250") )
 | 
| 
1584
 | 
    90 			throw new MailException(r);
 | 
| 
1582
 | 
    91 		return r;
 | 
| 
 | 
    92 	}
 | 
| 
 | 
    93 
 | 
| 
1584
 | 
    94 	public String data(String text) throws IOException, MailException {
 | 
| 
1582
 | 
    95 		if( !text.endsWith("\r\n") )
 | 
| 
1584
 | 
    96 			throw new MailException("text must end with \\r\\n");
 | 
| 
1582
 | 
    97 		text = text.replace("\r\n.","\r\n..");
 | 
| 
 | 
    98 		write( "DATA\r\n" );
 | 
| 
 | 
    99 		String r = read();
 | 
| 
 | 
   100 		if( !r.startsWith("354") )
 | 
| 
1584
 | 
   101 			throw new MailException(r);
 | 
| 
1582
 | 
   102 		write( text + ".\r\n" );
 | 
| 
 | 
   103 		r = read();
 | 
| 
 | 
   104 		if( !r.startsWith("250") )
 | 
| 
1584
 | 
   105 			throw new MailException(r);
 | 
| 
1582
 | 
   106 		return r;
 | 
| 
 | 
   107 	}
 | 
| 
 | 
   108 
 | 
| 
 | 
   109 	private String read() throws IOException {
 | 
| 
 | 
   110 		int n = reader.read(buf);
 | 
| 
 | 
   111 		return new String(buf,0,n);
 | 
| 
 | 
   112 	}
 | 
| 
 | 
   113 
 | 
| 
 | 
   114 	private void write(String s) throws IOException {
 | 
| 
 | 
   115 		writer.write(s);
 | 
| 
 | 
   116 		writer.flush();
 | 
| 
 | 
   117 	}
 | 
| 
 | 
   118 }
 |