001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.camel.component.mail; 018 019 import java.net.URI; 020 import java.util.HashMap; 021 import java.util.Map; 022 import java.util.Properties; 023 import javax.mail.Authenticator; 024 import javax.mail.Message; 025 import javax.mail.PasswordAuthentication; 026 import javax.mail.Session; 027 028 import org.apache.camel.RuntimeCamelException; 029 import org.springframework.mail.javamail.JavaMailSenderImpl; 030 031 /** 032 * Represents the configuration data for communicating over email 033 * 034 * @version $Revision: 760920 $ 035 */ 036 public class MailConfiguration implements Cloneable { 037 038 public static final String DEFAULT_FOLDER_NAME = "INBOX"; 039 public static final String DEFAULT_FROM = "camel@localhost"; 040 public static final String DEFAULT_ALTERNATE_BODY_HEADER = "mail_alternateBody"; 041 public static final long DEFAULT_CONNECTION_TIMEOUT = 30000L; 042 043 private Properties javaMailProperties; 044 private String protocol; 045 private String host; 046 private int port = -1; 047 private String username; 048 private String password; 049 private Session session; 050 private String defaultEncoding; 051 private String from = DEFAULT_FROM; 052 private String folderName = DEFAULT_FOLDER_NAME; 053 private boolean deleteProcessedMessages; 054 private boolean ignoreUriScheme; 055 private boolean processOnlyUnseenMessages = true; 056 private Map<Message.RecipientType, String> recipients = new HashMap<Message.RecipientType, String>(); 057 private String destination; 058 private int fetchSize = -1; 059 private boolean debugMode; 060 private long connectionTimeout = DEFAULT_CONNECTION_TIMEOUT; 061 private boolean dummyTrustManager; 062 private String contentType = "text/plain"; 063 private String alternateBodyHeader = DEFAULT_ALTERNATE_BODY_HEADER; 064 private boolean useInlineAttachments; 065 066 public MailConfiguration() { 067 } 068 069 /** 070 * Returns a copy of this configuration 071 */ 072 public MailConfiguration copy() { 073 try { 074 return (MailConfiguration) clone(); 075 } catch (CloneNotSupportedException e) { 076 throw new RuntimeCamelException(e); 077 } 078 } 079 080 public void configure(URI uri) { 081 String value = uri.getHost(); 082 if (value != null) { 083 setHost(value); 084 } 085 086 if (!isIgnoreUriScheme()) { 087 String scheme = uri.getScheme(); 088 if (scheme != null) { 089 setProtocol(scheme); 090 } 091 } 092 093 String userInfo = uri.getUserInfo(); 094 if (userInfo != null) { 095 setUsername(userInfo); 096 } 097 098 int port = uri.getPort(); 099 if (port > 0) { 100 setPort(port); 101 } else if (port <= 0 && this.port <= 0) { 102 // resolve default port if no port number was provided, and not already configured with a port number 103 setPort(MailUtils.getDefaultPortForProtocol(uri.getScheme())); 104 } 105 } 106 107 protected JavaMailSenderImpl createJavaMailSender() { 108 JavaMailSenderImpl answer = new JavaMailSenderImpl(); 109 110 // sets the debug mode of the underlying mail framework 111 answer.getSession().setDebug(debugMode); 112 113 if (javaMailProperties != null) { 114 answer.setJavaMailProperties(javaMailProperties); 115 } else { 116 // set default properties if none provided 117 answer.setJavaMailProperties(createJavaMailProperties()); 118 } 119 120 if (defaultEncoding != null) { 121 answer.setDefaultEncoding(defaultEncoding); 122 } 123 if (host != null) { 124 answer.setHost(host); 125 } 126 if (port >= 0) { 127 answer.setPort(port); 128 } 129 if (password != null) { 130 answer.setPassword(password); 131 } 132 if (protocol != null) { 133 answer.setProtocol(protocol); 134 } 135 if (session != null) { 136 answer.setSession(session); 137 } else { 138 // use our authenticator that does no live user interaction but returns the already configured username and password 139 Session session = Session.getDefaultInstance(answer.getJavaMailProperties(), getAuthenticator()); 140 answer.setSession(session); 141 } 142 if (username != null) { 143 answer.setUsername(username); 144 } 145 146 return answer; 147 } 148 149 private Properties createJavaMailProperties() { 150 // clone the system properties and set the java mail properties 151 Properties properties = (Properties)System.getProperties().clone(); 152 properties.put("mail." + protocol + ".connectiontimeout", connectionTimeout); 153 properties.put("mail." + protocol + ".timeout", connectionTimeout); 154 properties.put("mail." + protocol + ".host", host); 155 properties.put("mail." + protocol + ".port", "" + port); 156 if (username != null) { 157 properties.put("mail." + protocol + ".user", username); 158 properties.put("mail.user", username); 159 properties.put("mail." + protocol + ".auth", "true"); 160 } else { 161 properties.put("mail." + protocol + ".auth", "false"); 162 } 163 properties.put("mail." + protocol + ".rsetbeforequit", "true"); 164 properties.put("mail.transport.protocol", protocol); 165 properties.put("mail.store.protocol", protocol); 166 properties.put("mail.host", host); 167 168 if (debugMode) { 169 // add more debug for the SSL communication as well 170 properties.put("javax.net.debug", "all"); 171 } 172 173 if (dummyTrustManager && isSecureProtocol()) { 174 // set the custom SSL properties 175 properties.put("mail." + protocol + ".socketFactory.class", "org.apache.camel.component.mail.security.DummySSLSocketFactory"); 176 properties.put("mail." + protocol + ".socketFactory.fallback", "false"); 177 properties.put("mail." + protocol + ".socketFactory.port", "" + port); 178 } 179 180 return properties; 181 } 182 183 /** 184 * Is the used protocol to be secure or not 185 */ 186 public boolean isSecureProtocol() { 187 return this.protocol.equalsIgnoreCase("smtps") || this.protocol.equalsIgnoreCase("pop3s") 188 || this.protocol.equalsIgnoreCase("imaps"); 189 } 190 191 /** 192 * Returns an authenticator object for use in sessions 193 */ 194 public Authenticator getAuthenticator() { 195 return new Authenticator() { 196 protected PasswordAuthentication getPasswordAuthentication() { 197 return new PasswordAuthentication(getUsername(), getPassword()); 198 } 199 }; 200 } 201 202 public String getMailStoreLogInformation() { 203 String ssl = ""; 204 if (isSecureProtocol()) { 205 ssl = "(SSL enabled" + (dummyTrustManager ? " using DummyTrustManager)" : ")"); 206 } 207 208 return protocol + "//" + host + ":" + port + ssl + ", folder=" + folderName; 209 } 210 211 // Properties 212 // ------------------------------------------------------------------------- 213 214 public String getDefaultEncoding() { 215 return defaultEncoding; 216 } 217 218 public void setDefaultEncoding(String defaultEncoding) { 219 this.defaultEncoding = defaultEncoding; 220 } 221 222 public String getHost() { 223 return host; 224 } 225 226 public void setHost(String host) { 227 this.host = host; 228 } 229 230 public Properties getJavaMailProperties() { 231 return javaMailProperties; 232 } 233 234 public void setJavaMailProperties(Properties javaMailProperties) { 235 this.javaMailProperties = javaMailProperties; 236 } 237 238 public String getPassword() { 239 return password; 240 } 241 242 public void setPassword(String password) { 243 this.password = password; 244 } 245 246 public int getPort() { 247 return port; 248 } 249 250 public void setPort(int port) { 251 this.port = port; 252 } 253 254 public String getProtocol() { 255 return protocol; 256 } 257 258 public void setProtocol(String protocol) { 259 this.protocol = protocol; 260 } 261 262 public Session getSession() { 263 return session; 264 } 265 266 public void setSession(Session session) { 267 this.session = session; 268 } 269 270 public String getUsername() { 271 return username; 272 } 273 274 public void setUsername(String username) { 275 this.username = username; 276 if (destination == null) { 277 // set default destination to username@host for backwards compatibility 278 // can be overridden by URI parameters 279 String address = username; 280 if (address.indexOf("@") == -1) { 281 address += "@" + host; 282 } 283 destination = address; 284 } 285 } 286 287 /** 288 * Gets the destination (recipient <tt>To</tt> email address). 289 * 290 * @deprecated use {@link #getRecipients()} 291 */ 292 public String getDestination() { 293 return destination; 294 } 295 296 /** 297 * Sets the destination (recipient <tt>To</tt> email address). 298 * 299 * @deprecated use {@link #setTo(String)} 300 */ 301 public void setDestination(String destination) { 302 this.destination = destination; 303 } 304 305 public String getFrom() { 306 return from; 307 } 308 309 public void setFrom(String from) { 310 this.from = from; 311 } 312 313 public boolean isDeleteProcessedMessages() { 314 return deleteProcessedMessages; 315 } 316 317 public void setDeleteProcessedMessages(boolean deleteProcessedMessages) { 318 this.deleteProcessedMessages = deleteProcessedMessages; 319 } 320 321 public String getFolderName() { 322 return folderName; 323 } 324 325 public void setFolderName(String folderName) { 326 this.folderName = folderName; 327 } 328 329 public boolean isIgnoreUriScheme() { 330 return ignoreUriScheme; 331 } 332 333 public void setIgnoreUriScheme(boolean ignoreUriScheme) { 334 this.ignoreUriScheme = ignoreUriScheme; 335 } 336 337 public boolean isProcessOnlyUnseenMessages() { 338 return processOnlyUnseenMessages; 339 } 340 341 public void setProcessOnlyUnseenMessages(boolean processOnlyUnseenMessages) { 342 this.processOnlyUnseenMessages = processOnlyUnseenMessages; 343 } 344 345 /** 346 * Sets the <tt>To</tt> email address. Separate multiple email addresses with comma. 347 */ 348 public void setTo(String address) { 349 recipients.put(Message.RecipientType.TO, address); 350 } 351 352 /** 353 * Sets the <tt>CC</tt> email address. Separate multiple email addresses with comma. 354 */ 355 public void setCC(String address) { 356 recipients.put(Message.RecipientType.CC, address); 357 } 358 359 /** 360 * Sets the <tt>BCC</tt> email address. Separate multiple email addresses with comma. 361 */ 362 public void setBCC(String address) { 363 recipients.put(Message.RecipientType.BCC, address); 364 } 365 366 public Map<Message.RecipientType, String> getRecipients() { 367 return recipients; 368 } 369 370 public int getFetchSize() { 371 return fetchSize; 372 } 373 374 public void setFetchSize(int fetchSize) { 375 this.fetchSize = fetchSize; 376 } 377 378 public boolean isDebugMode() { 379 return debugMode; 380 } 381 382 public void setDebugMode(boolean debugMode) { 383 this.debugMode = debugMode; 384 } 385 386 public long getConnectionTimeout() { 387 return connectionTimeout; 388 } 389 390 public void setConnectionTimeout(long connectionTimeout) { 391 this.connectionTimeout = connectionTimeout; 392 } 393 394 public boolean isDummyTrustManager() { 395 return dummyTrustManager; 396 } 397 398 public void setDummyTrustManager(boolean dummyTrustManager) { 399 this.dummyTrustManager = dummyTrustManager; 400 } 401 402 public String getContentType() { 403 return contentType; 404 } 405 406 public void setContentType(String contentType) { 407 this.contentType = contentType; 408 } 409 410 public String getAlternateBodyHeader() { 411 return alternateBodyHeader; 412 } 413 414 public void setAlternateBodyHeader(String alternateBodyHeader) { 415 this.alternateBodyHeader = alternateBodyHeader; 416 } 417 418 public boolean isUseInlineAttachments() { 419 return useInlineAttachments; 420 } 421 422 public void setUseInlineAttachments(boolean useInlineAttachments) { 423 this.useInlineAttachments = useInlineAttachments; 424 } 425 }