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: 884755 $ 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 MailConfiguration copy = (MailConfiguration) clone(); 075 // must set a new recipients map as clone just reuse the same reference 076 copy.recipients = new HashMap<Message.RecipientType, String>(); 077 copy.recipients.putAll(this.recipients); 078 return copy; 079 } catch (CloneNotSupportedException e) { 080 throw new RuntimeCamelException(e); 081 } 082 } 083 084 public void configure(URI uri) { 085 String value = uri.getHost(); 086 if (value != null) { 087 setHost(value); 088 } 089 090 if (!isIgnoreUriScheme()) { 091 String scheme = uri.getScheme(); 092 if (scheme != null) { 093 setProtocol(scheme); 094 } 095 } 096 097 String userInfo = uri.getUserInfo(); 098 if (userInfo != null) { 099 setUsername(userInfo); 100 } 101 102 int port = uri.getPort(); 103 if (port > 0) { 104 setPort(port); 105 } else if (port <= 0 && this.port <= 0) { 106 // resolve default port if no port number was provided, and not already configured with a port number 107 setPort(MailUtils.getDefaultPortForProtocol(uri.getScheme())); 108 } 109 } 110 111 protected JavaMailSenderImpl createJavaMailSender() { 112 JavaMailSenderImpl answer = new JavaMailSenderImpl(); 113 114 // sets the debug mode of the underlying mail framework 115 answer.getSession().setDebug(debugMode); 116 117 // java mail properties 118 Properties prop = javaMailProperties; 119 if (prop == null) { 120 // set default properties if none provided 121 prop = createJavaMailProperties(); 122 } 123 answer.setJavaMailProperties(prop); 124 125 if (defaultEncoding != null) { 126 answer.setDefaultEncoding(defaultEncoding); 127 } 128 if (host != null) { 129 answer.setHost(host); 130 } 131 if (port >= 0) { 132 answer.setPort(port); 133 } 134 if (password != null) { 135 answer.setPassword(password); 136 } 137 if (protocol != null) { 138 answer.setProtocol(protocol); 139 } 140 if (session != null) { 141 answer.setSession(session); 142 } else { 143 // use our authenticator that does no live user interaction but returns the already configured username and password 144 Session session = Session.getDefaultInstance(prop, getAuthenticator()); 145 answer.setSession(session); 146 } 147 if (username != null) { 148 answer.setUsername(username); 149 } 150 151 return answer; 152 } 153 154 private Properties createJavaMailProperties() { 155 // clone the system properties and set the java mail properties 156 Properties properties = (Properties)System.getProperties().clone(); 157 properties.put("mail." + protocol + ".connectiontimeout", connectionTimeout); 158 properties.put("mail." + protocol + ".timeout", connectionTimeout); 159 properties.put("mail." + protocol + ".host", host); 160 properties.put("mail." + protocol + ".port", "" + port); 161 if (username != null) { 162 properties.put("mail." + protocol + ".user", username); 163 properties.put("mail.user", username); 164 properties.put("mail." + protocol + ".auth", "true"); 165 } else { 166 properties.put("mail." + protocol + ".auth", "false"); 167 } 168 properties.put("mail." + protocol + ".rsetbeforequit", "true"); 169 properties.put("mail.transport.protocol", protocol); 170 properties.put("mail.store.protocol", protocol); 171 properties.put("mail.host", host); 172 173 if (debugMode) { 174 // add more debug for the SSL communication as well 175 properties.put("javax.net.debug", "all"); 176 } 177 178 if (dummyTrustManager && isSecureProtocol()) { 179 // set the custom SSL properties 180 properties.put("mail." + protocol + ".socketFactory.class", "org.apache.camel.component.mail.security.DummySSLSocketFactory"); 181 properties.put("mail." + protocol + ".socketFactory.fallback", "false"); 182 properties.put("mail." + protocol + ".socketFactory.port", "" + port); 183 } 184 185 return properties; 186 } 187 188 /** 189 * Is the used protocol to be secure or not 190 */ 191 public boolean isSecureProtocol() { 192 return this.protocol.equalsIgnoreCase("smtps") || this.protocol.equalsIgnoreCase("pop3s") 193 || this.protocol.equalsIgnoreCase("imaps"); 194 } 195 196 /** 197 * Returns an authenticator object for use in sessions 198 */ 199 public Authenticator getAuthenticator() { 200 return new Authenticator() { 201 protected PasswordAuthentication getPasswordAuthentication() { 202 return new PasswordAuthentication(getUsername(), getPassword()); 203 } 204 }; 205 } 206 207 public String getMailStoreLogInformation() { 208 String ssl = ""; 209 if (isSecureProtocol()) { 210 ssl = "(SSL enabled" + (dummyTrustManager ? " using DummyTrustManager)" : ")"); 211 } 212 213 return protocol + "//" + host + ":" + port + ssl + ", folder=" + folderName; 214 } 215 216 // Properties 217 // ------------------------------------------------------------------------- 218 219 public String getDefaultEncoding() { 220 return defaultEncoding; 221 } 222 223 public void setDefaultEncoding(String defaultEncoding) { 224 this.defaultEncoding = defaultEncoding; 225 } 226 227 public String getHost() { 228 return host; 229 } 230 231 public void setHost(String host) { 232 this.host = host; 233 } 234 235 public Properties getJavaMailProperties() { 236 return javaMailProperties; 237 } 238 239 public void setJavaMailProperties(Properties javaMailProperties) { 240 this.javaMailProperties = javaMailProperties; 241 } 242 243 public String getPassword() { 244 return password; 245 } 246 247 public void setPassword(String password) { 248 this.password = password; 249 } 250 251 public int getPort() { 252 return port; 253 } 254 255 public void setPort(int port) { 256 this.port = port; 257 } 258 259 public String getProtocol() { 260 return protocol; 261 } 262 263 public void setProtocol(String protocol) { 264 this.protocol = protocol; 265 } 266 267 public Session getSession() { 268 return session; 269 } 270 271 public void setSession(Session session) { 272 this.session = session; 273 } 274 275 public String getUsername() { 276 return username; 277 } 278 279 public void setUsername(String username) { 280 this.username = username; 281 if (destination == null) { 282 // set default destination to username@host for backwards compatibility 283 // can be overridden by URI parameters 284 String address = username; 285 if (address.indexOf("@") == -1) { 286 address += "@" + host; 287 } 288 destination = address; 289 } 290 } 291 292 /** 293 * Gets the destination (recipient <tt>To</tt> email address). 294 * 295 * @deprecated use {@link #getRecipients()} 296 */ 297 public String getDestination() { 298 return destination; 299 } 300 301 /** 302 * Sets the destination (recipient <tt>To</tt> email address). 303 * 304 * @deprecated use {@link #setTo(String)} 305 */ 306 public void setDestination(String destination) { 307 this.destination = destination; 308 } 309 310 public String getFrom() { 311 return from; 312 } 313 314 public void setFrom(String from) { 315 this.from = from; 316 } 317 318 public boolean isDeleteProcessedMessages() { 319 return deleteProcessedMessages; 320 } 321 322 public void setDeleteProcessedMessages(boolean deleteProcessedMessages) { 323 this.deleteProcessedMessages = deleteProcessedMessages; 324 } 325 326 public String getFolderName() { 327 return folderName; 328 } 329 330 public void setFolderName(String folderName) { 331 this.folderName = folderName; 332 } 333 334 public boolean isIgnoreUriScheme() { 335 return ignoreUriScheme; 336 } 337 338 public void setIgnoreUriScheme(boolean ignoreUriScheme) { 339 this.ignoreUriScheme = ignoreUriScheme; 340 } 341 342 public boolean isProcessOnlyUnseenMessages() { 343 return processOnlyUnseenMessages; 344 } 345 346 public void setProcessOnlyUnseenMessages(boolean processOnlyUnseenMessages) { 347 this.processOnlyUnseenMessages = processOnlyUnseenMessages; 348 } 349 350 /** 351 * Sets the <tt>To</tt> email address. Separate multiple email addresses with comma. 352 */ 353 public void setTo(String address) { 354 recipients.put(Message.RecipientType.TO, address); 355 } 356 357 /** 358 * Sets the <tt>CC</tt> email address. Separate multiple email addresses with comma. 359 */ 360 public void setCC(String address) { 361 recipients.put(Message.RecipientType.CC, address); 362 } 363 364 /** 365 * Sets the <tt>BCC</tt> email address. Separate multiple email addresses with comma. 366 */ 367 public void setBCC(String address) { 368 recipients.put(Message.RecipientType.BCC, address); 369 } 370 371 public Map<Message.RecipientType, String> getRecipients() { 372 return recipients; 373 } 374 375 public int getFetchSize() { 376 return fetchSize; 377 } 378 379 public void setFetchSize(int fetchSize) { 380 this.fetchSize = fetchSize; 381 } 382 383 public boolean isDebugMode() { 384 return debugMode; 385 } 386 387 public void setDebugMode(boolean debugMode) { 388 this.debugMode = debugMode; 389 } 390 391 public long getConnectionTimeout() { 392 return connectionTimeout; 393 } 394 395 public void setConnectionTimeout(long connectionTimeout) { 396 this.connectionTimeout = connectionTimeout; 397 } 398 399 public boolean isDummyTrustManager() { 400 return dummyTrustManager; 401 } 402 403 public void setDummyTrustManager(boolean dummyTrustManager) { 404 this.dummyTrustManager = dummyTrustManager; 405 } 406 407 public String getContentType() { 408 return contentType; 409 } 410 411 public void setContentType(String contentType) { 412 this.contentType = contentType; 413 } 414 415 public String getAlternateBodyHeader() { 416 return alternateBodyHeader; 417 } 418 419 public void setAlternateBodyHeader(String alternateBodyHeader) { 420 this.alternateBodyHeader = alternateBodyHeader; 421 } 422 423 public boolean isUseInlineAttachments() { 424 return useInlineAttachments; 425 } 426 427 public void setUseInlineAttachments(boolean useInlineAttachments) { 428 this.useInlineAttachments = useInlineAttachments; 429 } 430 }