1 28 29 package com.caucho.vfs; 30 31 import com.caucho.server.util.CauchoSystem; 32 import com.caucho.util.Alarm; 33 import com.caucho.util.CharBuffer; 34 import com.caucho.util.Log; 35 import com.caucho.util.NullIterator; 36 import com.caucho.util.QDate; 37 import com.caucho.util.StringCharCursor; 38 39 import java.io.IOException ; 40 import java.io.InputStream ; 41 import java.net.Socket ; 42 import java.util.ArrayList ; 43 import java.util.HashMap ; 44 import java.util.Iterator ; 45 import java.util.logging.Level ; 46 import java.util.logging.Logger ; 47 48 55 class SmtpStream extends MemoryStream { 56 static final Logger log = Log.open(SmtpStream.class); 57 58 ArrayList <MailtoPath.Recipient> _to; 60 ArrayList <MailtoPath.Recipient> _cc; 62 ArrayList <MailtoPath.Recipient> _bcc; 64 65 private String _from; 66 private String _sender; 67 68 private HashMap <String ,Object > _attributes; 69 70 boolean _isClosed; 72 73 74 80 SmtpStream(ArrayList <MailtoPath.Recipient> to, 81 HashMap <String ,Object > attributes) 82 throws IOException 83 { 84 if (to.size() <= 0) 85 throw new IOException ("No recipients in mailto"); 86 87 _to = new ArrayList <MailtoPath.Recipient>(); 88 for (int i = 0; i < to.size(); i++) 89 _to.add(to.get(i)); 90 91 if (attributes != null) { 94 Iterator<String > iter = attributes.keySet().iterator(); 95 96 while (iter.hasNext()) { 97 String key = iter.next(); 98 99 try { 100 setAttribute(key, attributes.get(key)); 101 } catch (IOException e) { 102 } 103 } 104 } 105 } 106 107 110 public Object getAttribute(String name) 111 throws IOException 112 { 113 if (_attributes != null) 114 return _attributes.get(name.toLowerCase()); 115 else 116 return null; 117 } 118 119 public Iterator<String > getAttributeNames() 120 { 121 if (_attributes != null) 122 return _attributes.keySet().iterator(); 123 else 124 return NullIterator.create(); 125 } 126 127 132 public void setAttribute(String name, Object value) 133 throws IOException 134 { 135 name = name.toLowerCase(); 136 if (name.equals("date") || 137 name.equals("received") || name.equals("return-path") || 138 name.equals("message-id")) 139 throw new IOException ("cannot set property `" + name + "'"); 140 141 if (name.equals("to")) { 142 addTo((String ) value); 143 return; 144 } 145 if (name.equals("cc")) { 146 addCc((String ) value); 147 return; 148 } 149 150 if (name.equals("bcc")) { 151 addBcc((String ) value); 152 return; 153 } 154 155 if (name.equals("from")) { 156 _from = (String ) value; 157 return; 158 } 159 160 if (name.equals("sender")) { 161 _sender = (String ) value; 162 return; 163 } 164 165 if (_attributes == null) 166 _attributes = new HashMap <String ,Object >(); 167 168 _attributes.put(name, value); 169 } 170 171 176 public void addTo(String to) 177 throws IOException 178 { 179 StringCharCursor cursor = new StringCharCursor(to); 180 181 ArrayList <MailtoPath.Recipient> list = MailtoPath.parseAddressList(cursor); 182 183 for (int i = 0; i < list.size(); i++) 184 _to.add(list.get(i)); 185 } 186 187 192 public void addCc(String to) 193 throws IOException 194 { 195 StringCharCursor cursor = new StringCharCursor(to); 196 197 ArrayList <MailtoPath.Recipient> list = MailtoPath.parseAddressList(cursor); 198 199 if (_cc == null) 200 _cc = list; 201 else { 202 for (int i = 0; i < list.size(); i++) 203 _cc.add(list.get(i)); 204 } 205 } 206 207 212 public void addBcc(String to) 213 throws IOException 214 { 215 StringCharCursor cursor = new StringCharCursor(to); 216 217 ArrayList <MailtoPath.Recipient> list = MailtoPath.parseAddressList(cursor); 218 219 if (_bcc == null) 220 _bcc = list; 221 else { 222 for (int i = 0; i < list.size(); i++) 223 _bcc.add(list.get(i)); 224 } 225 } 226 227 230 public String getFrom() 231 { 232 if (_from != null) 233 return _from; 234 else 235 return null; 236 237 } 239 240 243 public String getSender() 244 { 245 if (_sender != null) 246 return _sender; 247 else 248 return null; 249 250 } 252 253 260 private int readResponse(InputStream is, CharBuffer msg) 261 throws IOException 262 { 263 int value; 264 265 do { 266 msg.clear(); 267 value = 0; 268 int ch; 269 if ((ch = is.read()) >= '0' && ch <= '9') { 270 for (; ch >= '0' && ch <= '9'; ch = is.read()) { 271 msg.append((char) ch); 272 value = 10 * value + ch - '0'; 273 } 274 } 275 276 if (ch == '-') 280 value = 0; 281 282 for (; ch != '\r' && ch != '\n'; ch = is.read()) 283 msg.append((char) ch); 284 285 if (ch == '\r') 286 ch = is.read(); 287 } while (value == 0); 288 289 if (log.isLoggable(Level.FINE)) 290 log.fine(msg.toString()); 291 292 return value; 293 } 294 295 303 void sendRecipients(ReadStream is, WriteStream os, 304 ArrayList <MailtoPath.Recipient> to, CharBuffer msg) 305 throws IOException 306 { 307 if (to == null) 308 return; 309 310 for (int i = 0; i < to.size(); i++) { 311 MailtoPath.Recipient rcpt = to.get(i); 312 313 os.print("RCPT TO: "); 314 os.print(rcpt.user); 315 if (rcpt.host != null) { 316 os.print("@"); 317 os.print(rcpt.host); 318 } 319 os.print("\r\n"); 320 321 if (log.isLoggable(Level.FINE)) 322 log.fine("RCPT TO: " + rcpt.user + "@" + rcpt.host); 323 324 if (readResponse(is, msg) / 100 != 2) 325 throw new IOException ("Expected '221' from SMTP: " + msg); 326 } 327 } 328 329 334 private void writeMessageBody(WriteStream os) 335 throws IOException 336 { 337 int ch; 338 339 ReadStream is = openRead(); 340 341 ch = is.read(); 342 if (ch < 0) { 343 os.print(".\r\n"); 344 return; 345 } 346 347 while (ch >= 0) { 348 if (ch == '\n') { 349 ch = is.read(); 350 if (ch == '.') { 351 os.print("\r\n.."); 352 ch = is.read(); 353 } 354 else if (ch <= 0) { 355 os.print("\r\n.\r\n"); 356 return; 357 } else { 358 os.print("\r\n"); 359 } 360 } else { 361 os.write(ch); 362 ch = is.read(); 363 } 364 } 365 366 os.print("\r\n.\r\n"); 367 } 368 369 372 private void writeMessage(WriteStream os) 373 throws IOException 374 { 375 String from = getFrom(); 376 os.print("From: "); 377 if (from != null) 378 os.print(from); 379 else { 380 os.print(CauchoSystem.getUserName()); 381 os.print("@"); 382 os.print(CauchoSystem.getLocalHost()); 383 } 384 os.print("\r\n"); 385 386 String date = QDate.formatLocal(Alarm.getCurrentTime(), 387 "%a, %d %b %Y %H:%M:%S %z"); 388 389 os.print("Date: " + date + "\r\n"); 390 391 os.print("To: "); 392 writeMessageRecipients(os, _to); 393 394 if (_cc != null && _cc.size() > 0) { 395 os.print("Cc: "); 396 writeMessageRecipients(os, _cc); 397 } 398 399 Iterator<String > iter = getAttributeNames(); 400 while (iter != null && iter.hasNext()) { 401 String key = iter.next(); 402 Object value = getAttribute(key); 403 404 if (value != null) { 405 os.print(key); 406 os.print(": "); 407 os.print(String.valueOf(value)); 408 os.print("\r\n"); 409 } 410 } 411 412 String sender = getSender(); 413 if (_from != sender && ! _from.equals(sender)) { 414 os.print("Sender: "); 415 416 if (sender != null) 417 os.print(sender); 418 else { 419 os.print(CauchoSystem.getUserName()); 420 os.print("@"); 421 os.print(CauchoSystem.getLocalHost()); 422 } 423 os.print("\r\n"); 424 } 425 426 os.print("\r\n"); 427 428 writeMessageBody(os); 429 } 430 431 434 private void writeMessageRecipients(WriteStream os, 435 ArrayList <MailtoPath.Recipient> list) 436 throws IOException 437 { 438 for (int i = 0; i < list.size(); i++) { 439 MailtoPath.Recipient rcpt = list.get(i); 440 441 if (i != 0) 442 os.print(", "); 443 444 os.print(rcpt.user); 445 if (rcpt.host != null) { 446 os.print("@"); 447 os.print(rcpt.host); 448 } 449 } 450 451 os.print("\r\n"); 452 } 453 454 457 public void close() 458 throws IOException 459 { 460 if (_isClosed) 461 return; 462 463 _isClosed = true; 464 465 String host = System.getProperty("mail.smtp.host"); 466 if (host == null) 467 host = "127.0.0.1"; 468 469 String portName = System.getProperty("mail.smtp.port"); 470 471 int port = 25; 472 if (portName != null) 473 port = Integer.parseInt(portName); 474 475 Socket sock = new Socket (host, port); 476 CharBuffer msg = new CharBuffer(); 477 ReadStream is = null; 478 WriteStream os = null; 479 try { 480 ReadWritePair s = VfsStream.openReadWrite(sock.getInputStream(), 481 sock.getOutputStream()); 482 is = s.getReadStream(); 483 os = s.getWriteStream(); 484 485 if (readResponse(is, msg) / 100 != 2) 486 throw new IOException ("Expected '220' from SMTP"); 487 488 os.print("HELO "); 489 os.print(CauchoSystem.getLocalHost()); 490 os.print("\r\n"); 491 if (readResponse(is, msg) / 100 != 2) 492 throw new IOException ("Expected '220' from SMTP"); 493 494 os.print("MAIL FROM: "); 495 String sender = getSender(); 496 if (sender != null) 497 os.print(sender); 498 else { 499 os.print(CauchoSystem.getUserName()); 500 os.print("@"); 501 os.print(CauchoSystem.getLocalHost()); 502 } 503 os.print("\r\n"); 504 if (readResponse(is, msg) / 100 != 2) 505 throw new IOException ("Expected '250' from SMTP: " + msg); 506 507 sendRecipients(is, os, _to, msg); 508 if (_cc != null) 509 sendRecipients(is, os, _cc, msg); 510 if (_bcc != null) 511 sendRecipients(is, os, _bcc, msg); 512 513 os.print("DATA\r\n"); 514 if (readResponse(is, msg) / 100 != 3) 515 throw new IOException ("Expected '354' from SMTP: " + msg); 516 517 writeMessage(os); 518 519 if (readResponse(is, msg) / 100 != 2) 520 throw new IOException ("Expected '200' from SMTP: " + msg); 521 522 os.print("QUIT\r\n"); 523 if (readResponse(is, msg) / 100 != 2) 524 throw new IOException ("Expected '250' from SMTP: " + msg); 525 } finally { 526 try { 527 if (is != null) 528 is.close(); 529 if (os != null) 530 os.close(); 531 } finally { 532 sock.close(); 533 } 534 destroy(); 535 } 536 } 537 } 538 | Popular Tags |