/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2009-2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
package org.opennms.javamail;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.MimeMultipart;
import javax.mail.search.SearchTerm;
import org.apache.commons.lang.StringUtils;
import org.opennms.netmgt.config.javamail.JavamailProperty;
import org.opennms.netmgt.config.javamail.ReadmailConfig;
/*
* TODO Handy API things I've found that should be implemented
*
Message[] msgs = new Message[mailFolder.getMessageCount()];
int unReadCnt = mailFolder.getUnreadMessageCount();
int newCnt = mailFolder.getNewMessageCount();
int delCnt = mailFolder.getUnreadMessageCount();
FetchProfile fp = new FetchProfile();
fp.add(FetchProfile.Item.FLAGS);
fp.add(FetchProfileItem.FLAGS);
mailFolder.fetch(msgs, fp);
SearchTerm st = new SubjectTerm(subjectMatch);
*/
/**
* JavaMail implementation for reading electronic mail.
*
* @author <a href="mailto:david@opennms.org">David Hustace</a>
* @version $Id: $
*/
public class JavaReadMailer extends JavaMailer2 {
private List<Message> m_messages;
final private ReadmailConfig m_config;
private Session m_session;
private Boolean m_deleteOnClose = false;
private Store m_store;
/**
* {@inheritDoc}
*
* Finalizer to be sure and close with the appropriate mode
* any open folders
*/
@Override
protected void finalize() throws Throwable {
log().debug("finalize: cleaning up mail folder an store connections...");
if (m_messages != null && !m_messages.isEmpty() && m_messages.get(0).getFolder() != null && m_messages.get(0).getFolder().isOpen()) {
m_messages.get(0).getFolder().close(m_deleteOnClose);
}
if (m_store.isConnected()) {
m_store.close();
}
super.finalize();
log().debug("finalize: Mail folder and store connections closed.");
}
//TODO figure out why need this throws here
/**
* <p>Constructor for JavaReadMailer.</p>
*
* @param config a {@link org.opennms.netmgt.config.javamail.ReadmailConfig} object.
* @param closeOnDelete a {@link java.lang.Boolean} object.
* @throws org.opennms.javamail.JavaMailerException if any.
*/
public JavaReadMailer(final ReadmailConfig config, Boolean closeOnDelete) throws JavaMailerException {
if (closeOnDelete != null) {
m_deleteOnClose = closeOnDelete;
}
m_config = config;
m_session = Session.getInstance(configureProperties(), createAuthenticator(config.getUserAuth().getUserName(), config.getUserAuth().getPassword()));
}
/**
* <p>retrieveMessages</p>
*
* @return a {@link java.util.List} object.
* @throws org.opennms.javamail.JavaMailerException if any.
*/
public List<Message> retrieveMessages() throws JavaMailerException {
Message[] msgs;
Folder mailFolder = null;
try {
m_store = m_session.getStore(m_config.getReadmailHost().getReadmailProtocol().getTransport());
m_store.connect(m_config.getReadmailHost().getHost(), (int)m_config.getReadmailHost().getPort(), m_config.getUserAuth().getUserName(), m_config.getUserAuth().getPassword());
mailFolder = m_store.getFolder(m_config.getMailFolder());
mailFolder.open(Folder.READ_WRITE);
msgs = mailFolder.getMessages();
} catch (NoSuchProviderException e) {
throw new JavaMailerException("No provider matching:"+m_config.getReadmailHost().getReadmailProtocol().getTransport()+" from config:"+m_config.getName(), e);
} catch (MessagingException e) {
throw new JavaMailerException("Problem reading messages from configured mail store", e);
}
return new ArrayList<Message>(Arrays.asList(msgs));
}
/*
* TODO: Need readers that:
* - use FetchProfiles
* - make use of pre-fetch nature of getMessages()
* - A reader for the entire system could be implemented using events/event listeners
* TODO: Need to make this more efficient... probably needs state so that message contents can be retrieved from the
* store after they are read via this message.
*/
/**
* <p>retrieveMessages</p>
*
* @param term a {@link javax.mail.search.SearchTerm} object.
* @return a {@link java.util.List} object.
* @throws org.opennms.javamail.JavaMailerException if any.
*/
public List<Message> retrieveMessages(SearchTerm term) throws JavaMailerException {
Message[] msgs;
Folder mailFolder = null;
try {
Store store = m_session.getStore(m_config.getReadmailHost().getReadmailProtocol().getTransport());
store.connect(m_config.getReadmailHost().getHost(), (int)m_config.getReadmailHost().getPort(), m_config.getUserAuth().getUserName(), m_config.getUserAuth().getPassword());
mailFolder = store.getFolder(m_config.getMailFolder());
mailFolder.open(Folder.READ_WRITE);
msgs = mailFolder.search(term);
} catch (NoSuchProviderException e) {
throw new JavaMailerException("No provider matching:"+m_config.getReadmailHost().getReadmailProtocol().getTransport()+" from config:"+m_config.getName(), e);
} catch (MessagingException e) {
throw new JavaMailerException("Problem reading messages from configured mail store", e);
}
List<Message> msgList = Arrays.asList(msgs);
return msgList;
}
/**
* Configures the java mail api properties based on the settings ReadMailConfig
* @return A set of javamail properties based on the mail configuration
*/
private Properties configureProperties() {
Properties props = new Properties();
props.setProperty("mail.debug", String.valueOf(m_config.isDebug()));
//first set the actual properties defined in the sendmail configuration
List<JavamailProperty> jmps = m_config.getJavamailPropertyCollection();
for (JavamailProperty jmp : jmps) {
props.setProperty(jmp.getName(), jmp.getValue());
}
String protocol = m_config.getReadmailHost().getReadmailProtocol().getTransport();
props.put("mail." + protocol + ".host", m_config.getReadmailHost().getHost());
props.put("mail." + protocol + ".user", m_config.getUserAuth().getUserName());
props.put("mail." + protocol + ".port", m_config.getReadmailHost().getPort());
props.put("mail." + protocol + ".starttls.enable", m_config.getReadmailHost().getReadmailProtocol().isStartTls());
props.put("mail.smtp.auth", "true");
if (m_config.getReadmailHost().getReadmailProtocol().isSslEnable()) {
props.put("mail." + protocol + ".socketFactory.port", m_config.getReadmailHost().getPort());
props.put("mail." + protocol + ".socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail." + protocol + ".socketFactory.fallback", "false");
}
//FIXME: need config for these
props.put("mail." + protocol + ".connectiontimeout", 3000);
props.put("mail." + protocol + ".timeout", 3000);
props.put("mail.store.protocol", protocol);
return props;
}
/**
* <p>getMessages</p>
*
* @return a {@link java.util.List} object.
*/
public List<Message> getMessages() {
return m_messages;
}
/**
* Attempts to reteive the string portion of a message... tries to handle
* multipart messages as well. This seems to be working so far with my tests
* but could use some tweaking later as more types of mail servers are used
* with this feature.
*
* @param msg a {@link javax.mail.Message} object.
* @return The text portion of an email with each line being an element of the list.
* @throws javax.mail.MessagingException if any.
* @throws java.io.IOException if any.
*/
public static List<String> getText(Message msg) throws MessagingException, IOException {
Object content = null;
String text = null;
log().debug("getText: getting text of message from MimeType: text/*");
try {
text = (String)msg.getContent();
} catch (ClassCastException cce) {
content = msg.getContent();
if (content instanceof MimeMultipart) {
log().debug("getText: content is MimeMultipart, checking for text from each part...");
for (int cnt = 0; cnt < ((MimeMultipart)content).getCount(); cnt++) {
BodyPart bp = ((MimeMultipart)content).getBodyPart(cnt);
if (bp.isMimeType("text/*")) {
text = (String)bp.getContent();
log().debug("getText: found text MIME type: "+text);
break;
}
}
log().debug("getText: did not find text within MimeMultipart message.");
}
}
return string2Lines(text);
}
/**
* <p>isDeleteOnClose</p>
*
* @return a {@link java.lang.Boolean} object.
*/
public Boolean isDeleteOnClose() {
return m_deleteOnClose;
}
/**
* <p>setDeleteOnClose</p>
*
* @param deleteOnClose a {@link java.lang.Boolean} object.
*/
public void setDeleteOnClose(Boolean deleteOnClose) {
m_deleteOnClose = deleteOnClose;
}
/**
* <p>string2Lines</p>
*
* @param text a {@link java.lang.String} object.
* @return a {@link java.util.List} object.
*/
public static List<String> string2Lines(String text) {
if (text == null) {
return null;
}
String[] linea = StringUtils.split(text, "\n");
for (int i = 0; i < linea.length; i++) {
linea[i] = StringUtils.chomp(linea[i]);
}
return Arrays.asList(linea);
}
}