1 19 package org.columba.mail.smtp; 20 21 import java.io.IOException ; 22 import java.net.InetAddress ; 23 import java.text.MessageFormat ; 24 import java.util.ArrayList ; 25 import java.util.Collections ; 26 import java.util.Iterator ; 27 import java.util.List ; 28 import java.util.Observable ; 29 import java.util.Observer ; 30 31 import javax.swing.JOptionPane ; 32 33 import org.columba.api.command.IWorkerStatusController; 34 import org.columba.core.base.Blowfish; 35 import org.columba.core.command.CommandCancelledException; 36 import org.columba.core.command.ProgressObservedInputStream; 37 import org.columba.core.gui.base.MultiLineLabel; 38 import org.columba.core.gui.frame.FrameManager; 39 import org.columba.mail.composer.SendableMessage; 40 import org.columba.mail.config.AccountItem; 41 import org.columba.mail.config.Identity; 42 import org.columba.mail.config.ImapItem; 43 import org.columba.mail.config.OutgoingItem; 44 import org.columba.mail.config.PopItem; 45 import org.columba.mail.gui.util.PasswordDialog; 46 import org.columba.mail.pop3.POP3Store; 47 import org.columba.mail.util.AuthenticationManager; 48 import org.columba.mail.util.AuthenticationSecurityComparator; 49 import org.columba.mail.util.MailResourceLoader; 50 import org.columba.ristretto.auth.AuthenticationException; 51 import org.columba.ristretto.auth.AuthenticationFactory; 52 import org.columba.ristretto.message.Address; 53 import org.columba.ristretto.parser.ParserException; 54 import org.columba.ristretto.pop3.POP3Exception; 55 import org.columba.ristretto.smtp.SMTPException; 56 import org.columba.ristretto.smtp.SMTPProtocol; 57 58 71 public class SMTPServer implements Observer { 72 73 private String [] capas; 74 75 protected SMTPProtocol protocol; 76 77 protected OutgoingItem smtpItem; 78 79 protected Identity identity; 80 81 protected String fromAddress; 82 83 private boolean usingSSL; 84 85 private AccountItem accountItem; 86 87 90 public SMTPServer(AccountItem accountItem) { 91 super(); 92 93 this.accountItem = accountItem; 94 identity = accountItem.getIdentity(); 95 96 smtpItem = accountItem.getSmtpItem(); 98 99 smtpItem.getRoot().addObserver(this); 100 protocol = new SMTPProtocol(smtpItem.get("host"), smtpItem.getInteger("port")); 101 } 102 103 private void ensureConnected() throws IOException , SMTPException, CommandCancelledException { 104 if (protocol.getState() == SMTPProtocol.NOT_CONNECTED) { 105 protocol.openPort(); 107 108 initialize(); 109 110 doSSL(); 111 } 112 } 113 114 119 private void ensureAuthenticated() throws IOException , SMTPException, 120 CommandCancelledException { 121 String username; 122 char[] password = new char[0]; 123 boolean savePassword; 124 125 fromAddress = identity.getAddress().getMailAddress(); 128 129 130 131 usingSSL = smtpItem.getBoolean("enable_ssl"); 132 int authMethod = getLoginMethod(); 133 134 boolean authenticated = (authMethod == AuthenticationManager.NONE); 135 136 if (authMethod == AuthenticationManager.POP_BEFORE_SMTP) { 137 try { 139 pop3Authentification(); 140 } catch (POP3Exception e) { 141 throw new SMTPException(e); 142 } 143 144 authenticated = true; 145 } 146 147 ensureConnected(); 148 149 150 if (!authenticated) { 151 username = smtpItem.get("user"); 152 password = Blowfish.decrypt(smtpItem.getRoot().getAttribute("password", "")); 153 savePassword = smtpItem.getBoolean("save_password"); 154 155 if (username.length() == 0) { 156 if (accountItem.isPopAccount()) { 159 PopItem pop3Item = accountItem.getPopItem(); 160 username = pop3Item.get("user"); 161 } else { 162 ImapItem imapItem = accountItem.getImapItem(); 163 username = imapItem.get("user"); 164 } 165 } 166 167 PasswordDialog passDialog = new PasswordDialog(); 168 169 if (password.length == 0) { 171 passDialog.showDialog(MessageFormat.format(MailResourceLoader 172 .getString("dialog", "password", "enter_password"), 173 new Object [] { username, 174 smtpItem.get("host") }), 175 new String (password), savePassword); 176 177 if (passDialog.success()) { 178 password = passDialog.getPassword(); 179 savePassword = passDialog.getSave(); 180 } else { 181 throw new CommandCancelledException(); 182 } 183 } 184 185 while (!authenticated) { 187 try { 188 try { 189 protocol.auth(AuthenticationManager 190 .getSaslName(authMethod), username, password); 191 authenticated = true; 192 } catch (AuthenticationException e) { 193 if (e.getCause() instanceof SMTPException) { 197 int errorCode = ((SMTPException) e.getCause()).getCode(); 198 199 if( errorCode == 504 ) { 201 JOptionPane 204 .showMessageDialog( 205 FrameManager.getInstance() 206 .getActiveFrame(), 207 new MultiLineLabel( 208 MailResourceLoader 209 .getString( 210 "dialog", 211 "error", 212 "authentication_not_supported")), 213 MailResourceLoader.getString("dialog", 214 "error", 215 "authentication_process_error"), 216 JOptionPane.INFORMATION_MESSAGE); 217 218 smtpItem.setString("login_method", Integer 220 .toString(AuthenticationManager.NONE)); 221 222 return; 223 } 224 225 } else { 226 throw (SMTPException) e.getCause(); 227 } 228 229 int result = JOptionPane 232 .showConfirmDialog( 233 FrameManager.getInstance() 234 .getActiveFrame(), 235 new MultiLineLabel( 236 e.getMessage() 237 + "\n" 238 + MailResourceLoader 239 .getString( 240 "dialog", 241 "error", 242 "authentication_fallback_to_default")), 243 MailResourceLoader.getString("dialog", 244 "error", 245 "authentication_process_error"), 246 JOptionPane.OK_CANCEL_OPTION); 247 248 if (result == JOptionPane.OK_OPTION) { 249 authMethod = AuthenticationManager.SASL_PLAIN; 250 smtpItem.setString("login_method", Integer 251 .toString(authMethod)); 252 } else { 253 throw new CommandCancelledException(); 254 } 255 256 } 257 } catch (SMTPException e) { 258 passDialog.showDialog(MessageFormat.format( 259 MailResourceLoader.getString("dialog", "password", 260 "enter_password"), new Object [] { username, 261 smtpItem.get("host") }), new String ( 262 password), savePassword); 263 264 if (!passDialog.success()) { 265 throw new CommandCancelledException(); 266 } else { 267 password = passDialog.getPassword(); 268 savePassword = passDialog.getSave(); 269 } 270 } 271 } 272 273 smtpItem.setString("user", username); 276 smtpItem.setBoolean("save_password", savePassword); 277 if (savePassword) { 278 smtpItem.setString("password", Blowfish.encrypt(password)); 279 } 280 } 281 } 282 283 289 private void doSSL() throws CommandCancelledException, IOException , SMTPException { 290 if (smtpItem.getBoolean("enable_ssl")) { 291 if (isSupported("STARTTLS")) { 292 try { 293 protocol.startTLS(); 294 usingSSL = true; 295 } catch (Exception e) { 296 Object [] options = new String [] { 297 MailResourceLoader.getString("", "global", "ok") 298 .replaceAll("&", ""), 299 MailResourceLoader 300 .getString("", "global", "cancel") 301 .replaceAll("&", "") }; 302 303 int result = JOptionPane.showOptionDialog(FrameManager.getInstance() 304 .getActiveFrame(), 305 MailResourceLoader.getString("dialog", "error", 306 "ssl_handshake_error") 307 + ": " 308 + e.getLocalizedMessage() 309 + "\n" 310 + MailResourceLoader.getString("dialog", 311 "error", "ssl_turn_off"), 312 "Warning", JOptionPane.DEFAULT_OPTION, 313 JOptionPane.WARNING_MESSAGE, null, options, 314 options[0]); 315 316 if (result == 1) { 317 throw new CommandCancelledException(); 318 } 319 320 smtpItem.setBoolean("enable_ssl", false); 322 323 protocol.openPort(); 324 325 initialize(); 326 } 327 } else { 328 Object [] options = new String [] { 329 MailResourceLoader.getString("", "global", "ok") 330 .replaceAll("&", ""), 331 MailResourceLoader.getString("", "global", "cancel") 332 .replaceAll("&", "") }; 333 int result = JOptionPane.showOptionDialog(null, 334 MailResourceLoader.getString("dialog", "error", 335 "ssl_not_supported") 336 + "\n" 337 + MailResourceLoader.getString("dialog", 338 "error", "ssl_turn_off"), "Warning", 339 JOptionPane.DEFAULT_OPTION, 340 JOptionPane.WARNING_MESSAGE, null, options, options[0]); 341 342 if (result == 1) { 343 throw new CommandCancelledException(); 344 } 345 346 smtpItem.setBoolean("enable_ssl", false); 348 } 349 } 350 } 351 352 356 private boolean isSupported(String string) { 357 for (int i = 0; i < capas.length; i++) { 358 if (capas[i].startsWith(string)) { 359 return true; 360 } 361 } 362 363 return false; 364 } 365 366 370 public List checkSupportedAuthenticationMethods() throws IOException , 371 SMTPException, CommandCancelledException { 372 ensureConnected(); 373 374 List supportedMechanisms = new ArrayList (); 375 376 for (int i = 0; i < capas.length; i++) { 377 if (capas[i].startsWith("AUTH")) { 378 List authMechanisms = AuthenticationFactory.getInstance() 379 .getSupportedMechanisms(capas[i]); 380 Iterator it = authMechanisms.iterator(); 381 while (it.hasNext()) { 382 supportedMechanisms.add(new Integer (AuthenticationManager 383 .getSaslCode((String ) it.next()))); 384 } 385 386 break; 387 } 388 } 389 390 if( supportedMechanisms.size() == 0) { 391 supportedMechanisms.add(new Integer (AuthenticationManager.SASL_PLAIN)); 393 } 394 395 return supportedMechanisms; 396 } 397 398 private void initialize() throws IOException , SMTPException { 399 try { 400 capas = protocol.ehlo(InetAddress.getLocalHost()); 401 } catch (SMTPException e1) { 402 if( protocol.getState() < SMTPProtocol.PLAIN ) { 404 protocol.openPort(); 405 } 406 protocol.helo(InetAddress.getLocalHost()); 407 capas = new String [] {}; 408 } 409 } 410 411 416 private int getLoginMethod() throws IOException , SMTPException, CommandCancelledException { 417 String authType = accountItem.getSmtpItem().get("login_method"); 418 int method = 0; 419 420 try { 421 method = Integer.parseInt(authType); 422 } catch (NumberFormatException e) { 423 } 425 426 if (method == 0) { 427 List supported = checkSupportedAuthenticationMethods(); 428 429 if (accountItem.isPopAccount()) { 430 supported 431 .add(new Integer (AuthenticationManager.POP_BEFORE_SMTP)); 432 } 433 434 if (supported.size() == 0) { 435 return AuthenticationManager.NONE; 437 } 438 439 if (usingSSL) { 440 method = ((Integer ) supported.get(0)).intValue(); 443 } else { 444 Collections.sort(supported, 445 new AuthenticationSecurityComparator()); 446 method = ((Integer ) supported.get(supported.size() - 1)) 447 .intValue(); 448 } 449 } 450 451 return method; 452 } 453 454 459 public void closeConnection() { 460 try { 462 protocol.quit(); 463 } catch (Exception e) { 464 e.printStackTrace(); 465 } 466 } 467 468 478 protected void pop3Authentification() throws IOException , POP3Exception, 479 CommandCancelledException { 480 POP3Store.doPOPbeforeSMTP(accountItem.getPopItem()); 481 } 482 483 493 public void sendMessage(SendableMessage message, 494 IWorkerStatusController workerStatusController) 495 throws SMTPException, IOException , CommandCancelledException { 496 ensureAuthenticated(); 497 498 protocol.mail(identity.getAddress()); 501 502 Iterator recipients = message.getRecipients().iterator(); 503 504 while (recipients.hasNext()) { 505 try { 506 protocol.rcpt(Address.parse((String ) recipients.next())); 507 } catch (ParserException e1) { 508 throw new SMTPException(e1); 509 } 510 } 511 512 protocol.data(new ProgressObservedInputStream( 514 message.getSourceStream(), workerStatusController)); 515 } 516 517 public String getName() { 518 OutgoingItem smtpItem = accountItem.getSmtpItem(); 519 String host = smtpItem.get("host"); 520 521 return host; 522 } 523 524 public void dropConnection() throws IOException { 525 protocol.dropConnection(); 526 } 527 528 public void update(Observable o, Object arg) { 529 protocol = new SMTPProtocol(smtpItem.get("host"), smtpItem.getInteger("port")); 530 } 531 } | Popular Tags |