first commit

This commit is contained in:
jomu
2013-02-06 22:06:43 +00:00
parent 1a6d3e4c41
commit aef92c311d
84 changed files with 5334 additions and 0 deletions

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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();
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}