Java tutorial
/** * * Copyright 2013-2014 OpenSextant.org * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package org.opensextant.xtext.collectors.mailbox; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.security.GeneralSecurityException; import java.util.Properties; import org.apache.commons.lang3.StringUtils; import com.sun.mail.util.MailSSLSocketFactory; import org.opensextant.ConfigException; /** * See reference property file at src/test/resources/collectors/imap-templ.cfg * This IMAP template documents the various parameters for configuring a Java mail client to use IMAP or IMAP/SSL * * @author ubaldino * @author b. o'neill * */ public class MailConfig extends Properties { /** * */ private static final long serialVersionUID = 1L; public static int READ_ALL = -1; public static String DEFAULT_IMAP_PORT = "143"; public static String DEFAULT_IMAPS_PORT = "993"; private boolean debug = false; // These must be provides private String host = null; private String keyStore = null; private String storePass = null; private String trustStore = null; private String username = null; private String password = null; private String mailFolder = "Inbox"; private int maxMessagesToRead = READ_ALL; private boolean readOnly = false; private boolean readNewMessagesOnly = false; private boolean deleteOld = true; private boolean deleteOnRead = true; private int exchangeServer = -1; private boolean isSSL = false; /** * Default mail client configuration that inherits System/OS properties */ public MailConfig() { super(System.getProperties()); } /** * Configure from a file or classpath. Mail client configuration that * inherits System/OS properties, then overrides defaults from parameters in * given confg file. * * @param propsFilePath path to property sheet * @throws IOException on err, likely SSL * @throws ConfigException on err */ public MailConfig(String propsFilePath) throws IOException, ConfigException { super(System.getProperties()); InputStream fileInputStream = null; fileInputStream = new FileInputStream(propsFilePath); this.load(fileInputStream); fileInputStream.close(); setProperties(); } public MailConfig(URL cfgUrl) throws IOException, ConfigException { super(System.getProperties()); if (cfgUrl == null) { throw new ConfigException("Mail Configuration not found"); } InputStream io = cfgUrl.openStream(); this.load(io); io.close(); setProperties(); } /** * Given this configuration, determine if the messages read so far (curr) is * at the total available * * or if config specified a max read count, then if curr > max read, return * true. * * @param total total available. * @param curr current incrementor. * @return true if client/session is done reading available msgs */ public boolean doneReading(int total, int curr) { if (this.getMaxMessagesToRead() < 0) { return curr >= total; } return curr >= getMaxMessagesToRead(); } /** * Set default properties, interpreting System props and any props loaded * from config file. Various flags are set as a result of interpreting the * key/value pairs. * * @throws ConfigException on err */ public void setProperties() throws ConfigException { setProperties(null); } /** * Set properties from existing Property sheet. * * @param props javamail props * @throws ConfigException SSL or other property error */ public void setProperties(Properties props) throws ConfigException { if (props != null) { for (Object o : props.keySet()) { setProperty(o.toString(), props.getProperty((String) o)); } } validateBasicSettings(); setConfiguration(); isSSL = getFlagProperty(getProperty("mail.imap.ssl.enable")); if (isSSL) { validateCertificates(); } try { setAdvancedSettings(); } catch (Exception securityErr) { throw new ConfigException("Advanced settings failed", securityErr); } } /** * * @throws ConfigException SSL-related problem, e.g., keystore does not exist. */ private void validateCertificates() throws ConfigException { if (StringUtils.isBlank(getKeyStore())) { return; } if (!new File(getKeyStore()).exists()) { throw new ConfigException("Keystore set, but is invalid file: " + getKeyStore()); } System.setProperty("javax.net.ssl.keyStore", getKeyStore()); if (StringUtils.isNotBlank(getStorepass())) { System.setProperty("javax.net.ssl.keyStorePassword", getStorepass()); } else { throw new ConfigException("Keystore set, but no store pass provided"); } // Trust Store is relatively unused. No references to it in code. // But may be used under the hood in java-mail API // if (StringUtils.isNotBlank(getTrustStore())) { System.setProperty("javax.net.ssl.trustStore", getTrustStore()); } } private void validateBasicSettings() throws ConfigException { String proto = getProperty("mail.protocol"); if (!("imap".equalsIgnoreCase(proto) || "imaps".equalsIgnoreCase(proto))) { throw new ConfigException("IMAP is only mailbox protocol supported currently"); } } public boolean isSSLEnabled() { return isSSL; } /** * Parameters supported: * * <pre> * ## Mail client behavior * mail.read.count=10 * mail.read.readonly=true * mail.read.newonly=true * mail.read.delete_after=false * mail.delete.purge_old=false * mail.debug=true * * ## Connection * ##################### * mail.host=SERVERSERVER * mail.user=USER * mail.password=XXXXXXXX * mail.folder=Inbox * mail.protocol=imap * * # SSL, Certificates * ##################### * keystore * storepass * truststore * * # Protocol: IMAP * ##################### * mail.imap.starttls.enable=true * mail.imap.socketFactory.fallback=false * mail.imap.socketFactory.port * mail.imap.ssl.enable=true * mail.imap.socketFactory.class=javax.net.SocketFactory * mail.imaps.class=com.sun.mail.IMAPSSLStore * * mail.microsoft.exchange.version=2007 * mail.imap.auth.ntlm.domain=xxxxxDOMAINxxxxx * * * Java Mail params: * mail.imap.auth.ntlm.domain * mail.imap.starttls.enable * mail.imap.socketFactory.fallback * mail.imap.socketFactory.port * mail.imap.ssl.enable * mail.imap.socketFactory.class * * </pre> * @return if relevant javamail properties were set. */ protected boolean setConfiguration() { boolean foundParameters = false; for (Object key : keySet()) { String keyName = key.toString(); String value = getProperty(keyName); if ("mail.host".equals(keyName)) { foundParameters = true; // Required. this.host = value; } else if ("keystore".equals(keyName)) { this.keyStore = value; } else if ("storepass".equals(keyName)) { this.storePass = value; } else if ("truststore".equals(keyName)) { this.trustStore = value; } else if ("mail.user".equals(keyName)) { this.username = value; } else if ("mail.password".equals(keyName)) { this.password = value; } else if ("mail.folder".equals(keyName)) { this.mailFolder = value; } else if ("mail.read.count".equals(keyName)) { this.maxMessagesToRead = getIntegerProperty(value); } else if ("mail.read.readonly".equals(keyName)) { this.readOnly = getFlagProperty(value); } else if ("mail.read.newonly".equals(keyName)) { this.readNewMessagesOnly = getFlagProperty(value); } else if ("mail.delete.purge_old".equals(keyName)) { this.deleteOld = getFlagProperty(value); } else if ("mail.debug".equals(keyName)) { this.debug = getFlagProperty(value); } else if ("mail.read.delete_after".equals(keyName)) { this.deleteOld = getFlagProperty(value); } else if ("mail.microsoft.exchange.version".equals(keyName)) { exchangeServer = getIntegerProperty(value); } } return foundParameters; } /** * A conveneince wrapper around setting the SSL socket factory and other parameters. * @throws GeneralSecurityException error related to mail/socket factory or other issue */ public void setAdvancedSettings() throws GeneralSecurityException { if (this.isSSLEnabled()) { MailSSLSocketFactory socketFactory = new MailSSLSocketFactory(); socketFactory.setTrustAllHosts(true); this.put("mail.imaps.ssl.socketFactory", socketFactory); // Default? // setProperty("mail.imap.socketFactory.class", // "javax.net.ssl.SSLSocketFactory"); } } public String getDefaultPort(boolean useSSL) { return (useSSL ? DEFAULT_IMAPS_PORT : DEFAULT_IMAP_PORT); } /** * Return -1 if unknown or if it does not matter. 2003, 2007, 2010 * * @return int representing year/version of MS Exchange */ public int getExchangeServerVersion() { return exchangeServer; } /** * Defaults to -1 if no value found * * @param val property * @return parsed int */ protected static int getIntegerProperty(Object val) { if (val == null) { return -1; } return Integer.parseInt(val.toString()); } /** * get a flag. DEFAULT: false * * @param val property value * @return parsed boolean */ protected static boolean getFlagProperty(Object val) { if (val == null) { return false; } return Boolean.parseBoolean(val.toString()); } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public String getKeyStore() { return keyStore; } public void setKeyStore(String keyStore) { this.keyStore = keyStore; } public String getStorepass() { return storePass; } public void setStorepass(String keyStoreKey) { this.storePass = keyStoreKey; } public String getTrustStore() { return trustStore; } public void setTrustStore(String trustStore) { this.trustStore = trustStore; } public String getUsername() { return username; } public void setUsername(String userName) { this.username = userName; } public String getPassword() { return password; } public void setPassword(String userKey) { this.password = userKey; } public String getMailFolder() { return mailFolder; } public void setMailFolder(String mailFolder) { this.mailFolder = mailFolder; } public int getMaxMessagesToRead() { return maxMessagesToRead; } public void setMaxMessagesToRead(int maxMessagesToRead) { if (maxMessagesToRead <= READ_ALL) { this.maxMessagesToRead = READ_ALL; } else { this.maxMessagesToRead = maxMessagesToRead; } } public boolean isReadOnly() { return readOnly; } public void setReadOnly(boolean readOnly) { this.readOnly = readOnly; } public boolean isReadNewMessagesOnly() { return readNewMessagesOnly; } public void setReadNewMessagesOnly(boolean readNewMessagesOnly) { this.readNewMessagesOnly = readNewMessagesOnly; } public boolean isDeleteOld() { return deleteOld; } public void setDeleteOld(boolean deleteOld) { this.deleteOld = deleteOld; } public boolean isDebug() { return debug; } public void setDebug(boolean debug) { this.debug = debug; } public boolean isDeleteOnRead() { return deleteOnRead; } public void setDeleteOnRead(boolean deleteOnRead) { this.deleteOnRead = deleteOnRead; } }