1 29 30 package com.caucho.mail.smtp; 31 32 import com.caucho.server.util.CauchoSystem; 33 import com.caucho.util.L10N; 34 import com.caucho.vfs.ReadStream; 35 import com.caucho.vfs.SocketStream; 36 import com.caucho.vfs.WriteStream; 37 38 import javax.mail.Address ; 39 import javax.mail.Message ; 40 import javax.mail.MessagingException ; 41 import javax.mail.Session ; 42 import javax.mail.Transport ; 43 import javax.mail.URLName ; 44 import javax.mail.internet.InternetAddress ; 45 import javax.mail.internet.MimeMessage ; 46 import java.io.IOException ; 47 import java.io.OutputStream ; 48 import java.net.Socket ; 49 import java.util.logging.Level ; 50 import java.util.logging.Logger ; 51 52 55 public class SmtpTransport extends Transport { 56 private static final L10N L = new L10N(SmtpTransport.class); 57 private static final Logger log 58 = Logger.getLogger(SmtpTransport.class.getName()); 59 60 private Socket _socket; 61 62 private ReadStream _is; 63 private WriteStream _os; 64 65 public SmtpTransport(Session session, URLName urlName) 66 { 67 super(session, urlName); 68 } 69 72 protected boolean protocolConnect(String host, 73 int port, 74 String user, 75 String password) 76 throws MessagingException 77 { 78 if (host == null) 79 host = "localhost"; 80 81 if (port < 0) 82 port = 25; 83 84 if (_socket != null) 86 throw new MessagingException (L.l("Attempted to connect to open connection.")); 87 88 try { 89 _socket = new Socket (host, port); 90 _socket.setSoTimeout(10000); 91 SocketStream s = new SocketStream(_socket); 92 93 _os = new WriteStream(s); 94 _is = new ReadStream(s, _os); 95 96 String line = _is.readLine(); 97 98 log.fine("smtp connection to " + host + ":" + port + " succeeded"); 99 log.fine("smtp: " + line); 100 101 _os.print("EHLO " + CauchoSystem.getLocalHost() + "\r\n"); 102 _os.flush(); 103 104 readResponse(); 105 106 setConnected(true); 107 } catch (IOException e) { 108 log.fine("smtp connection to " + host + ":" + port + " failed: " + e); 109 110 log.log(Level.FINER, e.toString(), e); 111 112 throw new MessagingException ("smtp connection to " + host + ":" + port + " failed.\n" + e); 113 } 114 115 return true; 116 } 117 118 124 public void sendMessage(Message msg, Address []addresses) 125 throws MessagingException 126 { 127 if (! isConnected()) 128 throw new MessagingException ("Transport does not have an active connection."); 129 130 if (! (msg instanceof MimeMessage )) 131 throw new MessagingException ("message must be a MimeMessage at '" 132 + msg.getClass().getName() + "'"); 133 134 MimeMessage mimeMsg = (MimeMessage ) msg; 135 136 try { 137 140 String []fromList = mimeMsg.getHeader("From"); 141 String from; 142 143 if (fromList == null || fromList.length < 1) { 144 throw new MessagingException ("message should have a sender"); 146 } 147 else 148 from = fromList[0]; 149 150 _os.print("MAIL FROM:<" + from + ">\r\n"); 151 _os.flush(); 152 153 if (log.isLoggable(Level.FINER)) 154 log.finer("mail from:<" + from + ">"); 155 156 readResponse(); 157 158 for (int i = 0; i < addresses.length; i++) { 159 InternetAddress addr = (InternetAddress ) addresses[i]; 160 161 if (log.isLoggable(Level.FINER)) 162 log.finer("mail to:<" + addr.getAddress() + ">"); 163 164 _os.print("RCPT TO:<" + addr.getAddress() + ">\r\n"); 165 _os.flush(); 166 167 readResponse(); 168 } 169 170 _os.print("DATA\r\n"); 171 _os.flush(); 172 173 String line = _is.readLine(); 174 if (! line.startsWith("354 ")) 175 throw new MessagingException ("Data not accepted: " + line); 176 177 mimeMsg.writeTo(new DataFilter(_os)); 178 179 _os.print("\r\n.\r\n"); 180 _os.flush(); 181 } catch (IOException e) { 182 log.log(Level.FINER, e.toString(), e); 183 184 throw new MessagingException (e.toString()); 185 } 186 } 187 188 private int readResponse() 189 throws IOException , MessagingException 190 { 191 while (true) { 192 String line = _is.readLine(); 193 if (line.length() < 4) 194 throw new MessagingException (line); 195 196 int status = 0; 197 for (int i = 0; i < 3; i++) { 198 char ch; 199 200 if ('0' <= (ch = line.charAt(i)) && ch <= '9') 201 status = 10 * status + ch - '0'; 202 } 203 204 if ((status / 100) % 10 != 2) 205 throw new MessagingException (line); 206 207 if (line.charAt(3) != '-') 208 return status; 209 } 210 } 211 212 215 public void close() 216 throws MessagingException 217 { 218 Socket socket = _socket; 219 _socket = null; 220 221 WriteStream os = _os; 222 _os = null; 223 224 setConnected(false); 225 226 try { 227 if (os != null) { 228 os.print("QUIT\r\n"); 229 os.flush(); 230 } 231 } catch (IOException e) { 232 } 233 234 try { 235 if (socket != null) 236 socket.close(); 237 } catch (IOException e) { 238 } 239 } 240 241 private class DataFilter extends OutputStream { 242 private OutputStream _os; 243 244 private boolean _isCr; 245 private boolean _isLf; 246 247 DataFilter(OutputStream os) 248 { 249 _os = os; 250 } 251 252 public void write(int ch) 253 throws IOException 254 { 255 switch (ch) { 256 case '\r': 257 _isCr = true; 258 _isLf = false; 259 break; 260 case '\n': 261 _isLf = _isCr; 262 _isCr = false; 263 break; 264 case '.': 265 if (_isLf) 266 _os.write('.'); 267 _isLf = false; 268 _isCr = false; 269 break; 270 default: 271 _isLf = false; 272 _isCr = false; 273 break; 274 } 275 276 _os.write(ch); 277 } 278 } 279 } 280 | Popular Tags |