first commit
This commit is contained in:
@ -0,0 +1,241 @@
|
||||
package de.muehlencord.shared.network.ftp;
|
||||
|
||||
import com.enterprisedt.net.ftp.FTPClient;
|
||||
import com.enterprisedt.net.ftp.FTPConnectMode;
|
||||
import com.enterprisedt.net.ftp.FTPException;
|
||||
import com.enterprisedt.net.ftp.FTPFile;
|
||||
import de.muehlencord.shared.util.StringUtil;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern@muehlencord.de
|
||||
*/
|
||||
public class FTPConnection {
|
||||
|
||||
/** the default timeout in ms */
|
||||
public static final int DEFAULTTIMEOUT = 30000;
|
||||
/** the logger object */
|
||||
private final Logger logger = Logger.getLogger(FTPConnection.class);
|
||||
/** the username to connect with */
|
||||
private String userName;
|
||||
/** the password to connect with */
|
||||
private String password;
|
||||
/** the ftp client to use */
|
||||
private FTPClient client;
|
||||
/** the remote host to connect to */
|
||||
private String remoteHost;
|
||||
/** the locale of the client to use */
|
||||
private Locale clientLocale;
|
||||
|
||||
/**
|
||||
* creates a new ftp connection
|
||||
*
|
||||
* @param remoteHost the host to connect to
|
||||
* @param userName the user to connect with
|
||||
* @param password the password to connect with
|
||||
*/
|
||||
public FTPConnection(String remoteHost, String userName, String password) {
|
||||
this(remoteHost, userName, password, Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a new ftp connection
|
||||
*
|
||||
* @param remoteHost the host to connect to
|
||||
* @param userName the user to connect with
|
||||
* @param password the password to connect with
|
||||
* @param clientLocale the locale to use for the client
|
||||
*/
|
||||
public FTPConnection(String remoteHost, String userName, String password, Locale clientLocale) {
|
||||
this.remoteHost = remoteHost;
|
||||
this.userName = userName;
|
||||
this.password = password;
|
||||
this.clientLocale = clientLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* connects the ftp client to the remote host
|
||||
*
|
||||
* @throws FTPConnectionException if the command cannot be executed
|
||||
*/
|
||||
public void connect() throws FTPConnectionException {
|
||||
try {
|
||||
client = new FTPClient();
|
||||
client.setConnectMode(FTPConnectMode.PASV);
|
||||
client.setParserLocale(clientLocale);
|
||||
client.setRemoteHost(remoteHost);
|
||||
client.setTimeout(DEFAULTTIMEOUT);
|
||||
client.connect();
|
||||
client.login(userName, password);
|
||||
} catch (Exception ex) {
|
||||
throw new FTPConnectionException("Error while connecting to ftp client. Reason: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/** disconnects the ftp client from the remote host */
|
||||
public void disconnect() {
|
||||
try {
|
||||
client.quit();
|
||||
} catch (IOException ex) {
|
||||
logger.error(ex.getMessage());
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
} catch (FTPException ex) {
|
||||
logger.error(ex.getMessage());
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a list of files (as string) found in the given directory
|
||||
*
|
||||
* @param dir the directory to return the list for
|
||||
* @return a list of files (as string) found in the given directory
|
||||
*
|
||||
* @throws FTPConnectionException if the command cannot be executed
|
||||
*/
|
||||
public List<String> list(String dir) throws FTPConnectionException {
|
||||
List<String> returnValue = new LinkedList<String>();
|
||||
try {
|
||||
FTPFile[] files = client.dirDetails(dir);
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
returnValue.add(files[i].getName());
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.error(ex.getMessage());
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
throw new FTPConnectionException("Error while getting diretoy listing. Reason: " + ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a list of directories contained in given directory
|
||||
*
|
||||
* @param dir the directory to return the subfolders for
|
||||
* @return a list of subfolders of the given directory
|
||||
*
|
||||
* @throws FTPConnectionException if the command cannot be executed
|
||||
*/
|
||||
public List<String> listDirsOnly(String dir) throws FTPConnectionException {
|
||||
List<String> returnValue = new LinkedList<String>();
|
||||
try {
|
||||
FTPFile[] files = client.dirDetails(dir);
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
if (files[i].isDir()) {
|
||||
returnValue.add(files[i].getName());
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.error(ex.getMessage());
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
throw new FTPConnectionException("Error while getting diretoy listing. Reason: " + ex.getMessage(), ex);
|
||||
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a list of files contained in the given folder
|
||||
*
|
||||
* @param dir the directory to list
|
||||
* @return a list of files contained in the given folder
|
||||
*
|
||||
* @throws FTPConnectionException if the command cannot be executed
|
||||
*/
|
||||
public List<String> listFilesOnly(String dir) throws FTPConnectionException {
|
||||
List<String> returnValue = new LinkedList<String>();
|
||||
try {
|
||||
FTPFile[] files = client.dirDetails(dir);
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
if (!files[i].isDir()) {
|
||||
returnValue.add(files[i].getName());
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.error(ex.getMessage());
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
throw new FTPConnectionException("Error while getting diretoy listing. Reason: " + ex.getMessage(), ex);
|
||||
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a list of links contained in the given folder
|
||||
*
|
||||
* @param dir the directory to list
|
||||
* @return a list of links contained in the given folder
|
||||
*
|
||||
* @throws FTPConnectionException if the command cannot be executed
|
||||
*/
|
||||
public List<String> listLinksOnly(String dir) throws FTPConnectionException {
|
||||
List<String> returnValue = new LinkedList<String>();
|
||||
try {
|
||||
FTPFile[] files = client.dirDetails(dir);
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
if (files[i].isLink()) {
|
||||
returnValue.add(files[i].getName());
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.error(ex.getMessage());
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
throw new FTPConnectionException("Error while getting diretoy listing. Reason: " + ex.getMessage(), ex);
|
||||
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* uploads the given file and stores it under the given remote filename - including path
|
||||
*
|
||||
* @param localFilename the path and filename of the source file
|
||||
* @param remoteFileName the path and filename of the destination file
|
||||
* @throws FTPConnectionException if the command cannot be executed
|
||||
*/
|
||||
public void uploadFile(String localFilename, String remoteFileName) throws FTPConnectionException {
|
||||
|
||||
try {
|
||||
client.setDetectTransferMode(true);
|
||||
if ((remoteFileName != null) && !remoteFileName.equals("")) {
|
||||
client.put(localFilename, remoteFileName, false);
|
||||
} else {
|
||||
File f = new File(localFilename);
|
||||
String remoteName = f.getName();
|
||||
client.put(localFilename, remoteName, false);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.error(ex.getMessage());
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
throw new FTPConnectionException("Error while uploading file. Reason: " + ex.getMessage(), ex);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* renames a file on the remote host
|
||||
*
|
||||
* @param remoteOldName the current file name
|
||||
* @param remoteNewName the new file name
|
||||
* @throws FTPConnectionException if the command cannot be executed
|
||||
*/
|
||||
public void rename(String remoteOldName, String remoteNewName) throws FTPConnectionException {
|
||||
try {
|
||||
client.rename(remoteOldName, remoteNewName);
|
||||
} catch (Exception ex) {
|
||||
logger.error(ex.getMessage());
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
throw new FTPConnectionException("Error while renaming file. Reason: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package de.muehlencord.shared.network.ftp;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jomu
|
||||
*/
|
||||
public class FTPConnectionException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 4393979078434188521L;
|
||||
|
||||
/**
|
||||
* Creates a new instance of
|
||||
* <code>FTPConnectionException</code> without detail message.
|
||||
*/
|
||||
public FTPConnectionException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of
|
||||
* <code>FTPConnectionException</code> with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public FTPConnectionException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of
|
||||
* <code>FTPConnectionException</code> with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
* @param th the causing exception
|
||||
*/
|
||||
public FTPConnectionException(String msg, Throwable th) {
|
||||
super(msg, th);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,263 @@
|
||||
package de.muehlencord.shared.network.http;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Communication endpoint for posting a messages
|
||||
*
|
||||
* @author joern@muehlencord.de
|
||||
*/
|
||||
public class HttpLayer {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(HttpLayer.class);
|
||||
/** the url to post to */
|
||||
private String destinationUrlString;
|
||||
/** the encoding to use */
|
||||
private String encoding;
|
||||
|
||||
/**
|
||||
* creates a new http layer which can communicate with the given url
|
||||
*
|
||||
* @param urlString
|
||||
* the url to communicate with
|
||||
*/
|
||||
public HttpLayer(String urlString) {
|
||||
this.destinationUrlString = urlString;
|
||||
this.encoding = "UTF-8";
|
||||
}
|
||||
|
||||
/**
|
||||
* posts the value of message into the varialbe parameter
|
||||
*
|
||||
* @param parameter
|
||||
* the parameter to write the message to
|
||||
* @param message
|
||||
* the message to post
|
||||
* @throws MessageNotSendException
|
||||
* if the message cannot be sent
|
||||
*/
|
||||
public void post(String parameter, String message)
|
||||
throws MessageNotSendException {
|
||||
Map<String, String[]> parameterMap = new HashMap<String, String[]>();
|
||||
String[] valueArray = { message };
|
||||
parameterMap.put(parameter, valueArray);
|
||||
post(parameterMap);
|
||||
}
|
||||
|
||||
public void post(List<Map<String, String[]>> parameterMap)
|
||||
throws MessageNotSendException {
|
||||
// construct string to post
|
||||
String content = getDataString(parameterMap);
|
||||
post(content);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* posts the parameters and values specified by the parameter map to the
|
||||
* configured url
|
||||
*
|
||||
* @param parameterMap
|
||||
* the parameter map to post
|
||||
* @throws MessageNotSendException
|
||||
* if the http / post request cannot be executed
|
||||
*
|
||||
* TODO add https support
|
||||
*/
|
||||
public void post(Map<String, String[]> parameterMap) throws MessageNotSendException {
|
||||
List<Map<String,String[]>> parameterList = new LinkedList<Map<String,String[]>>();
|
||||
parameterList.add(parameterMap);
|
||||
String content = getDataString(parameterList);
|
||||
post (content);
|
||||
}
|
||||
|
||||
private void post(String messageString) throws MessageNotSendException {
|
||||
// check URL string and return URL object if valid; otherwise
|
||||
// MessageNotSendException is thrown
|
||||
URLConnection urlConn = getUrlConnection();
|
||||
|
||||
// post data
|
||||
IOException exceptionDuringPost = null;
|
||||
OutputStream outputStream = null;
|
||||
DataOutputStream printout = null;
|
||||
try {
|
||||
outputStream = urlConn.getOutputStream();
|
||||
printout = new DataOutputStream(outputStream);
|
||||
printout.writeBytes(messageString);
|
||||
printout.flush();
|
||||
logger.info("Message sent successfully");
|
||||
} catch (IOException ioex) {
|
||||
// store received exception but first get output and
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(ioex);
|
||||
}
|
||||
exceptionDuringPost = ioex;
|
||||
} finally {
|
||||
if (outputStream != null) {
|
||||
try {
|
||||
outputStream.close();
|
||||
} catch (IOException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (printout != null) {
|
||||
try {
|
||||
printout.close();
|
||||
|
||||
} catch (IOException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get response message
|
||||
StringBuilder sb = new StringBuilder();
|
||||
InputStreamReader inputStreamReader = null;
|
||||
BufferedReader bufferedReader = null;
|
||||
try {
|
||||
inputStreamReader = new InputStreamReader(urlConn.getInputStream());
|
||||
bufferedReader = new BufferedReader(inputStreamReader);
|
||||
while (bufferedReader.ready()) {
|
||||
sb.append(bufferedReader.readLine());
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Response from server");
|
||||
logger.debug(sb.toString());
|
||||
}
|
||||
|
||||
} catch (IOException ioex) {
|
||||
logger.error(ioex);
|
||||
exceptionDuringPost = ioex;
|
||||
} finally {
|
||||
if (bufferedReader != null) {
|
||||
try {
|
||||
bufferedReader.close();
|
||||
} catch (IOException ex) {
|
||||
logger.error(ex.getMessage());
|
||||
}
|
||||
}
|
||||
if (inputStreamReader != null) {
|
||||
try {
|
||||
inputStreamReader.close();
|
||||
} catch (IOException ex) {
|
||||
logger.error(ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (exceptionDuringPost != null) {
|
||||
String hint = "Error while sending message. Reason: "
|
||||
+ exceptionDuringPost.getMessage();
|
||||
logger.error(hint);
|
||||
throw new MessageNotSendException(hint, exceptionDuringPost);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param urlString
|
||||
* the url to check
|
||||
* @return a URl object created from the given urlString
|
||||
* @throws MessageNotSendException
|
||||
* if the url is invalid
|
||||
*/
|
||||
private URLConnection getUrlConnection() throws MessageNotSendException {
|
||||
URLConnection urlConn;
|
||||
URL url;
|
||||
try {
|
||||
url = new URL(destinationUrlString);
|
||||
} catch (MalformedURLException ex) {
|
||||
String hint = "Cannot send message to url - invalid url "
|
||||
+ destinationUrlString;
|
||||
logger.error(hint);
|
||||
throw new MessageNotSendException(hint, ex);
|
||||
}
|
||||
String protocol = url.getProtocol().toLowerCase();
|
||||
if (!protocol.equals("http")) {
|
||||
String hint = "protocol " + protocol + " not supported";
|
||||
logger.error(hint);
|
||||
throw new MessageNotSendException(hint);
|
||||
}
|
||||
|
||||
// setup url connection
|
||||
try {
|
||||
// URL connection channel.
|
||||
urlConn = url.openConnection();
|
||||
// Let the run-time system (RTS) know that we want input.
|
||||
urlConn.setDoInput(true);
|
||||
// Let the RTS know that we want to do output.
|
||||
urlConn.setDoOutput(true);
|
||||
// No caching, we want the real thing.
|
||||
urlConn.setUseCaches(false);
|
||||
// Specify the content type.
|
||||
urlConn.setRequestProperty("Content-Type",
|
||||
"application/x-www-form-urlencoded");
|
||||
} catch (IOException ioex) {
|
||||
String hint = "Error while setting up connection. Reason: "
|
||||
+ ioex.getMessage();
|
||||
logger.error(hint);
|
||||
throw new MessageNotSendException(hint, ioex);
|
||||
}
|
||||
|
||||
return urlConn;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the data string to post based on the given parameter map
|
||||
*
|
||||
* @param parameterMap
|
||||
* the parameter map to construct the data string from
|
||||
* @return the data string to post
|
||||
* @throws MessageNotSendException
|
||||
* if the datastring cannot be constructed
|
||||
*/
|
||||
private String getDataString(List<Map<String, String[]>> parameterList)
|
||||
throws MessageNotSendException {
|
||||
// perpare data
|
||||
String data = "";
|
||||
for (Map<String,String[]> parameterMap : parameterList) {
|
||||
try {
|
||||
Iterator<String> keyIterator = parameterMap.keySet().iterator();
|
||||
while (keyIterator.hasNext()) {
|
||||
String key = keyIterator.next();
|
||||
String[] valueArray = parameterMap.get(key);
|
||||
for (String currentValue : valueArray) {
|
||||
if (!data.equals("")) {
|
||||
data += "&";
|
||||
}
|
||||
data += key.toLowerCase() + "="
|
||||
+ URLEncoder.encode(currentValue, encoding);
|
||||
}
|
||||
}
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
String hint = "Error while preparing data for message. Unknown encoding "
|
||||
+ encoding;
|
||||
logger.error(hint);
|
||||
throw new MessageNotSendException(hint, ex);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package de.muehlencord.shared.network.http;
|
||||
|
||||
/**
|
||||
* This message is thrown if a message cannot be sent
|
||||
* @author joern@muehlencord.de
|
||||
*/
|
||||
public class MessageNotSendException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -8959773341187046577L;
|
||||
|
||||
/**
|
||||
* Creates a new instance of
|
||||
* <code>MessageNotSendException</code> without detail message.
|
||||
*/
|
||||
public MessageNotSendException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of
|
||||
* <code>MessageNotSendException</code> with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public MessageNotSendException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of
|
||||
* <code>MessageNotSendException</code> with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
* @param th the causing exception
|
||||
*/
|
||||
public MessageNotSendException(String msg, Throwable th) {
|
||||
super(msg, th);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,485 @@
|
||||
package de.muehlencord.shared.network.mail;
|
||||
|
||||
import de.muehlencord.shared.util.StringUtil;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Level;
|
||||
import javax.mail.Flags;
|
||||
import javax.mail.Folder;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.Store;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import javax.mail.search.MessageIDTerm;
|
||||
import javax.mail.search.SearchTerm;
|
||||
import javax.mail.util.SharedByteArrayInputStream;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* MailReader to connect and work with IMAP mailboxes. Also works with exchange servers.
|
||||
*
|
||||
* @author joern@muehlencord.de
|
||||
*/
|
||||
public abstract class DefaultMailReader implements MailReader {
|
||||
|
||||
/** the logging object */
|
||||
private final static Logger logger = Logger.getLogger(DefaultMailReader.class);
|
||||
/** the store to connect with */
|
||||
private Store store = null;
|
||||
/** the smtp host to work with */
|
||||
private final MailReaderConfiguration configuration;
|
||||
|
||||
/**
|
||||
* creates a new instance of the DefaultMailReader and updates needed values and settings
|
||||
*
|
||||
* @param config the configuration for the reader
|
||||
*/
|
||||
public DefaultMailReader(MailReaderConfiguration config) {
|
||||
this.configuration = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* onnects to the mailbox
|
||||
*
|
||||
* @throws MailReaderConnectionException if the connection cannot be established
|
||||
*/
|
||||
@Override
|
||||
public abstract void connect() throws MailReaderConnectionException;
|
||||
|
||||
/** disconnects from mailbox */
|
||||
@Override
|
||||
public void disconnect() {
|
||||
if (getStore() != null) {
|
||||
try {
|
||||
getStore().close();
|
||||
} catch (MessagingException ex) {
|
||||
logger.error("Cannot disconnect from mailbox");
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
} finally {
|
||||
logger.info("Connection closed");
|
||||
setStore(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** returns the default folder
|
||||
*
|
||||
* @return the default folder
|
||||
*
|
||||
* @throws MailReaderException if the default folder cannot be found
|
||||
*/
|
||||
@Override
|
||||
public String getDefaultFolder() throws MailReaderException {
|
||||
|
||||
try {
|
||||
return getStore().getDefaultFolder().getFullName();
|
||||
} catch (Exception ex) {
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
throw new MailReaderException("Error while retrieving default folder. Reason: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the list of subfolders of the specified source folder
|
||||
*
|
||||
* @param sourceFolder the folder to return the folder list for
|
||||
* @return the list of subfolders of the specified source folder
|
||||
*
|
||||
* @throws MailReaderException if the folder list cannot be retrieved
|
||||
*/
|
||||
public List<String> getSubFolder(Folder sourceFolder) throws MailReaderException {
|
||||
List<String> returnValue = new LinkedList<String>();
|
||||
try {
|
||||
Folder[] folders = sourceFolder.list();
|
||||
for (Folder folder : folders) {
|
||||
returnValue.add(folder.getFullName());
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
throw new MailReaderException("Cannot retrieve folder list. Reason: " + ex.getMessage(), ex);
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the session object to use
|
||||
*
|
||||
* @return the session object to use
|
||||
*/
|
||||
protected Session getDefaultSession() {
|
||||
Properties props = (Properties) System.getProperties().clone();
|
||||
props.put("mail.smtp.host", configuration.getSmtpHost());
|
||||
// TODO - add needed properties - only valid for session, do not overwrite properites
|
||||
// TODO - add chained properties
|
||||
return Session.getInstance(props, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the store
|
||||
*/
|
||||
protected Store getStore() {
|
||||
return store;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param store the store to set
|
||||
*/
|
||||
protected void setStore(Store store) {
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the configuration object
|
||||
*
|
||||
* @return returns the configuration
|
||||
*/
|
||||
protected MailReaderConfiguration getConfiguration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the folder, if folder path is a valid path to an existing folder
|
||||
*
|
||||
* @param folderPath the folder to return
|
||||
* @return the folder, if folder path is a valid path to an existing folder
|
||||
*
|
||||
* @throws MailReaderException if the folder cannot be found
|
||||
*/
|
||||
private List<Folder> getFolderPath(String folderPath) throws MailReaderException {
|
||||
List<Folder> returnValue = new LinkedList<Folder>();
|
||||
try {
|
||||
String[] folderPathParts = folderPath.split("/");
|
||||
Folder currentFolder = store.getDefaultFolder();
|
||||
boolean stillExists = true;
|
||||
|
||||
for (int i = 0; ((i < folderPathParts.length) && (stillExists)); i++) {
|
||||
currentFolder = currentFolder.getFolder(folderPathParts[i]);
|
||||
stillExists = currentFolder.exists();
|
||||
returnValue.add(currentFolder);
|
||||
}
|
||||
|
||||
if (stillExists) {
|
||||
return returnValue;
|
||||
} else {
|
||||
throw new MailReaderException("Folder " + folderPath + " not found");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new MailReaderException("Error while getting older " + folderPath + ". Reason: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the folder object defined by the folder path
|
||||
*
|
||||
* @param sourceFolder the full name of the folder (including path)
|
||||
* @return the folder object if existent
|
||||
*
|
||||
* @throws MailReaderException if the folder does not exist
|
||||
*/
|
||||
private Folder getFolderObject(String sourceFolder) throws MailReaderException {
|
||||
List<Folder> folderList = getFolderPath(sourceFolder);
|
||||
return folderList.get(folderList.size() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the folder, if folder path is a valid path to an existing folder
|
||||
*
|
||||
* @param folderPath the folder to return
|
||||
* @return the folder, if folder path is a valid path to an existing folder
|
||||
*
|
||||
* @throws MailReaderException if the folder cannot be found
|
||||
*/
|
||||
@Override
|
||||
public String getFolder(String folderPath) throws MailReaderException {
|
||||
String returnValue = "";
|
||||
List<Folder> folderList = getFolderPath(folderPath);
|
||||
for (Folder folder : folderList) {
|
||||
returnValue += folder.getName() + "/";
|
||||
}
|
||||
if (returnValue.endsWith("/")) {
|
||||
returnValue = returnValue.substring(0, returnValue.length() - 1);
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the list of subfolders of the specified source folder
|
||||
*
|
||||
* @param sourceFolder the folder to return the folder list for
|
||||
* @return the list of subfolders of the specified source folder
|
||||
*
|
||||
* @throws MailReaderException if the folder list cannot be retrieved
|
||||
*/
|
||||
@Override
|
||||
public List<String> getSubFolder(String sourceFolder) throws MailReaderException {
|
||||
List<String> returnValue = new LinkedList<String>();
|
||||
Folder folder = getFolderObject(sourceFolder);
|
||||
|
||||
try {
|
||||
folder.open(Folder.READ_ONLY);
|
||||
Folder[] subFolders = folder.list();
|
||||
for (Folder subFolder : subFolders) {
|
||||
returnValue.add(subFolder.getFullName());
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new MailReaderException("Error while getting subfolders. Reason: " + ex.getMessage(), ex);
|
||||
} finally {
|
||||
if ((folder != null) && folder.isOpen()) {
|
||||
try {
|
||||
folder.close(false);
|
||||
} catch (MessagingException ex) {
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the message count for the given folder
|
||||
*
|
||||
* @param sourceFolder the folder to return the message count for
|
||||
* @return the message count for the given folder
|
||||
*
|
||||
* @throws MailReaderException if the amount of messages cannot be determined
|
||||
*/
|
||||
@Override
|
||||
public int getMessageCount(String sourceFolder) throws MailReaderException {
|
||||
Folder folder = getFolderObject(sourceFolder);
|
||||
int messageCount;
|
||||
try {
|
||||
|
||||
folder.open(Folder.READ_ONLY);
|
||||
messageCount = folder.getMessageCount();
|
||||
} catch (Exception ex) {
|
||||
throw new MailReaderException("Error while getting messageCount. Reason:" + ex.getMessage(), ex);
|
||||
} finally {
|
||||
if ((folder != null) && folder.isOpen()) {
|
||||
try {
|
||||
folder.close(false);
|
||||
} catch (MessagingException ex) {
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
}
|
||||
}
|
||||
}
|
||||
return messageCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieves the list of messages stored in the given folder
|
||||
*
|
||||
* @param sourceFolder the folder to search return the emails for
|
||||
* @return list of messages stored in the given folder
|
||||
*
|
||||
* @throws MailReaderException if the message list cannot be retrieved
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public List<MailMessage> getMessages(String sourceFolder) throws MailReaderException {
|
||||
List<MailMessage> returnValue = new LinkedList<MailMessage>();
|
||||
Folder folder = getFolderObject(sourceFolder);
|
||||
try {
|
||||
folder.open(Folder.READ_ONLY);
|
||||
Message[] messages = folder.getMessages();
|
||||
for (Message msg : messages) {
|
||||
returnValue.add(MailMessageUtils.getInstance(getValidMessage(msg)));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new MailReaderException("Cannot fetch email from folder " + folder.getFullName() + ". Reason: " + ex.getMessage(), ex);
|
||||
|
||||
} finally {
|
||||
if ((folder != null) && (folder.isOpen())) {
|
||||
try {
|
||||
folder.close(false);
|
||||
} catch (MessagingException ex) {
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* copies the given message from the source folder to the destination folder
|
||||
*
|
||||
* @param mm the message to copy
|
||||
* @param sourceFolder the folder the message currently resists in
|
||||
* @param destFolder the folder the message should be copied to
|
||||
* @throws MailReaderException if the operation fails
|
||||
*/
|
||||
@Override
|
||||
public void copyMessage(MailMessage mm, String sourceFolder, String destFolder) throws MailReaderException {
|
||||
copyMessages(mm, sourceFolder, destFolder, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* moves the given message from the source folder to the destination folder
|
||||
*
|
||||
* @param mm the message to move
|
||||
* @param sourceFolder the folder the message currently resists in
|
||||
* @param destFolder the folder the message should be moved to
|
||||
* @throws MailReaderException if the operation fails
|
||||
*/
|
||||
@Override
|
||||
public void moveMessage(MailMessage mm, String sourceFolder, String destFolder) throws MailReaderException {
|
||||
copyMessages(mm, sourceFolder, destFolder, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* marks the messages as seen
|
||||
*
|
||||
* @param folderName the folder to search for the email
|
||||
* @param mm the message to mark as seen
|
||||
* @param flagValue if set to true, the seen flag is set; otherwise it is removed (unset)
|
||||
* @throws MailReaderException if the flag cannot be set
|
||||
*/
|
||||
@Override
|
||||
public void setSeenFlag(String folderName, MailMessage mm, boolean flagValue) throws MailReaderException {
|
||||
Folder folder = getFolderObject(folderName);
|
||||
try {
|
||||
folder.open(Folder.READ_WRITE);
|
||||
Message[] msgs = getMessage(folder, mm.getMessageId());
|
||||
|
||||
for (Message message : msgs) {
|
||||
message.setFlag(Flags.Flag.SEEN, true);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new MailReaderException("Cannot set seen flag. Reason: " + ex.getMessage(), ex);
|
||||
} finally {
|
||||
if ((folder != null) && (folder.isOpen())) {
|
||||
try {
|
||||
folder.close(false);
|
||||
} catch (MessagingException ex) {
|
||||
logger.debug("Error while closing folder", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns an array with one element of javax.mail.Message with the given messageid
|
||||
*
|
||||
* @param folder the folder to search for the message
|
||||
* @param messageId messageid of the message
|
||||
* @return the javax.mail.Message object for the mail with the givne messageid
|
||||
*
|
||||
* @throws MailReaderException if the message cannot be found or if more than one message with the same messageid exists
|
||||
*/
|
||||
private Message[] getMessage(Folder folder, String messageId) throws MailReaderException {
|
||||
try {
|
||||
SearchTerm st = new MessageIDTerm(messageId);
|
||||
Message[] messages = folder.search(st);
|
||||
if (messages.length != 1) {
|
||||
throw new MailReaderException("Cannot find message with messageID = " + messageId);
|
||||
}
|
||||
return messages;
|
||||
} catch (Exception ex) {
|
||||
throw new MailReaderException("Cannot find message with messageID = " + messageId + ". Reason: " + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* moves the given message from the source folder to the destination folder
|
||||
*
|
||||
* @param mm the message to move
|
||||
* @param sourceFolder the folder the message currently resists in
|
||||
* @param destFolder the folder the message should be moved to
|
||||
* @param deleteMessage if set to true, the messages are deleted from source folder after deletion
|
||||
* @throws MailReaderException if the operation fails
|
||||
*/
|
||||
private void copyMessages(MailMessage mm, String sourceFolder, String destFolder, boolean deleteMessage) throws MailReaderException {
|
||||
Folder sf = getFolderObject(sourceFolder);
|
||||
Folder df = getFolderObject(destFolder);
|
||||
|
||||
try {
|
||||
sf.open(Folder.READ_WRITE);
|
||||
df.open(Folder.READ_WRITE);
|
||||
|
||||
Message[] messages = getMessage(sf, mm.getMessageId());
|
||||
sf.copyMessages(messages, df);
|
||||
|
||||
if (deleteMessage) {
|
||||
for (Message message : messages) {
|
||||
message.setFlag(Flags.Flag.DELETED, true);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
} finally {
|
||||
if ((df != null) && (df.isOpen())) {
|
||||
try {
|
||||
df.close(false);
|
||||
} catch (MessagingException ex) {
|
||||
logger.debug("Error while closing destination folder", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if ((sf != null) && (sf.isOpen())) {
|
||||
try {
|
||||
sf.close(true);
|
||||
} catch (MessagingException ex) {
|
||||
logger.debug("Error while closing source folder", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* asures the message can be read even if the underlaying IMAP server does not handle the message correctly. see
|
||||
* http://www.oracle.com/technetwork/java/faq-135477.html for details
|
||||
*
|
||||
* @param msg the message to read
|
||||
* @return the message in a readable format
|
||||
*
|
||||
* @throws MessagingException if the message cannot be processed
|
||||
*/
|
||||
private Message getValidMessage(Message msg) throws MessagingException {
|
||||
|
||||
// assert message can be read
|
||||
// see
|
||||
MessagingException initialException;
|
||||
try {
|
||||
msg.getContentType();
|
||||
return msg;
|
||||
} catch (MessagingException ex) {
|
||||
initialException = ex;
|
||||
logger.debug("Direct access failed - trying workaround copy constructor");
|
||||
}
|
||||
|
||||
try {
|
||||
MimeMessage copyMsg = (MimeMessage) msg;
|
||||
// Use the MimeMessage copy constructor to make a copy
|
||||
// of the entire message, which will fetch the entire
|
||||
// message from the server and parse it on the client:
|
||||
MimeMessage cmsg = new MimeMessage(copyMsg);
|
||||
cmsg.getContentType();
|
||||
return cmsg;
|
||||
} catch (MessagingException ex) {
|
||||
logger.debug("Access via copy constructor failed, trying byte array constructor");
|
||||
}
|
||||
|
||||
try {
|
||||
Session session = getDefaultSession();
|
||||
|
||||
// Copy the message by writing into an byte array and
|
||||
// creating a new MimeMessage object based on the contents
|
||||
// of the byte array:
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
msg.writeTo(bos);
|
||||
bos.close();
|
||||
SharedByteArrayInputStream bis =
|
||||
new SharedByteArrayInputStream(bos.toByteArray());
|
||||
MimeMessage cmsg = new MimeMessage(session, bis);
|
||||
bis.close();
|
||||
|
||||
return cmsg;
|
||||
} catch (Exception ex) {
|
||||
logger.debug("Also fallback solution did not work");
|
||||
throw initialException;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,315 @@
|
||||
/**
|
||||
* package containing containing acess to mail messages, covering javax.mail api
|
||||
*/
|
||||
package de.muehlencord.shared.network.mail;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import javax.mail.Address;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
|
||||
/**
|
||||
* A mail message
|
||||
*
|
||||
* @author joern@muehlencord.de
|
||||
*/
|
||||
public class MailMessage {
|
||||
|
||||
/** the subect of the email */
|
||||
private String subject;
|
||||
/** the content of the message */
|
||||
private List<String> content;
|
||||
/** the html content of the message if avaialble, null else */
|
||||
private List<String> htmlContent;
|
||||
/** true, if content is html message body */
|
||||
private boolean isHtmlMessage;
|
||||
/** the message id if available, null otherwise */
|
||||
private String messageId;
|
||||
/** the size of the message in bytes */
|
||||
private int size;
|
||||
/** the date the message was sent */
|
||||
private Date sentDate;
|
||||
/** the sender of the email */
|
||||
private String sender;
|
||||
/** the list of receivers */
|
||||
private List<String> receiver;
|
||||
/** the list of CC receivers */
|
||||
private List<String> ccReceiver;
|
||||
/** the list of BCCC receivers */
|
||||
private List<String> bccReceiver;
|
||||
|
||||
// TODO add replyTo, add attachmentSupport
|
||||
/**
|
||||
* creates a new instance of a MailMessage
|
||||
*
|
||||
* @param subj the subject of the message
|
||||
* @param contentString the content of the message
|
||||
*/
|
||||
public MailMessage(String subj, String contentString) {
|
||||
this.subject = subj;
|
||||
this.content = new LinkedList<String>();
|
||||
if (contentString != null) {
|
||||
content.add(contentString);
|
||||
}
|
||||
this.htmlContent = new LinkedList<String>();
|
||||
this.isHtmlMessage = false;
|
||||
this.messageId = null;
|
||||
this.sender = null;
|
||||
this.receiver = new LinkedList<String>();
|
||||
this.ccReceiver = new LinkedList<String>();
|
||||
this.bccReceiver = new LinkedList<String>();
|
||||
}
|
||||
|
||||
/** creates a new instance of MaiLmessage
|
||||
*
|
||||
* @param subj the subject of the message
|
||||
* @param contentString the content of the message
|
||||
* @param id the message id the message was sent with
|
||||
*/
|
||||
public MailMessage(String subj, String contentString, String id) {
|
||||
this(subj, contentString);
|
||||
this.messageId = id;
|
||||
}
|
||||
|
||||
/* *** getter / setter *** */
|
||||
/**
|
||||
* @return the subject
|
||||
*/
|
||||
public String getSubject() {
|
||||
return subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the content
|
||||
*/
|
||||
public String getContent() {
|
||||
return getContent(content);
|
||||
}
|
||||
|
||||
private String getContent(List<String> contentList) {
|
||||
String returnValue = "";
|
||||
String contentSeparator = "--------";
|
||||
for (String currentContent : contentList) {
|
||||
returnValue += currentContent;
|
||||
returnValue += contentSeparator; // FIXME make configurable
|
||||
}
|
||||
if (returnValue.endsWith(contentSeparator)) {
|
||||
returnValue = returnValue.substring(0, returnValue.length() - contentSeparator.length());
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the content string of the message
|
||||
*
|
||||
* @param c the content to set
|
||||
* @param isHtmlContent if set to true, given content is treated as html content
|
||||
*/
|
||||
public void setContent(String c, boolean isHtmlContent) {
|
||||
if (c != null) {
|
||||
content.add(c);
|
||||
this.isHtmlMessage = isHtmlContent;
|
||||
if (isHtmlContent) {
|
||||
this.htmlContent.add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the html content of the message
|
||||
*
|
||||
* @param c the content to set (html string)
|
||||
*/
|
||||
public void setHtmlContent(String c) {
|
||||
this.htmlContent.add(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the html content string
|
||||
*
|
||||
* @return the html content string
|
||||
*/
|
||||
public String getHtmlContent() {
|
||||
return getContent(htmlContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the isHtmlMessage
|
||||
*/
|
||||
public boolean isHtmlMessage() {
|
||||
return isHtmlMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the messageId
|
||||
*/
|
||||
public String getMessageId() {
|
||||
return messageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the size of the message in bytes
|
||||
*
|
||||
* @param messageSize the size of the message in bytes
|
||||
*/
|
||||
public void setSize(int messageSize) {
|
||||
this.size = messageSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the message size in bytes
|
||||
*/
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the sentDate
|
||||
*/
|
||||
public Date getSentDate() {
|
||||
return new Date(sentDate.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param date the sentDate to set
|
||||
*/
|
||||
public void setSentDate(Date date) {
|
||||
this.sentDate = new Date(date.getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the sender
|
||||
*/
|
||||
public String getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the sender address
|
||||
*
|
||||
* @param sender the sender to set
|
||||
*
|
||||
*/
|
||||
public void setSender(String sender) {
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the sender address
|
||||
*
|
||||
* @param sender the sender to set
|
||||
*/
|
||||
public void setSender(Address[] sender) {
|
||||
if (sender.length > 0) {
|
||||
this.sender = getEmailAddress(sender[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the receiver
|
||||
*/
|
||||
public List<String> getReceiver() {
|
||||
return receiver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rcv the receiver to set
|
||||
*/
|
||||
public void addReceiver(String rcv) {
|
||||
this.receiver.add(rcv);
|
||||
}
|
||||
|
||||
/**
|
||||
* adds the given receiver to the list of receivers
|
||||
*
|
||||
* @param rcvList the receiver to add
|
||||
*/
|
||||
public void addReceiver(List<String> rcvList) {
|
||||
this.receiver.addAll(rcvList);
|
||||
}
|
||||
|
||||
/**
|
||||
* adds the give list of addresses to the receiver list
|
||||
*
|
||||
* @param addresses the addresses to add
|
||||
*/
|
||||
public void addReceiver(Address[] addresses) {
|
||||
if (addresses != null) {
|
||||
for (Address currentAddress : addresses) {
|
||||
addReceiver(getEmailAddress(currentAddress));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the ccReceiver
|
||||
*/
|
||||
public List<String> getCcReceiver() {
|
||||
return ccReceiver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rcv the ccReceiver to set
|
||||
*/
|
||||
public void addCcReceiver(String rcv) {
|
||||
this.ccReceiver.add(rcv);
|
||||
}
|
||||
|
||||
/**
|
||||
* adds the give list of addresses to the cc receiver list
|
||||
*
|
||||
* @param addresses the addresses to add
|
||||
*/
|
||||
public void addCcReceiver(Address[] addresses) {
|
||||
if (addresses != null) {
|
||||
for (Address currentAddress : addresses) {
|
||||
addCcReceiver(getEmailAddress(currentAddress));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the bccReceiver
|
||||
*/
|
||||
public List<String> getBccReceiver() {
|
||||
return bccReceiver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rcv the bccReceiver to set
|
||||
*/
|
||||
public void addBccReceiver(String rcv) {
|
||||
this.bccReceiver.add(rcv);
|
||||
}
|
||||
|
||||
/**
|
||||
* adds the give list of addresses to the bcc receiver list
|
||||
*
|
||||
* @param addresses the addresses to add
|
||||
*/
|
||||
public void addBccReceiver(Address[] addresses) {
|
||||
if (addresses != null) {
|
||||
for (Address currentAddress : addresses) {
|
||||
addBccReceiver(getEmailAddress(currentAddress));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the email adddress of the givne address
|
||||
*
|
||||
* @param currentAddress the address to get
|
||||
* @return the email adddress of the givne address as string
|
||||
*/
|
||||
private String getEmailAddress(Address currentAddress) {
|
||||
if (currentAddress instanceof InternetAddress) {
|
||||
InternetAddress address = (InternetAddress) currentAddress;
|
||||
return address.getAddress();
|
||||
} else {
|
||||
return currentAddress.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package de.muehlencord.shared.network.mail;
|
||||
|
||||
/**
|
||||
* Exception used during mail handling
|
||||
* @author joern@muehlencord.de
|
||||
*/
|
||||
public class MailMessageException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 6699249884047524285L;
|
||||
|
||||
/**
|
||||
* Creates a new instance of
|
||||
* <code>MailMessageException</code> without detail message.
|
||||
*/
|
||||
public MailMessageException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of
|
||||
* <code>MailMessageException</code> with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public MailMessageException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of
|
||||
* <code>MailMessageException</code> with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
* @param th the causing Throwable
|
||||
*/
|
||||
public MailMessageException(String msg, Throwable th) {
|
||||
super(msg,th);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,326 @@
|
||||
/**
|
||||
* wrapper classes around javax.mail package
|
||||
* written by Joern Muehlencord
|
||||
*
|
||||
*/
|
||||
package de.muehlencord.shared.network.mail;
|
||||
|
||||
import de.muehlencord.shared.util.StringUtil;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringWriter;
|
||||
import javax.mail.BodyPart;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.Multipart;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import javax.mail.internet.MimeMultipart;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Util class to convert between javax.mail.Message and MailMessage objects
|
||||
* @author joern@muehlencord.de
|
||||
*/
|
||||
public abstract class MailMessageUtils {
|
||||
|
||||
/** the logging object */
|
||||
private static final Logger logger = Logger.getLogger(MailMessageUtils.class.getName());
|
||||
|
||||
/** content type of mutipart messages - e.g. multipart_alternative or _mixed */
|
||||
private static final String CONTENTTYPE_MULTIPART = "multipart/";
|
||||
/** content type of text messages - like text/plain or text/html */
|
||||
private static final String CONTENTTYPE_TEXT = "text/";
|
||||
/** content type of text/plain messages */
|
||||
private static final String CONTENTTYPE_TEXT_PLAIN = "text/plain";
|
||||
/** content type of text/html messages */
|
||||
private static final String CONTENTTYPE_TEXT_HTML = "text/html";
|
||||
/** content type of application based messages - e.g. application/pdf */
|
||||
private static final String CONTENTTYPE_APPLICATION = "application/";
|
||||
/** content type of application pgp-signature */
|
||||
private static final String CONTENTTYPE_APPLICATION_PGPSIGNATURE = "application/pgp-signature";
|
||||
/** content type of embedded message */
|
||||
private static final String CONTENTTYPE_MESSAGE = "message/";
|
||||
/** content type of attached images */
|
||||
private static final String CONTENTTYPE_IMAGE = "image/";
|
||||
/** content type of attached videos */
|
||||
private static final String CONTENTTYPE_VIDEO = "video/";
|
||||
/** content type of attached audios */
|
||||
private static final String CONTENTTYPE_AUDIO = "audio/";
|
||||
|
||||
/**
|
||||
* creates a new instance of MailMessage based on the given javax.mail.Message object
|
||||
*
|
||||
* @param message the message object to create the message from
|
||||
* @return the MailMessage object created from the given javax.mail.Message
|
||||
*
|
||||
* @throws MailMessageException if the message cannot be created
|
||||
*/
|
||||
public static MailMessage getInstance(Message message) throws MailMessageException {
|
||||
MailMessage returnMessage = null;
|
||||
|
||||
if (message instanceof MimeMessage) {
|
||||
MimeMessage mm = (MimeMessage) message;
|
||||
String contentType;
|
||||
String subject;
|
||||
String messageId;
|
||||
try {
|
||||
contentType = getContentType(mm.getContentType());
|
||||
subject = mm.getSubject();
|
||||
logger.debug("message subject = " + subject);
|
||||
messageId = getMessageId(message);
|
||||
logger.debug("messageid = " + messageId);
|
||||
logger.debug(mm.getSentDate());
|
||||
|
||||
} catch (MessagingException ex) {
|
||||
throw new MailMessageException("Error while converting mime message. Reason: " + ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
logger.debug("messageContentType = " + contentType);
|
||||
|
||||
// handling multipart messages
|
||||
if (contentType.contains(CONTENTTYPE_MULTIPART)) {
|
||||
returnMessage = new MailMessage(subject, null, messageId);
|
||||
|
||||
try {
|
||||
Multipart mp = (Multipart) mm.getContent();
|
||||
int partsFound = mp.getCount();
|
||||
logger.debug(partsFound + " parts found");
|
||||
for (int i = 0; i < partsFound; i++) {
|
||||
logger.debug("Working on multiPart " + (i + 1));
|
||||
BodyPart bp = mp.getBodyPart(i);
|
||||
String bodyContentType = getContentType(bp.getContentType());
|
||||
logger.debug("contentType = " + bodyContentType);
|
||||
|
||||
|
||||
if (bodyContentType.contains(CONTENTTYPE_MULTIPART)) {
|
||||
MimeMultipart bodyMultiPart = (MimeMultipart) bp.getContent();
|
||||
int bodyPartCount = bodyMultiPart.getCount();
|
||||
logger.debug(bodyPartCount + " bodyMultiParts found");
|
||||
for (int currentBodyPart = 0; currentBodyPart < bodyPartCount; currentBodyPart++) {
|
||||
|
||||
logger.debug("Working on bodypart " + (currentBodyPart + 1));
|
||||
BodyPart bodyPart = bodyMultiPart.getBodyPart(currentBodyPart);
|
||||
String bodyPartContentType = getContentType(bodyPart.getContentType());
|
||||
logger.debug("bodyPart contentType = " + bodyPartContentType);
|
||||
|
||||
if (bodyPartContentType.contains(CONTENTTYPE_TEXT_PLAIN)) {
|
||||
returnMessage.setContent(getContent(bodyPart), false);
|
||||
} else if (bodyPartContentType.contains(CONTENTTYPE_TEXT_HTML)) {
|
||||
returnMessage.setHtmlContent(getContent(bodyPart));
|
||||
}
|
||||
}
|
||||
} else if (bodyContentType.equals(CONTENTTYPE_TEXT_PLAIN)) {
|
||||
|
||||
if (bp.getFileName() == null) {
|
||||
returnMessage.setContent(getContent(bp), false);
|
||||
} else {
|
||||
logger.debug("Found base64 coded attachment - not yet supported, skipping");
|
||||
}
|
||||
|
||||
} else if (bodyContentType.equals(CONTENTTYPE_TEXT_HTML)) {
|
||||
returnMessage.setHtmlContent(getContent(bp));
|
||||
|
||||
} else if (bodyContentType.equals(CONTENTTYPE_APPLICATION_PGPSIGNATURE)) {
|
||||
logger.debug("Found pgp signature - not yet supported, skipping");
|
||||
// TODO add pgp/signature support
|
||||
|
||||
} else if ((bodyContentType.contains(CONTENTTYPE_APPLICATION) || (bodyContentType.contains(CONTENTTYPE_MESSAGE))
|
||||
|| (bodyContentType.contains(CONTENTTYPE_TEXT)) || (bodyContentType.contains(CONTENTTYPE_IMAGE))
|
||||
|| (bodyContentType.contains(CONTENTTYPE_VIDEO)) || (bodyContentType.contains(CONTENTTYPE_AUDIO)))) {
|
||||
logger.debug("Found attachment - not yet supported, skipping");
|
||||
// TODO add attachment support
|
||||
} else {
|
||||
throw new MailMessageException("Reading bodyContentType " + bodyContentType + " not yet implemented");
|
||||
}
|
||||
} // for all parts
|
||||
|
||||
// asure content is set even if message contains html part only
|
||||
if ((returnMessage.getContent() == null) && (returnMessage.getHtmlContent() != null)) {
|
||||
returnMessage.setContent(returnMessage.getHtmlContent(), true);
|
||||
}
|
||||
|
||||
if ((returnMessage.getContent() == null) && (returnMessage.getHtmlContent() == null)) {
|
||||
throw new MailMessageException("Neither plain/text nor text/html content found. Unsupported message format");
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new MailMessageException("Error while converting multipart mime message. Reason: " + ex.getMessage(), ex);
|
||||
}
|
||||
} else if (contentType.equals(CONTENTTYPE_TEXT_PLAIN)) {
|
||||
// plain/text mimmessage
|
||||
try {
|
||||
returnMessage = new MailMessage(subject, mm.getContent().toString(), messageId);
|
||||
} catch (Exception ex) {
|
||||
throw new MailMessageException("Error while converting plain/text mime message. Reason: " + ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
} else if (contentType.equals(CONTENTTYPE_TEXT_HTML)) {
|
||||
// plain/text mimmessage
|
||||
try {
|
||||
String contentString = mm.getContent().toString();
|
||||
returnMessage = new MailMessage(subject, null, messageId);
|
||||
returnMessage.setContent(contentString, true);
|
||||
// returnMessage.setContent(mm.getContent().toString(), false);
|
||||
} catch (Exception ex) {
|
||||
throw new MailMessageException("Error while converting plain/text mime message. Reason: " + ex.getMessage(), ex);
|
||||
}
|
||||
} else if (contentType.contains(CONTENTTYPE_MESSAGE)) {
|
||||
try {
|
||||
Message nestedMessage = (Message) mm.getContent();
|
||||
returnMessage = getInstance(nestedMessage);
|
||||
} catch (Exception ex) {
|
||||
throw new MailMessageException("Error while converting nested message. Reason: " + ex.getMessage(), ex);
|
||||
}
|
||||
} else if (contentType.contains(CONTENTTYPE_APPLICATION)) {
|
||||
// message with only attachment
|
||||
returnMessage = new MailMessage(subject, "", messageId);
|
||||
logger.debug("Found attachment - not yet supported, skipping"); // TODO add attachment
|
||||
} else if (contentType.contains(CONTENTTYPE_TEXT)) {
|
||||
returnMessage = new MailMessage(subject, "", messageId);
|
||||
logger.debug("Found attachment - not yet supported, skipping"); // TODO add attachment
|
||||
} else {
|
||||
String hint = "Unkonwn message format Converting MimeMessage of contentType " + contentType + " not yet implemented.";
|
||||
|
||||
try {
|
||||
logger.debug(mm.getContent().getClass());
|
||||
logger.debug(mm.getContent());
|
||||
logger.error(hint);
|
||||
} catch (Exception ex) {
|
||||
logger.error(hint);
|
||||
}
|
||||
throw new MailMessageException(hint);
|
||||
}
|
||||
} else if (message instanceof Message) {
|
||||
try {
|
||||
String content = message.getContent().toString();
|
||||
String subject = message.getSubject();
|
||||
returnMessage = new MailMessage(subject, content);
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new MailMessageException("Error whilec converting email. Reason: " + ex.getMessage(), ex);
|
||||
}
|
||||
} else {
|
||||
throw new MailMessageException("Unsupported messagetype " + message.getClass().toString() + ". Cannot create message");
|
||||
}
|
||||
|
||||
// TODO add missing parameters
|
||||
// messageid
|
||||
try {
|
||||
returnMessage.addReceiver(message.getRecipients(Message.RecipientType.TO));
|
||||
returnMessage.addCcReceiver(message.getRecipients(Message.RecipientType.CC));
|
||||
returnMessage.addBccReceiver(message.getRecipients(Message.RecipientType.BCC));
|
||||
|
||||
returnMessage.setSender(message.getFrom());
|
||||
returnMessage.setSentDate(message.getSentDate());
|
||||
returnMessage.setSize(message.getSize());
|
||||
} catch (Exception ex) {
|
||||
throw new MailMessageException("Cannot read email. Reason: " + ex.getMessage(), ex);
|
||||
}
|
||||
return returnMessage;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns the content type based on the content-type header. The messad asures the contentype
|
||||
* is selected correctly from the string, including trim and tolower case
|
||||
* @param contentType the contenttype string read from email header
|
||||
* @return the content type of the email (small letters)
|
||||
*/
|
||||
private static String getContentType(String contentType) {
|
||||
|
||||
if (contentType.contains(";")) {
|
||||
contentType = contentType.substring(0, contentType.indexOf(';'));
|
||||
}
|
||||
contentType = contentType.toLowerCase();
|
||||
contentType = contentType.trim();
|
||||
return contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the content of the given bodypart which needs to be a text based bodypart
|
||||
* The method tries to read the messages as it is. In case of an unsupported encoding it reads the message with
|
||||
* the default encoding (accepting "ugly" characters)
|
||||
* @param bp the body part to read the content from
|
||||
* @return the content of the body part
|
||||
* @throws IOException if the content cannot be read
|
||||
* @throws MessagingException if the message cannot be processed
|
||||
*/
|
||||
private static String getContent(BodyPart bp) throws IOException, MessagingException {
|
||||
|
||||
String returnValue = null;
|
||||
try {
|
||||
returnValue = bp.getContent().toString();
|
||||
} catch (java.io.UnsupportedEncodingException ex) {
|
||||
logger.debug(ex.getMessage());
|
||||
} catch (java.io.IOException ioex) {
|
||||
throw new IOException("Cannot read content from bodypart.", ioex);
|
||||
} catch (MessagingException mex) {
|
||||
throw new MessagingException("Cannot read content from bodypart.", mex);
|
||||
}
|
||||
|
||||
if (returnValue == null) {
|
||||
return getContentByStream(bp, "UTF-8"); // TODO make configurable
|
||||
} else {
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the content of the given body part by reading the stream directly. This ommits getting unsupported encoding exceptions, as the content
|
||||
* is read with the given encoding
|
||||
* @param bp the bodypart to read the content from
|
||||
* @param encoding the encoding to force
|
||||
* @return the content string read with the given encoding
|
||||
* @throws IOException if the content cannot be read
|
||||
* @throws MessagingException if the message cannot be processed
|
||||
*/
|
||||
private static String getContentByStream(BodyPart bp, String encoding) throws IOException, MessagingException {
|
||||
String returnValue;
|
||||
Reader input = null;
|
||||
StringWriter output = null;
|
||||
try {
|
||||
input = new BufferedReader(new InputStreamReader(bp.getInputStream(), encoding));
|
||||
output = new StringWriter();
|
||||
char[] b = new char[4096];
|
||||
while (input.read(b) != -1) {
|
||||
output.write(b);
|
||||
}
|
||||
returnValue = output.toString();
|
||||
} catch (IOException ioex) {
|
||||
throw new IOException("Cannot read content from bodypart by reading content stream.", ioex);
|
||||
} finally {
|
||||
try {
|
||||
output.close();
|
||||
} catch (IOException ex) {
|
||||
logger.debug(ex.getMessage());
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
}
|
||||
try {
|
||||
input.close();
|
||||
} catch (IOException ex) {
|
||||
logger.debug(ex.getMessage());
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the message id from the header of the given message
|
||||
* @param message the message to return the message id from
|
||||
* @return either the message id or null if the message id cannot be read
|
||||
* @throws MessagingException if the message cannot be processed
|
||||
*/
|
||||
private static String getMessageId(Message message) throws MessagingException {
|
||||
String[] messageHeaders = message.getHeader("Message-Id");
|
||||
if ((messageHeaders != null) && (messageHeaders.length > 0)) {
|
||||
return messageHeaders[0];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package de.muehlencord.shared.network.mail;
|
||||
|
||||
import java.util.List;
|
||||
import javax.mail.Folder;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern@muehlencord.de
|
||||
*/
|
||||
public interface MailReader {
|
||||
|
||||
/** connects to the mailbox
|
||||
*
|
||||
* @throws MailReaderConnectionException if he connection cannot be established
|
||||
*/
|
||||
void connect() throws MailReaderConnectionException;
|
||||
|
||||
/** disconnects from mailbox */
|
||||
void disconnect();
|
||||
|
||||
/** returns the default folder
|
||||
*
|
||||
* @return the default folder
|
||||
*
|
||||
* @throws MailReaderException if the folder cannot be retrieved
|
||||
*/
|
||||
String getDefaultFolder() throws MailReaderException;
|
||||
|
||||
/**
|
||||
* returns the list of subfolders of the specified source folder
|
||||
*
|
||||
* @param sourceFolder the folder to return the folder list for
|
||||
* @return the list of subfolders of the specified source folder
|
||||
*
|
||||
* @throws MailReaderException if the folder list cannot be retrieved
|
||||
*/
|
||||
List<String> getSubFolder(String sourceFolder) throws MailReaderException;
|
||||
|
||||
/**
|
||||
* returns the folder, if folder path is a valid path to an existing folder
|
||||
*
|
||||
* @param folderPath the folder to return
|
||||
* @return the folder, if folder path is a valid path to an existing folder
|
||||
*
|
||||
* @throws MailReaderException if the folder cannot be found
|
||||
*/
|
||||
String getFolder(String folderPath) throws MailReaderException;
|
||||
|
||||
/**
|
||||
* returns the amount of message in the given folder
|
||||
*
|
||||
* @param holdFolder the folder to return the amount of messages for
|
||||
* @return the amount of message in the given folder
|
||||
*
|
||||
* @throws MailReaderException if the folder cannot be accessed or the amount of messages cannot be determined
|
||||
*/
|
||||
int getMessageCount(String holdFolder) throws MailReaderException;
|
||||
|
||||
/**
|
||||
* retrieves the list of messages stored in the given folder
|
||||
*
|
||||
* @param folder the folder to search return the emails for
|
||||
* @return list of messages stored in the given folder
|
||||
*
|
||||
* @throws MailReaderException if the message list cannot be retrieved
|
||||
*
|
||||
*/
|
||||
List<MailMessage> getMessages(String folder) throws MailReaderException;
|
||||
|
||||
/**
|
||||
* copies the given message from the source folder to the destination folder
|
||||
*
|
||||
* @param mm the message to copy
|
||||
* @param sourceFolder the folder the message currently resists in
|
||||
* @param destFolder the folder the message should be copied to
|
||||
* @throws MailReaderException if the operation fails
|
||||
*/
|
||||
void copyMessage(MailMessage mm, String sourceFolder, String destFolder) throws MailReaderException;
|
||||
|
||||
/**
|
||||
* moves the given message from the source folder to the destination folder
|
||||
*
|
||||
* @param mm the message to move
|
||||
* @param sourceFolder the folder the message currently resists in
|
||||
* @param destFolder the folder the message should be moved to
|
||||
* @throws MailReaderException if the operation fails
|
||||
*/
|
||||
void moveMessage(MailMessage mm, String sourceFolder, String destFolder) throws MailReaderException;
|
||||
|
||||
/**
|
||||
* marks the messages as seen
|
||||
*
|
||||
* @param folder the folder to search for the email
|
||||
* @param mm the message to mark as seen
|
||||
* @param flagValue if set to true, the seen flag is set; otherwise it is removed (unset)
|
||||
* @throws MailReaderException if the flag cannot be set
|
||||
*/
|
||||
void setSeenFlag(String folder, MailMessage mm, boolean flagValue) throws MailReaderException;
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package de.muehlencord.shared.network.mail;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord
|
||||
*/
|
||||
public class MailReaderConfiguration {
|
||||
/** server for smtp sessions */
|
||||
private String smtpHost = null;
|
||||
/** server for incoming emails - e.g. the imap or pop3 server */
|
||||
private String readerHost = null;
|
||||
/** the username to connect with */
|
||||
private String userName = null;
|
||||
/** the password to connect with */
|
||||
private String password = null;
|
||||
|
||||
// TODO add checkConfig to asure the config is valid for the reader it is attached to
|
||||
|
||||
/**
|
||||
* creates a new config
|
||||
* @param mailHost the smtp host to connect to
|
||||
* @param host the mailreader host (imap, exchange, pop, ...) to connect to
|
||||
* @param user the username to connect with
|
||||
* @param pw the password to connect with
|
||||
*/
|
||||
public MailReaderConfiguration (String mailHost, String host, String user, String pw) {
|
||||
this.smtpHost = mailHost;
|
||||
this.readerHost = host;
|
||||
this.userName = user;
|
||||
this.password = pw;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the smtpHost
|
||||
*/
|
||||
public String getSmtpHost() {
|
||||
return smtpHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the readerHost
|
||||
*/
|
||||
public String getReaderHost() {
|
||||
return readerHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the userName
|
||||
*/
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the password
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package de.muehlencord.shared.network.mail;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern@muehlencord.de
|
||||
*/
|
||||
public class MailReaderConfigurationException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 3874572911465653501L;
|
||||
|
||||
/**
|
||||
* Creates a new instance of
|
||||
* <code>MailReaderConfigurationException</code> without detail message.
|
||||
*/
|
||||
public MailReaderConfigurationException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of
|
||||
* <code>MailReaderConfigurationException</code> with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public MailReaderConfigurationException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of
|
||||
* <code>MailReaderConfigurationException</code> with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
* @param th the causing exception
|
||||
*/
|
||||
public MailReaderConfigurationException(String msg, Throwable th) {
|
||||
super(msg, th);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
package de.muehlencord.shared.network.mail;
|
||||
|
||||
import de.muehlencord.shared.util.StringUtil;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern@muehlencord.de
|
||||
*/
|
||||
public abstract class MailReaderConfigurationFactory {
|
||||
|
||||
/** the logging object */
|
||||
private final static Logger logger = Logger.getLogger(MailReaderConfigurationFactory.class.getName());
|
||||
|
||||
/**
|
||||
* reads the config file and creates a configured mailreader configuration
|
||||
*
|
||||
* @param configFile the file to read
|
||||
* @return the configured MailReaderConfiguration object
|
||||
*
|
||||
* @throws MailReaderConfigurationException if the file does not exist or the config cannot be created
|
||||
*/
|
||||
public static MailReaderConfiguration getConfiguration(String configFile) throws MailReaderConfigurationException {
|
||||
File f = new File(configFile);
|
||||
if (!f.exists()) {
|
||||
throw new MailReaderConfigurationException("Cannot find configfile " + configFile);
|
||||
}
|
||||
|
||||
Properties p = new Properties();
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = new FileInputStream(f);
|
||||
p.load(is);
|
||||
} catch (Exception ex) {
|
||||
throw new MailReaderConfigurationException("Error while reading config file. Reason: " + ex.getMessage(), ex);
|
||||
} finally {
|
||||
try {
|
||||
is.close();
|
||||
} catch (Exception ex) {
|
||||
logger.error("Error while reading input file.");
|
||||
logger.debug(StringUtil.getStackTraceString(ex));
|
||||
}
|
||||
}
|
||||
|
||||
String smtpServer = p.getProperty("smtp.server");
|
||||
if ((smtpServer == null) || (smtpServer.isEmpty())) {
|
||||
throw new MailReaderConfigurationException("property smtp.server not specified. Please check config");
|
||||
}
|
||||
String host = p.getProperty("imap.server");
|
||||
if ((smtpServer == null) || (smtpServer.isEmpty())) {
|
||||
throw new MailReaderConfigurationException("property imap.server not specified. Please check config");
|
||||
}
|
||||
String userName = p.getProperty("imap.username");
|
||||
if ((smtpServer == null) || (smtpServer.isEmpty())) {
|
||||
throw new MailReaderConfigurationException("property imap.username not specified. Please check config");
|
||||
}
|
||||
String password = p.getProperty("imap.password");
|
||||
if ((smtpServer == null) || (smtpServer.isEmpty())) {
|
||||
throw new MailReaderConfigurationException("property imap.password not specified. Please check config");
|
||||
}
|
||||
|
||||
return new MailReaderConfiguration(smtpServer, host, userName, password);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package de.muehlencord.shared.network.mail;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jomu
|
||||
*/
|
||||
public class MailReaderConnectionException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -1593741665654202661L;
|
||||
|
||||
/**
|
||||
* Creates a new instance of
|
||||
* <code>MailReaderConnectionException</code> without detail message.
|
||||
*/
|
||||
public MailReaderConnectionException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of
|
||||
* <code>MailReaderConnectionException</code> with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public MailReaderConnectionException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of
|
||||
* <code>MailReaderConnectionException</code> with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
* @param th the causing error
|
||||
*/
|
||||
public MailReaderConnectionException(String msg, Throwable th) {
|
||||
super(msg, th);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package de.muehlencord.shared.network.mail;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jomu
|
||||
*/
|
||||
public class MailReaderException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 4850689622364462635L;
|
||||
|
||||
/**
|
||||
* Creates a new instance of
|
||||
* <code>MailReaderException</code> without detail message.
|
||||
*/
|
||||
public MailReaderException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of
|
||||
* <code>MailReaderException</code> with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public MailReaderException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of
|
||||
* <code>MailReaderException</code> with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
* @param th the causing exception
|
||||
*/
|
||||
public MailReaderException(String msg, Throwable th) {
|
||||
super(msg, th);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package de.muehlencord.shared.network.mail.imap;
|
||||
|
||||
import de.muehlencord.shared.network.mail.DefaultMailReader;
|
||||
import de.muehlencord.shared.network.mail.MailReaderConfiguration;
|
||||
import de.muehlencord.shared.network.mail.MailReaderConnectionException;
|
||||
import javax.mail.Session;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Implementation of MaiLReader to connect to an IMAP server
|
||||
*
|
||||
* @author joern@muehlencord.de
|
||||
*/
|
||||
public class ImapMailReader extends DefaultMailReader {
|
||||
|
||||
/** the logger object */
|
||||
private final static Logger logger = Logger.getLogger(ImapMailReader.class);
|
||||
|
||||
/**
|
||||
* creates a new instance to connect to an IMAP (or MS Exchange) server
|
||||
*
|
||||
* @param config the configuration of the mail reader
|
||||
*/
|
||||
public ImapMailReader(MailReaderConfiguration config) {
|
||||
super(config);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() throws MailReaderConnectionException {
|
||||
Session session = getDefaultSession();
|
||||
String hostName = getConfiguration().getReaderHost();
|
||||
String userName = getConfiguration().getUserName();
|
||||
String password = getConfiguration().getPassword();
|
||||
try {
|
||||
setStore(session.getStore("imap")); // TODO add ssl support
|
||||
getStore().connect(hostName, userName, password);
|
||||
} catch (Exception ex) {
|
||||
String hint = "Error while connecting to mailbox " + getConnectionShortCut();
|
||||
hint += ". Reason: " + ex.getMessage();
|
||||
throw new MailReaderConnectionException(hint, ex);
|
||||
}
|
||||
logger.info("Connected to " + getConnectionShortCut());
|
||||
}
|
||||
|
||||
/**
|
||||
* returns userName@hostname
|
||||
*
|
||||
* @return userName@hostname
|
||||
*/
|
||||
private String getConnectionShortCut() {
|
||||
return getConfiguration().getUserName() + "@" + getConfiguration().getReaderHost();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user