Index: client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListPresenter.java
===================================================================
--- client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListPresenter.java	(revision 824847)
+++ client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListPresenter.java	(working copy)
@@ -28,7 +28,7 @@
 import net.customware.gwt.presenter.client.widget.WidgetDisplay;
 import net.customware.gwt.presenter.client.widget.WidgetPresenter;
 
-import org.apache.hupa.client.SessionAsyncCallback;
+import org.apache.hupa.client.HupaCallback;
 import org.apache.hupa.client.widgets.HasDialog;
 import org.apache.hupa.shared.data.IMAPFolder;
 import org.apache.hupa.shared.data.Message;
@@ -43,7 +43,7 @@
 import org.apache.hupa.shared.rpc.DeleteAllMessages;
 import org.apache.hupa.shared.rpc.DeleteMessageByUid;
 import org.apache.hupa.shared.rpc.DeleteMessageResult;
-import org.apache.hupa.shared.rpc.EmptyResult;
+import org.apache.hupa.shared.rpc.GenericResult;
 import org.apache.hupa.shared.rpc.MoveMessage;
 import org.apache.hupa.shared.rpc.MoveMessageResult;
 import org.apache.hupa.shared.rpc.SetFlag;
@@ -58,7 +58,6 @@
 import com.google.gwt.gen2.table.event.client.HasRowSelectionHandlers;
 import com.google.gwt.gen2.table.event.client.RowSelectionEvent;
 import com.google.gwt.gen2.table.event.client.RowSelectionHandler;
-import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.SourcesTableEvents;
 import com.google.gwt.user.client.ui.TableListener;
 import com.google.inject.Inject;
@@ -126,19 +125,13 @@
 
 			public void onMoveMessageHandler(MoveMessageEvent event) {
 				final Message message = event.getMessage();
-				dispatcher.execute(new MoveMessage(event.getOldFolder(), event.getNewFolder(), message.getUid()), new SessionAsyncCallback<MoveMessageResult>(new AsyncCallback<MoveMessageResult>() {
-
-					public void onFailure(Throwable caught) {
-						GWT.log("ERROR while moving",caught);
-					}
-
-					public void onSuccess(MoveMessageResult result) {
+				dispatcher.execute(new MoveMessage(event.getOldFolder(), event.getNewFolder(), message.getUid()), new HupaCallback<MoveMessageResult>(dispatcher, eventBus) {
+					public void callback(MoveMessageResult result) {
 						ArrayList<Message> messageArray = new ArrayList<Message>();
 						messageArray.add(message);
 						display.removeMessages(messageArray);
 					}
-					
-				},eventBus,user));
+				}); 
 			}
 			
 		}));
@@ -199,17 +192,12 @@
 		registerHandler(display.getConfirmDeleteAllDialogClick().addClickHandler(new ClickHandler() {
 
 			public void onClick(ClickEvent event) {
-				dispatcher.execute(new DeleteAllMessages(folder), new SessionAsyncCallback<DeleteMessageResult>(new AsyncCallback<DeleteMessageResult>() {
-
-					public void onFailure(Throwable caught) {
-						GWT.log("E=", caught);
-					}
-
-					public void onSuccess(DeleteMessageResult result) {
+				dispatcher.execute(new DeleteAllMessages(folder), new HupaCallback<DeleteMessageResult>(dispatcher, eventBus) {
+					public void callback(DeleteMessageResult result) {
 						display.reset();
 						eventBus.fireEvent(new DecreaseUnseenEvent(user,folder,result.getCount()));
 					}
-				}, eventBus,user));
+				});
 			}
 			
 		}));
@@ -225,12 +213,8 @@
 						selectedMessages.remove(m);
 					}
 				}
-				dispatcher.execute(new SetFlag(folder, IMAPFlag.SEEN, true, uids), new SessionAsyncCallback<EmptyResult>(new AsyncCallback<EmptyResult>() {
-					public void onFailure(Throwable caught) {
-						GWT.log("ERR=", caught);
-					}
-
-					public void onSuccess(EmptyResult result) {
+				dispatcher.execute(new SetFlag(folder, IMAPFlag.SEEN, true, uids), new HupaCallback<GenericResult>(dispatcher, eventBus) {
+					public void callback(GenericResult result) {
 						GWT.log("S="+selectedMessages.size(), null);
 						for (int i = 0; i < selectedMessages.size(); i++) {
 							Message m = selectedMessages.get(i);
@@ -240,10 +224,8 @@
 						}
 						display.redraw();
 						eventBus.fireEvent(new DecreaseUnseenEvent(user, folder,selectedMessages.size()));
-												
 					}
-
-				}, eventBus, user));
+				});
 			}
 
 		}));
@@ -262,12 +244,8 @@
 					}
 				}
 				
-				dispatcher.execute(new SetFlag(folder, IMAPFlag.SEEN, false, uids), new SessionAsyncCallback<EmptyResult>(new AsyncCallback<EmptyResult>() {
-					public void onFailure(Throwable caught) {
-						GWT.log("ERR=", caught);
-					}
-
-					public void onSuccess(EmptyResult result) {
+				dispatcher.execute(new SetFlag(folder, IMAPFlag.SEEN, false, uids), new HupaCallback<GenericResult>(dispatcher, eventBus) {
+					public void callback(GenericResult result) {
 						for (int i = 0; i < selectedMessages.size(); i++) {
 							Message m = selectedMessages.get(i);
 							if (m.getFlags().contains(IMAPFlag.SEEN)) {
@@ -276,10 +254,8 @@
 						}
 						display.redraw();
 						eventBus.fireEvent(new IncreaseUnseenEvent(user, folder,selectedMessages.size()));
-												
 					}
-
-				}, eventBus, user));
+				});
 			}
 			
 			
@@ -312,17 +288,12 @@
 		for (int i = 0; i < selectedMessages.size(); i++) {
 			uids.add(selectedMessages.get(i).getUid());
 		}
-		dispatcher.execute(new DeleteMessageByUid(folder,uids), new SessionAsyncCallback<DeleteMessageResult>(new AsyncCallback<DeleteMessageResult>() {
-
-			public void onFailure(Throwable caught) {
-				// TODO Auto-generated method stub
-			}
-
-			public void onSuccess(DeleteMessageResult result) {
+		dispatcher.execute(new DeleteMessageByUid(folder,uids), new HupaCallback<DeleteMessageResult>(dispatcher, eventBus) {
+			public void callback(DeleteMessageResult result) {
 				display.removeMessages(selectedMessages);
 				eventBus.fireEvent(new DecreaseUnseenEvent(user,folder,result.getCount()));
 			}
-		}, eventBus,user));
+		}); 
 	}
 	
 	public void bind(User user, IMAPFolder folder, String searchValue) {
Index: client/src/main/java/org/apache/hupa/client/mvp/LoginPresenter.java
===================================================================
--- client/src/main/java/org/apache/hupa/client/mvp/LoginPresenter.java	(revision 824847)
+++ client/src/main/java/org/apache/hupa/client/mvp/LoginPresenter.java	(working copy)
@@ -20,13 +20,13 @@
 package org.apache.hupa.client.mvp;
 
 import net.customware.gwt.dispatch.client.DispatchAsync;
-import net.customware.gwt.presenter.client.DisplayCallback;
 import net.customware.gwt.presenter.client.EventBus;
 import net.customware.gwt.presenter.client.place.Place;
 import net.customware.gwt.presenter.client.place.PlaceRequest;
 import net.customware.gwt.presenter.client.widget.WidgetDisplay;
 import net.customware.gwt.presenter.client.widget.WidgetPresenter;
 
+import org.apache.hupa.client.HupaCallback;
 import org.apache.hupa.client.HupaConstants;
 import org.apache.hupa.shared.events.LoginEvent;
 import org.apache.hupa.shared.events.SessionExpireEvent;
@@ -69,22 +69,16 @@
 	 * Try to login the user
 	 */
 	private void doLogin() {
-		dispatcher.execute(new LoginUser(display.getUserNameValue().getValue(),display.getPasswordValue().getValue()), new DisplayCallback<LoginUserResult>(display) {
-
-
-			@Override
-			protected void handleFailure(Throwable e) {
+		dispatcher.execute(new LoginUser(display.getUserNameValue().getValue(),display.getPasswordValue().getValue()), new HupaCallback<LoginUserResult>(dispatcher, eventBus, display) {
+			public void callback(LoginUserResult result) {
+				eventBus.fireEvent(new LoginEvent(result.getUser()));
 				doReset();
-				display.getErrorText().setText(constants.loginInvalid());
 			}
-
-			@Override
-			protected void handleSuccess(LoginUserResult result) {
-				eventBus.fireEvent(new LoginEvent(result.getUser()));
+			public void callbackError(Throwable caught) {
+				display.getErrorText().setText(constants.loginInvalid());
 				doReset();
 			}
-			
-		});
+		}); 
 	}
 	
 	/**
Index: client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListView.java
===================================================================
--- client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListView.java	(revision 824847)
+++ client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListView.java	(working copy)
@@ -27,6 +27,7 @@
 import net.customware.gwt.dispatch.client.DispatchAsync;
 import net.customware.gwt.presenter.client.EventBus;
 
+import org.apache.hupa.client.HupaCallback;
 import org.apache.hupa.client.HupaConstants;
 import org.apache.hupa.client.HupaMessages;
 import org.apache.hupa.client.bundles.HupaImageBundle;
@@ -78,7 +79,6 @@
 import com.google.gwt.gen2.table.event.client.PageLoadHandler;
 import com.google.gwt.i18n.client.DateTimeFormat;
 import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HorizontalPanel;
@@ -104,7 +104,7 @@
 	private DragRefetchPagingScrollTable<Message> mailTable;
 	private CachedTableModel<Message> cTableModel = new CachedTableModel<Message>(new IMAPMessageTableModel());
 
-	private EventBus bus;
+	private EventBus eventBus;
 	private FixedWidthGrid dataTable = createDataTable();
 	private MyButton deleteMailButton = new MyButton(constants.deleteMailButton());
 	private	Button newMailButton = new Button(constants.newMailButton());
@@ -121,7 +121,7 @@
 	
 	@Inject
 	public IMAPMessageListView(DispatchAsync dispatcher,EventBus bus, PagingScrollTableRowDragController controller) {
-		this.bus = bus;
+		this.eventBus = bus;
 		this.dispatcher = dispatcher;
 		
 		VerticalPanel vPanel = new VerticalPanel();
@@ -374,27 +374,19 @@
 				});
 			}
 			
-			dispatcher.execute(new FetchMessages(folder, request.getStartRow(), request.getNumRows(),searchValue), new AsyncCallback<FetchMessagesResult>() {
-
-				public void onFailure(Throwable caught) {
-					callback.onFailure(caught);
-				}
-
-				public void onSuccess(final FetchMessagesResult result) {
-					bus.fireEvent(new MessagesReceivedEvent(folder,result.getMessages()));
+			dispatcher.execute(new FetchMessages(folder, request.getStartRow(), request.getNumRows(),searchValue),new HupaCallback<FetchMessagesResult>(dispatcher, eventBus) {
+				public void callback(final FetchMessagesResult result) {
+					eventBus.fireEvent(new MessagesReceivedEvent(folder,result.getMessages()));
 					 TableModelHelper.Response<Message> response = new TableModelHelper.Response<Message>() {
-
 						@Override
 						public Iterator<Message> getRowValues() {
 							return result.getMessages().iterator();
 						}
-						
 					};
 					cTableModel.setRowCount(result.getRealCount());
 					callback.onRowsReady(request,response);
 				}
-				
-			});
+			}); 
 		}
 
 		@Override
Index: client/src/main/java/org/apache/hupa/client/mvp/IMAPMessagePresenter.java
===================================================================
--- client/src/main/java/org/apache/hupa/client/mvp/IMAPMessagePresenter.java	(revision 824847)
+++ client/src/main/java/org/apache/hupa/client/mvp/IMAPMessagePresenter.java	(working copy)
@@ -22,7 +22,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import net.customware.gwt.presenter.client.DisplayCallback;
 import net.customware.gwt.presenter.client.EventBus;
 import net.customware.gwt.presenter.client.place.Place;
 import net.customware.gwt.presenter.client.place.PlaceRequest;
@@ -30,13 +29,13 @@
 import net.customware.gwt.presenter.client.widget.WidgetPresenter;
 
 import org.apache.hupa.client.CachingDispatchAsync;
-import org.apache.hupa.client.SessionAsyncCallback;
+import org.apache.hupa.client.HupaCallback;
 import org.apache.hupa.client.widgets.HasDialog;
 import org.apache.hupa.shared.Util;
 import org.apache.hupa.shared.data.IMAPFolder;
 import org.apache.hupa.shared.data.Message;
-import org.apache.hupa.shared.data.MessageDetails;
 import org.apache.hupa.shared.data.MessageAttachment;
+import org.apache.hupa.shared.data.MessageDetails;
 import org.apache.hupa.shared.data.User;
 import org.apache.hupa.shared.events.BackEvent;
 import org.apache.hupa.shared.events.ForwardMessageEvent;
@@ -44,13 +43,11 @@
 import org.apache.hupa.shared.events.ReplyMessageEvent;
 import org.apache.hupa.shared.rpc.DeleteMessageByUid;
 import org.apache.hupa.shared.rpc.DeleteMessageResult;
-import org.apache.hupa.shared.rpc.RawMessage;
-import org.apache.hupa.shared.rpc.RawMessageResult;
 
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.HasClickHandlers;
-import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.Frame;
 import com.google.gwt.user.client.ui.HasHTML;
 import com.google.gwt.user.client.ui.HasText;
 import com.google.inject.Inject;
@@ -65,7 +62,7 @@
 		public HasText getCc();
 
 		public HasText getSubject();
-		public HasText getShowRawMessageText();
+		public Frame getShowRawMessageFrame();
 		public HasDialog getShowRawMessageDialog();
 		public HasHTML getContent();
 		public HasClickHandlers getShowRawMessageClick();
@@ -128,20 +125,13 @@
 			public void onClick(ClickEvent event) {
 				ArrayList<Long> uidList = new ArrayList<Long>();
 				uidList.add(message.getUid());
-				dispatcher.execute(new DeleteMessageByUid(folder, uidList), new SessionAsyncCallback<DeleteMessageResult>(new AsyncCallback<DeleteMessageResult>() {
-
-					public void onFailure(Throwable caught) {
-						// TODO Auto-generated method stub
-						
-					}
-
-					public void onSuccess(DeleteMessageResult result) {
+				dispatcher.execute(new DeleteMessageByUid(folder, uidList), new HupaCallback<DeleteMessageResult>(dispatcher, eventBus) {
+					public void callback(DeleteMessageResult result) {
 						eventBus.fireEvent(new LoadMessagesEvent(user,folder));
 					}
-					
-				}, eventBus,user));
+				}); 
 			}
-			
+
 		}));
 		
 		registerHandler(display.getForwardButtonClick().addClickHandler(new ClickHandler() {
@@ -177,22 +167,9 @@
 		registerHandler(display.getShowRawMessageClick().addClickHandler(new ClickHandler() {
 
 			public void onClick(ClickEvent event) {
-				dispatcher.executeWithCache(new RawMessage(folder, message.getUid()), new SessionAsyncCallback<RawMessageResult>(new DisplayCallback<RawMessageResult>(display) {
-
-					@Override
-					protected void handleFailure(Throwable e) {
-						// TODO Auto-generated method stub
-						
-					}
-
-					@Override
-					protected void handleSuccess(RawMessageResult result) {
-						display.getShowRawMessageText().setText(result.getRawMessage());
-						display.getShowRawMessageDialog().center();
-					}
-
-					
-				},eventBus,user));
+				String message_url = "/hupa/messageSourceServlet?uid=" + message.getUid() + "&folder=" + folder.getFullName();
+				display.getShowRawMessageFrame().setUrl(message_url);
+				display.getShowRawMessageDialog().center();
 			}
 			
 		}));
Index: client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageView.java
===================================================================
--- client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageView.java	(revision 824847)
+++ client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageView.java	(working copy)
@@ -41,6 +41,7 @@
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Frame;
 import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HasHTML;
@@ -72,7 +73,7 @@
 	private Hyperlink backButton = new Hyperlink(constants.backButton(),"");
 	private FlowPanel attachments = new FlowPanel();
 	private MyDialogBox rawDialogBox = new MyDialogBox();
-	private Label rawLabel = new Label();
+	private Frame rawFrame = new Frame();
 	public final static int DELETE_BUTTON = 0;
 	public final static int REPLY_BUTTON = 1;
 	public final static int REPLY_ALL_BUTTON = 2;
@@ -167,13 +168,11 @@
 		sPanel.add(msgArea);
 		mPanel.add(sPanel);
 
-	    DOM.setStyleAttribute(rawLabel.getElement(), "whiteSpace", "pre"); 
-	    ScrollPanel rawPanel = new ScrollPanel(rawLabel);
-	    rawPanel.setAlwaysShowScrollBars(false);
-	    rawPanel.setHeight("600px");
-	    rawPanel.setWidth("600px");
+	    // TODO: put this in css
+	    rawFrame.setHeight("600px");
+	    rawFrame.setWidth("600px");
 	    rawDialogBox.setText(constants.rawTitle());
-	    rawDialogBox.add(rawPanel);
+	    rawDialogBox.add(rawFrame);
 		rawDialogBox.setAnimationEnabled(true);
 		rawDialogBox.setAutoHideEnabled(true);
 		initWidget(mPanel);
@@ -269,8 +268,8 @@
 		return rawDialogBox;
 	}
 
-	public HasText getShowRawMessageText() {
-		return rawLabel;
+	public Frame getShowRawMessageFrame() {
+		return rawFrame;
 	}
 	
 }
Index: client/src/main/java/org/apache/hupa/client/mvp/MessageSendPresenter.java
===================================================================
--- client/src/main/java/org/apache/hupa/client/mvp/MessageSendPresenter.java	(revision 824847)
+++ client/src/main/java/org/apache/hupa/client/mvp/MessageSendPresenter.java	(working copy)
@@ -19,15 +19,6 @@
 
 package org.apache.hupa.client.mvp;
 
-import eu.maydu.gwt.validation.client.DefaultValidationProcessor;
-import eu.maydu.gwt.validation.client.ValidationProcessor;
-import eu.maydu.gwt.validation.client.actions.FocusAction;
-import eu.maydu.gwt.validation.client.actions.StyleAction;
-import eu.maydu.gwt.validation.client.i18n.ValidationMessages;
-import gwtupload.client.IUploader;
-import gwtupload.client.IUploader.OnFinishUploaderHandler;
-import gwtupload.client.IUploader.OnStartUploaderHandler;
-
 import java.util.ArrayList;
 
 import net.customware.gwt.dispatch.client.DispatchAsync;
@@ -37,7 +28,7 @@
 import net.customware.gwt.presenter.client.widget.WidgetDisplay;
 import net.customware.gwt.presenter.client.widget.WidgetPresenter;
 
-import org.apache.hupa.client.SessionAsyncCallback;
+import org.apache.hupa.client.HupaCallback;
 import org.apache.hupa.client.validation.EmailListValidator;
 import org.apache.hupa.client.validation.NotEmptyValidator;
 import org.apache.hupa.shared.Util;
@@ -53,8 +44,8 @@
 import org.apache.hupa.shared.events.LoadMessagesEvent;
 import org.apache.hupa.shared.events.LoadMessagesEventHandler;
 import org.apache.hupa.shared.events.SentMessageEvent;
-import org.apache.hupa.shared.rpc.EmptyResult;
 import org.apache.hupa.shared.rpc.ForwardMessage;
+import org.apache.hupa.shared.rpc.GenericResult;
 import org.apache.hupa.shared.rpc.ReplyMessage;
 import org.apache.hupa.shared.rpc.SendMessage;
 import org.apache.hupa.widgets.ui.HasEnable;
@@ -62,39 +53,66 @@
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.HasClickHandlers;
-import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.HasText;
 import com.google.inject.Inject;
 
+import eu.maydu.gwt.validation.client.DefaultValidationProcessor;
+import eu.maydu.gwt.validation.client.ValidationProcessor;
+import eu.maydu.gwt.validation.client.actions.FocusAction;
+import eu.maydu.gwt.validation.client.actions.StyleAction;
+import eu.maydu.gwt.validation.client.i18n.ValidationMessages;
+import gwtupload.client.IUploader;
+import gwtupload.client.IUploadStatus.Status;
+import gwtupload.client.IUploader.OnCancelUploaderHandler;
+import gwtupload.client.IUploader.OnFinishUploaderHandler;
+import gwtupload.client.IUploader.OnStatusChangedHandler;
+
 public class MessageSendPresenter extends WidgetPresenter<MessageSendPresenter.Display>{
 
 	private User user;
 	private DispatchAsync dispatcher;
 	public static final Place PLACE = new Place("MessageSend");
-	private ArrayList<MessageAttachment> aList = new ArrayList<MessageAttachment>();
+	private ArrayList<MessageAttachment> attachments = new ArrayList<MessageAttachment>();
 	private Type type = Type.NEW;
 	private IMAPFolder folder;
 	private Message oldmessage;
 	private ValidationMessages vMessages = new ValidationMessages();
 	private ValidationProcessor validator = new DefaultValidationProcessor(vMessages);
-	private MessageDetails oldDetails;
-	
-	private OnFinishUploaderHandler finishHandler = new  OnFinishUploaderHandler() {
+	@SuppressWarnings("unused")
+    private MessageDetails oldDetails;
+
+	private OnFinishUploaderHandler onFinishUploadHandler = new OnFinishUploaderHandler() {
 		public void onFinish(IUploader uploader) {
-			String name =  uploader.getFileName();
-			MessageAttachment attachment = new MessageAttachment();
-			attachment.setName(name);
-			aList.add(attachment);
-			display.getSendEnable().setEnabled(true);
-	    }
+			if (uploader.getStatus() == Status.SUCCESS) {
+				String name =  uploader.getInputName();
+				MessageAttachment attachment = new MessageAttachment();
+				attachment.setName(name);
+				attachments.add(attachment);
+				display.getSendEnable().setEnabled(true);
+			}
+        }
 	};
-		
-	private OnStartUploaderHandler startHandler = new  OnStartUploaderHandler() {
-	    public void onStart(IUploader uploader) {
-			display.getSendEnable().setEnabled(false);
-	    }
+	
+	private OnStatusChangedHandler onStatusChangedHandler = new OnStatusChangedHandler() {
+		public void onStatusChanged(IUploader uploader) {
+			Status stat = display.getUploader().getStatus();
+			if (stat == Status.INPROGRESS)
+				display.getSendEnable().setEnabled(false);
+			else
+				display.getSendEnable().setEnabled(true);
+        }
 	};
-		
+
+	private OnCancelUploaderHandler onCancelUploadHandler = new OnCancelUploaderHandler() {
+		public void onCancel(IUploader uploader) {
+			for (MessageAttachment attachment: attachments) {
+				if (attachment.getName().equals(uploader.getInputName()))
+					attachments.remove(attachment);
+			}
+        }
+	};
+	
 	@Inject
 	public MessageSendPresenter(Display display, EventBus eventBus, DispatchAsync dispatcher) {
 		super(display, eventBus);
@@ -160,8 +178,10 @@
 			}
 			
 		}));
-		registerHandler(display.getUploader().addOnStartUploadHandler(startHandler));
-		registerHandler(display.getUploader().addOnFinishUploadHandler(finishHandler));
+
+		registerHandler(display.getUploader().addOnStatusChangedHandler(onStatusChangedHandler));
+		registerHandler(display.getUploader().addOnFinishUploadHandler(onFinishUploadHandler));
+		registerHandler(display.getUploader().addOnCancelUploadHandler(onCancelUploadHandler));
 		
 		registerHandler(display.getSendClick().addClickHandler(new ClickHandler() {
 
@@ -201,57 +221,45 @@
 					message.setSubject(display.getSubjectText().getText());
 					message.setText(display.getMessageText().getText());
 
-					message.setMessageAttachments(aList);
-				
+					message.setMessageAttachments(attachments);
+
+					// TODO: good handling of error messages, and use an error widget instead of Window.alert
 					if (type.equals(Type.NEW)) {
-						dispatcher.execute(new SendMessage(message), new SessionAsyncCallback<EmptyResult>(new AsyncCallback<EmptyResult>() {
-
-							public void onFailure(Throwable caught) {
-								// TODO Auto-generated method stub
-								
-							}
-
-							public void onSuccess(EmptyResult result) {
-								reset();
-								eventBus.fireEvent(new SentMessageEvent());
-							}
-							
-						}, eventBus,user));
+						dispatcher.execute(new SendMessage(message), new HupaCallback<GenericResult>(dispatcher, eventBus) {
+                            public void callback(GenericResult result) {
+								if (result.isSuccess()) {
+									eventBus.fireEvent(new SentMessageEvent());
+									reset();
+								} else {
+									Window.alert(result.getMessage());
+								}	
+                            }
+						});
 					} else if(type.equals(Type.FORWARD)) {
-						dispatcher.execute(new ForwardMessage(message, folder, oldmessage.getUid()), new SessionAsyncCallback<EmptyResult>(new AsyncCallback<EmptyResult>() {
-
-							public void onFailure(Throwable caught) {
-								// TODO Auto-generated method stub
-								
-							}
-
-							public void onSuccess(EmptyResult result) {
-								reset();
-								eventBus.fireEvent(new SentMessageEvent());
-							}
-							
-						}, eventBus,user));
+						dispatcher.execute(new ForwardMessage(message, folder, oldmessage.getUid()), new HupaCallback<GenericResult>(dispatcher, eventBus) {
+                            public void callback(GenericResult result) {
+								if (result.isSuccess()) {
+									eventBus.fireEvent(new SentMessageEvent());
+									reset();
+								} else {
+									Window.alert(result.getMessage());
+								}	
+                            }
+						});
 					} else if(type.equals(Type.REPLY) || type.equals(Type.REPLY_ALL)) {
-					
 						boolean replyAll = type.equals(Type.REPLY_ALL);
-						dispatcher.execute(new ReplyMessage(message, folder, oldmessage.getUid(), replyAll),new SessionAsyncCallback<EmptyResult>(new AsyncCallback<EmptyResult>() {
-
-							public void onFailure(Throwable caught) {
-								// TODO Auto-generated method stub
-								
-							}
-
-							public void onSuccess(EmptyResult result) {
-								reset();
-								eventBus.fireEvent(new SentMessageEvent());
-							}
-							
-						}, eventBus,user));
-					
+						dispatcher.execute(new ReplyMessage(message, folder, oldmessage.getUid(), replyAll), new HupaCallback<GenericResult>(dispatcher, eventBus) {
+                            public void callback(GenericResult result) {
+								if (result.isSuccess()) {
+									eventBus.fireEvent(new SentMessageEvent());
+									reset();
+								} else {
+									Window.alert(result.getMessage());
+								}	
+                            }
+						});
 					}
 				}
-		
-			
 		}));
 		
 		registerHandler(display.getBackButtonClick().addClickHandler(new ClickHandler() {
@@ -269,7 +277,7 @@
 		display.getCcText().setText("");
 		display.getToText().setText("");
 		display.getSubjectText().setText("");
-		aList.clear();
+		attachments.clear();
 		folder = null;
 		oldmessage = null;
 		type = Type.NEW;
Index: client/src/main/java/org/apache/hupa/client/mvp/MessageSendView.java
===================================================================
--- client/src/main/java/org/apache/hupa/client/mvp/MessageSendView.java	(revision 824847)
+++ client/src/main/java/org/apache/hupa/client/mvp/MessageSendView.java	(working copy)
@@ -23,7 +23,6 @@
 import gwtupload.client.IUploadStatus;
 import gwtupload.client.IUploader;
 import gwtupload.client.MultiUploader;
-import gwtupload.client.IUploader.OnStartUploaderHandler;
 
 import org.apache.hupa.client.HupaConstants;
 import org.apache.hupa.client.widgets.MyButton;
@@ -151,16 +150,10 @@
 		text.setVisibleLines(50);
 
 		uploadStatus.setCancelConfiguration(IUploadStatus.GMAIL_CANCEL_CFG);
-		uploader.addOnStartUploadHandler(new OnStartUploaderHandler() {
-			public void onStart(IUploader uploader) {
-				sendButton.setEnabled(false);
-			}
-		});
 		uploader.setServletPath(GWT.getModuleBaseURL() + "uploadAttachmentServlet");
 		uploader.avoidRepeatFiles(true);
 		uploader.setI18Constants(constants);
 		
-		
 		mPanel.add(detailGrid);
 
 		HorizontalPanel buttonBar = new HorizontalPanel();
Index: client/src/main/java/org/apache/hupa/client/mvp/MainPresenter.java
===================================================================
--- client/src/main/java/org/apache/hupa/client/mvp/MainPresenter.java	(revision 824847)
+++ client/src/main/java/org/apache/hupa/client/mvp/MainPresenter.java	(working copy)
@@ -24,7 +24,6 @@
 import java.util.Comparator;
 import java.util.List;
 
-import net.customware.gwt.presenter.client.DisplayCallback;
 import net.customware.gwt.presenter.client.EventBus;
 import net.customware.gwt.presenter.client.place.Place;
 import net.customware.gwt.presenter.client.place.PlaceRequest;
@@ -32,7 +31,7 @@
 import net.customware.gwt.presenter.client.widget.WidgetPresenter;
 
 import org.apache.hupa.client.CachingDispatchAsync;
-import org.apache.hupa.client.SessionAsyncCallback;
+import org.apache.hupa.client.HupaCallback;
 import org.apache.hupa.client.mvp.MessageSendPresenter.Type;
 import org.apache.hupa.client.widgets.HasDialog;
 import org.apache.hupa.client.widgets.IMAPTreeItem;
@@ -65,9 +64,9 @@
 import org.apache.hupa.shared.events.SentMessageEventHandler;
 import org.apache.hupa.shared.rpc.CreateFolder;
 import org.apache.hupa.shared.rpc.DeleteFolder;
-import org.apache.hupa.shared.rpc.EmptyResult;
 import org.apache.hupa.shared.rpc.FetchFolders;
 import org.apache.hupa.shared.rpc.FetchFoldersResult;
+import org.apache.hupa.shared.rpc.GenericResult;
 import org.apache.hupa.shared.rpc.GetMessageDetails;
 import org.apache.hupa.shared.rpc.GetMessageDetailsResult;
 import org.apache.hupa.shared.rpc.RenameFolder;
@@ -153,23 +152,14 @@
     }
 
     protected void loadTreeItems() {
-        cachingDispatcher.execute(new FetchFolders(), new SessionAsyncCallback<FetchFoldersResult>(new DisplayCallback<FetchFoldersResult>(display) {
-
-            @Override
-            protected void handleFailure(Throwable e) {
-                GWT.log("ERROR=", e);
-            }
-
-            @Override
-            protected void handleSuccess(FetchFoldersResult result) {
+        cachingDispatcher.execute(new FetchFolders(), new HupaCallback<FetchFoldersResult>(cachingDispatcher, eventBus, display) {
+			public void callback(FetchFoldersResult result) {
                 display.bindTreeItems(createTreeNodes(result.getFolders()));
-
                 // disable
                 display.getDeleteEnable().setEnabled(false);
                 display.getRenameEnable().setEnabled(false);
-            }
-
-        }, eventBus, user));
+			}
+		});
     }
 
     /**
@@ -192,19 +182,15 @@
                         IMAPFolder iFolder = new IMAPFolder((String) event.getOldValue());
                         final String newName = (String) event.getNewValue();
                         if (iFolder.getFullName().equalsIgnoreCase(newName) == false) {
-                            cachingDispatcher.execute(new RenameFolder(iFolder, newName), new SessionAsyncCallback<EmptyResult>(new AsyncCallback<EmptyResult>() {
-
-                                public void onFailure(Throwable caught) {
-                                    record.cancelEdit();
-                                }
-
-                                public void onSuccess(EmptyResult result) {
+                            cachingDispatcher.execute(new RenameFolder(iFolder, newName), new HupaCallback<GenericResult>(cachingDispatcher, eventBus) {
+                				public void callback(GenericResult result) {
                                     folder.setFullName(newName);
-                                }
-
-                            }, eventBus, user));
+                				}
+                				public void callbackError(Throwable caught) {
+                                    record.cancelEdit();
+                				}
+                			}); 
                         }
-
                     }
                 }
 
@@ -340,26 +326,14 @@
                 } else {
                     decreaseUnseen = false;
                 }
-                cachingDispatcher.executeWithCache(new GetMessageDetails(event.getFolder(), message.getUid()), new SessionAsyncCallback<GetMessageDetailsResult>(
-                        new DisplayCallback<GetMessageDetailsResult>(display) {
-
-                            @Override
-                            protected void handleFailure(Throwable e) {
-                                GWT.log("ERROR", e);
-                            }
-
-                            @Override
-                            protected void handleSuccess(GetMessageDetailsResult result) {
-                                // decrease the unseen count if we were able to
-                                // expose the message
-                                if (decreaseUnseen) {
-                                    eventBus.fireEvent(new DecreaseUnseenEvent(user, folder));
-                                }
-
-                                showMessage(user, folder, message, result.getMessageDetails());
-                            }
-
-                        }, eventBus, user));
+                cachingDispatcher.executeWithCache(new GetMessageDetails(event.getFolder(), message.getUid()), new HupaCallback<GetMessageDetailsResult>(cachingDispatcher, eventBus, display) {
+    				public void callback(GetMessageDetailsResult result) {
+                        if (decreaseUnseen) {
+                            eventBus.fireEvent(new DecreaseUnseenEvent(user, folder));
+                        }
+                        showMessage(user, folder, message, result.getMessageDetails());
+    				}
+    			});
             }
 
         }));
@@ -503,13 +477,13 @@
         registerHandler(display.getDeleteConfirmClick().addClickHandler(new ClickHandler() {
 
             public void onClick(ClickEvent event) {
-                cachingDispatcher.execute(new DeleteFolder(folder), new AsyncCallback<EmptyResult>() {
+                cachingDispatcher.execute(new DeleteFolder(folder), new AsyncCallback<GenericResult>() {
 
                     public void onFailure(Throwable caught) {
                         GWT.log("ERROR while deleting", caught);
                     }
 
-                    public void onSuccess(EmptyResult result) {
+                    public void onSuccess(GenericResult result) {
                         display.deleteSelectedFolder();
                     }
 
@@ -527,14 +501,14 @@
                         final IMAPTreeItem item = (IMAPTreeItem) event.getSource();
                         final String newValue = (String) event.getNewValue();
                         if (event.getEventType().equals(EditEvent.EventType.Stop)) {
-                            cachingDispatcher.execute(new CreateFolder(new IMAPFolder(newValue.trim())), new AsyncCallback<EmptyResult>() {
+                            cachingDispatcher.execute(new CreateFolder(new IMAPFolder(newValue.trim())), new AsyncCallback<GenericResult>() {
 
                                 public void onFailure(Throwable caught) {
                                     GWT.log("Error while create folder", caught);
                                     item.cancelEdit();
                                 }
 
-                                public void onSuccess(EmptyResult result) {
+                                public void onSuccess(GenericResult result) {
                                     // Nothing todo
                                 }
 
Index: client/src/main/java/org/apache/hupa/client/HupaCallback.java
===================================================================
--- client/src/main/java/org/apache/hupa/client/HupaCallback.java	(revision 824825)
+++ client/src/main/java/org/apache/hupa/client/HupaCallback.java	(working copy)
@@ -1,15 +1,16 @@
 package org.apache.hupa.client;
 
 import net.customware.gwt.dispatch.client.DispatchAsync;
+import net.customware.gwt.presenter.client.Display;
 import net.customware.gwt.presenter.client.EventBus;
 
 import org.apache.hupa.shared.events.LogoutEvent;
 import org.apache.hupa.shared.events.ServerStatusEvent;
 import org.apache.hupa.shared.events.ServerStatusEvent.ServerStatus;
+import org.apache.hupa.shared.exception.InvalidSessionException;
 import org.apache.hupa.shared.rpc.CheckSession;
 import org.apache.hupa.shared.rpc.CheckSessionResult;
 
-import com.google.gwt.core.client.GWT;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.inject.Inject;
 
@@ -19,8 +20,16 @@
 	private EventBus eventBus = null;
 	private ServerStatusEvent available = new ServerStatusEvent(ServerStatus.Available); 
 	private ServerStatusEvent unavailable = new ServerStatusEvent(ServerStatus.Unavailable); 
+    private Display display = null;
 
 	@Inject
+	public HupaCallback(DispatchAsync dispatcher, EventBus bus, Display display) {
+		this(dispatcher, bus);
+		this.display = display;
+		this.display.startProcessing();
+	}
+	
+	@Inject
 	public HupaCallback(DispatchAsync dispatcher, EventBus bus) {
 		this.dispatcher = dispatcher;
 		this.eventBus = bus;
@@ -34,9 +43,13 @@
 		// server unaccessible, session error or server exception
 		dispatcher.execute(new CheckSession(), new AsyncCallback<CheckSessionResult>() {
 			public void onFailure(Throwable caught) {
-				// The server is unaccessible
-				eventBus.fireEvent(unavailable);
-				callbackError(originalCaught);
+				if (caught instanceof InvalidSessionException) {
+					eventBus.fireEvent(new LogoutEvent(null));
+				} else {
+					// The server is unaccessible
+					eventBus.fireEvent(unavailable);
+				}
+				finish();
 			}
 			public void onSuccess(CheckSessionResult result) {
 				if (!result.isValid()) {
@@ -47,7 +60,13 @@
 					// So the original action failed because a server's exception 
 					eventBus.fireEvent(available);
 				}
+				finish();
+			}
+
+			private void finish() {
 				callbackError(originalCaught);
+				if (display != null)
+					display.stopProcessing();
 			}
 		});
 	}
@@ -60,10 +79,13 @@
 		eventBus.fireEvent(available);
 		// Execute the original method
 		callback(result);
+		// If display is being used, stop it
+		if (display != null)
+			display.stopProcessing();
 	}
 	
 	/**
-	 * The callback code
+	 * The callback code which the user has to implement
 	 * @param result
 	 */
 	public abstract void callback(T result); 
@@ -75,6 +97,6 @@
 	 * @param result
 	 */
 	public void callbackError(Throwable caught) {
-		GWT.log("Error", caught);
+		System.out.println("HupaCallBack Error: " + caught);
 	}
 }
Index: client/src/main/java/org/apache/hupa/client/SessionAsyncCallback.java
===================================================================
--- client/src/main/java/org/apache/hupa/client/SessionAsyncCallback.java	(revision 824825)
+++ client/src/main/java/org/apache/hupa/client/SessionAsyncCallback.java	(working copy)
@@ -1,66 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.hupa.client;
-
-import net.customware.gwt.presenter.client.EventBus;
-
-import org.apache.hupa.shared.data.User;
-import org.apache.hupa.shared.events.SessionExpireEvent;
-import org.apache.hupa.shared.exception.InvalidSessionException;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-
-/**
- * AsyncCallback which wraps an other AsyncCallback and checks if an InvalidSessionException was thrown. If so
- * it will fire an InvalidSessionEvent, if not it will just call the wrapped AsyncCallback
- */
-public class SessionAsyncCallback<T> implements AsyncCallback<T>{
-
-	private EventBus bus;
-	private User user;
-	private AsyncCallback<T> callBack; 
-	
-	public SessionAsyncCallback(AsyncCallback<T> callBack, EventBus bus,User user) {
-		this.callBack = callBack;
-		this.bus = bus;
-		this.user = user;
-	}
-	
-	/*
-	 * (non-Javadoc)
-	 * @see com.google.gwt.user.client.rpc.AsyncCallback#onFailure(java.lang.Throwable)
-	 */
-	public void onFailure(Throwable caught) {
-		if (caught instanceof InvalidSessionException) {
-			bus.fireEvent(new SessionExpireEvent(user));
-		} else {
-			callBack.onFailure(caught);
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * @see com.google.gwt.user.client.rpc.AsyncCallback#onSuccess(java.lang.Object)
-	 */
-	public void onSuccess(T result) {
-		callBack.onSuccess(result);
-	}
-
-}
Index: server/src/main/java/org/apache/hupa/server/servlet/UploadAttachmentServlet.java
===================================================================
--- server/src/main/java/org/apache/hupa/server/servlet/UploadAttachmentServlet.java	(revision 823413)
+++ server/src/main/java/org/apache/hupa/server/servlet/UploadAttachmentServlet.java	(working copy)
@@ -49,9 +49,13 @@
 	
 	@Override
 	public String executeAction(HttpServletRequest request, List<FileItem> sessionFiles) throws UploadActionException {
-        for (int i =0; i < sessionFiles.size(); i++) {
-        	registry.add(sessionFiles.get(i));
-        }
+		logger.info("Executing Action, files in session: " + sessionFiles.size() + " files in registry: " + registry.size());
+		// save file items in the registry
+		for(FileItem item: sessionFiles) 
+        	registry.add(item);
+		
+		// remove items from session but not remove the data from disk or memory
+        removeSessionFileItems(request, false);
         return null;
 	}
 	
Index: server/src/main/java/org/apache/hupa/server/servlet/MessageSourceServlet.java
===================================================================
--- server/src/main/java/org/apache/hupa/server/servlet/MessageSourceServlet.java	(revision 0)
+++ server/src/main/java/org/apache/hupa/server/servlet/MessageSourceServlet.java	(revision 0)
@@ -0,0 +1,97 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.hupa.server.servlet;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.mail.Folder;
+import javax.mail.Message;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.hupa.server.InMemoryIMAPStoreCache;
+import org.apache.hupa.shared.data.User;
+
+import com.google.inject.Inject;
+import com.sun.mail.imap.IMAPFolder;
+import com.sun.mail.imap.IMAPStore;
+
+/**
+ * Handle download of attachments
+ */
+public class MessageSourceServlet extends HttpServlet {
+
+	private static final long serialVersionUID = 1245563204035792963L;
+	private InMemoryIMAPStoreCache cache;
+	private Log logger;
+
+	@Inject
+	public MessageSourceServlet(InMemoryIMAPStoreCache cache, Log logger) {
+		this.cache = cache;
+		this.logger = logger;
+	}
+
+	/**
+	 * Handle to write back the requested attachment
+	 */
+	@Override
+	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+		User user = (User) request.getSession().getAttribute("user");
+
+		String message_uid = (String) request.getParameter("uid");
+		String folder = (String) request.getParameter("folder");
+		
+		try {
+			long uid = Long.parseLong(message_uid);
+
+			IMAPStore store = cache.get(user);
+			IMAPFolder f = (IMAPFolder) store.getFolder(folder);
+			if (f.isOpen() == false) {
+				f.open(Folder.READ_ONLY);
+			}
+
+			Message m = f.getMessageByUID(uid);
+
+			response.setContentType("text/plain");
+			OutputStream outs = response.getOutputStream();
+			m.writeTo(outs);
+			outs.flush();
+			outs.close();
+
+			if (f.isOpen()) {
+				f.close(false);
+			}
+		} catch (Exception e) {
+			logger.error("Unable to get raw content of msg for user " + user + " in folder " + folder + " with uid " + message_uid, e);
+			throw new ServletException("Unable to get raw content of msg for user " + user + " in folder " + folder + " with uid " + message_uid);
+		}
+	}
+
+	@Override
+	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+		doGet(request, response);
+	}
+
+}
Index: server/src/main/java/org/apache/hupa/server/FileItemRegistry.java
===================================================================
--- server/src/main/java/org/apache/hupa/server/FileItemRegistry.java	(revision 823413)
+++ server/src/main/java/org/apache/hupa/server/FileItemRegistry.java	(working copy)
@@ -21,6 +21,7 @@
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import org.apache.commons.fileupload.FileItem;
 import org.apache.commons.logging.Log;
@@ -42,13 +43,30 @@
 		map.put(item.getFieldName(), item);
 	}
 	
+	public void remove(String name) {
+		remove(get(name));
+	}
+	
 	public void remove(FileItem item) {
-		logger.debug("Remove item " + item.getName() + " with name " + item.getFieldName());
-		map.remove(item);
+		if (item != null) {
+			logger.debug("Remove item " + item.getName() + " with name " + item.getFieldName());
+			map.remove(item);
+			// Remove temporary stuff
+			item.delete();
+		}
 	}
 	
+	public void clear() {
+		for (Entry<String,FileItem> e: map.entrySet()) 
+			remove(e.getValue());
+	}
+	
 	public FileItem get(String name) {
-		logger.debug("Retrieve item " + name);
+		logger.debug("Retrieve item " + name + " isNull=" + (map.get(name) == null));
 		return map.get(name);
 	}
+	
+	public int size() {
+		return map.size();
+	}
 }
Index: server/src/main/java/org/apache/hupa/server/InMemoryIMAPStoreCache.java
===================================================================
--- server/src/main/java/org/apache/hupa/server/InMemoryIMAPStoreCache.java	(revision 823413)
+++ server/src/main/java/org/apache/hupa/server/InMemoryIMAPStoreCache.java	(working copy)
@@ -71,7 +71,7 @@
 	 * (non-Javadoc)
 	 * @see org.apache.hupa.server.IMAPStoreCache#get(org.apache.hupa.shared.data.User)
 	 */
-	public synchronized IMAPStore get(User user) throws MessagingException {
+	public IMAPStore get(User user) throws MessagingException {
 		return get(user.getName(),user.getPassword());
 	}
 	
@@ -79,7 +79,7 @@
 	 * (non-Javadoc)
 	 * @see org.apache.hupa.server.IMAPStoreCache#get(java.lang.String, java.lang.String)
 	 */
-	public synchronized IMAPStore get(String username, String password) throws MessagingException {
+	public IMAPStore get(String username, String password) throws MessagingException {
 		CachedIMAPStore cstore = pool.get(username);
 		if (cstore == null) {
 			logger.debug("No cached store found for user " +username);
@@ -89,7 +89,6 @@
 			    try {
 			        cstore.validate();
 			    } catch (MessagingException e) {
-			        
 			        cstore = createCachedIMAPStore();
 			    }
 			} else {
@@ -104,14 +103,9 @@
 		}
 		
 		if (cstore.getStore().isConnected() == false) {
-			// TODO: Full demo-mode able to mock all actions (folders, messages ...) 
-			// setting IMAPServerAddress=demo-mode allows login in the application using
-			// any user and password. It is thought to play the client application without
-			// having any imap/smtp server installed. Very useful while developing and testing. 
 			try {
 				cstore.getStore().connect(address, port, username, password);
 			} catch (MessagingException e) {
-				if (!DEMO_MODE.equals(this.address))
 					throw (e);
 			}
 		}
@@ -121,7 +115,9 @@
 	
 	private CachedIMAPStore createCachedIMAPStore() throws NoSuchProviderException {
 		CachedIMAPStore cstore;
-		if (useSSL) {
+		if (DEMO_MODE.equals(this.address)) {
+			cstore = new CachedIMAPStore(new DemoModeIMAPStore(session), 300);
+		} else if (useSSL) {
 			cstore = new CachedIMAPStore((IMAPStore)session.getStore("imaps"),300);
 		} else {
 			cstore =  new CachedIMAPStore((IMAPStore)session.getStore("imap"),300);
@@ -153,18 +149,18 @@
 	}
 	
 	private final class CachedIMAPStore {
-		private long validTo;
+		private long validUntil;
 		private int validForMillis;
 		private IMAPStore store;
 		
 		public CachedIMAPStore(IMAPStore store, int validForSeconds) {
 			this.store = store;
 			this.validForMillis = validForSeconds * 1000;
-			this.validTo = System.currentTimeMillis() + validForMillis;
+			this.validUntil = System.currentTimeMillis() + validForMillis;
 		}
 		
 		public boolean isExpired() {
-			if (validTo < System.currentTimeMillis() && store.isConnected()) {
+			if (validUntil > System.currentTimeMillis() && store.isConnected()) {
 				return false;
 			}
 			return true;
@@ -172,7 +168,7 @@
 		
 		public void validate() throws MessagingException {
 			store.idle();
-			validTo = System.currentTimeMillis() + validForMillis;
+			validUntil = System.currentTimeMillis() + validForMillis;
 		}
 		
 		public IMAPStore getStore() {
Index: server/src/main/java/org/apache/hupa/server/DemoModeSMTPTransport.java
===================================================================
--- server/src/main/java/org/apache/hupa/server/DemoModeSMTPTransport.java	(revision 0)
+++ server/src/main/java/org/apache/hupa/server/DemoModeSMTPTransport.java	(revision 0)
@@ -0,0 +1,46 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.hupa.server;
+
+import javax.mail.Address;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.URLName;
+
+
+public class DemoModeSMTPTransport extends Transport {
+
+	static final URLName demoUrl = new URLName(null, InMemoryIMAPStoreCache.DEMO_MODE, 143, null, null, null);
+	
+	public DemoModeSMTPTransport(Session session) {
+		super(session, demoUrl);
+	}
+
+	@Override
+    public void sendMessage(Message msg, Address[] addresses) throws MessagingException {
+    }
+    
+    @Override
+    public void connect(String host, int port, String user, String password) throws MessagingException {
+    }
+	
+}
Index: server/src/main/java/org/apache/hupa/server/guice/ServerModul.java
===================================================================
--- server/src/main/java/org/apache/hupa/server/guice/ServerModul.java	(revision 823413)
+++ server/src/main/java/org/apache/hupa/server/guice/ServerModul.java	(working copy)
@@ -28,6 +28,7 @@
 import net.customware.gwt.dispatch.server.guice.ActionHandlerModule;
 
 import org.apache.commons.logging.Log;
+import org.apache.hupa.server.DemoModeIMAPStore;
 import org.apache.hupa.server.FileItemRegistry;
 import org.apache.hupa.server.IMAPStoreCache;
 import org.apache.hupa.server.InMemoryIMAPStoreCache;
@@ -52,6 +53,7 @@
 import org.apache.hupa.server.handler.SetFlagsHandler;
 import org.apache.hupa.server.handler.TagMessagesHandler;
 import org.apache.hupa.server.servlet.DownloadAttachmentServlet;
+import org.apache.hupa.server.servlet.MessageSourceServlet;
 import org.apache.hupa.server.servlet.UploadAttachmentServlet;
 import org.apache.hupa.shared.data.Settings;
 
@@ -108,13 +110,20 @@
 				Singleton.class);
 		bind(DownloadAttachmentServlet.class).in(Singleton.class);
 		bind(UploadAttachmentServlet.class).in(Singleton.class);
+		bind(MessageSourceServlet.class).in(Singleton.class);
 		bind(Session.class).toProvider(SessionProvider.class);
-		// bind addresses and ports for imap and smtp
+
 		Properties properties;
 		try {
+			// Bind addresses and ports for imap and smtp
 			properties = loadProperties();
+			// Configure default parameters for Hupa in demo mode
+			if (properties.get("IMAPServerAddress").equals(InMemoryIMAPStoreCache.DEMO_MODE)) {
+				properties.put("DefaultInboxFolder", DemoModeIMAPStore.DEMO_MODE_INBOX_FOLDER);
+				properties.put("DefaultTrashFolder", DemoModeIMAPStore.DEMO_MODE_TRASH_FOLDER);
+				properties.put("DefaultSentFolder", DemoModeIMAPStore.DEMO_MODE_SENT_FOLDER);
+			}
 			Names.bindProperties(binder(), properties);
-
 		} catch (Exception e) {
 			throw new RuntimeException("Unable to to configure hupa server," +
 					"\nmake sure that you have a valid /etc/default/hupa file" +
Index: server/src/main/java/org/apache/hupa/server/guice/DispatchServletModule.java
===================================================================
--- server/src/main/java/org/apache/hupa/server/guice/DispatchServletModule.java	(revision 823413)
+++ server/src/main/java/org/apache/hupa/server/guice/DispatchServletModule.java	(working copy)
@@ -21,6 +21,7 @@
 
 
 import org.apache.hupa.server.servlet.DownloadAttachmentServlet;
+import org.apache.hupa.server.servlet.MessageSourceServlet;
 import org.apache.hupa.server.servlet.UploadAttachmentServlet;
 
 import net.customware.gwt.dispatch.server.service.DispatchServiceServlet;
@@ -31,11 +32,9 @@
 public class DispatchServletModule extends ServletModule{
 	 @Override
 	    public void configureServlets() {
-		 	serve( "/hupa/dispatch" ).with(DispatchServiceServlet.class );
+		 	serve("/hupa/dispatch").with(DispatchServiceServlet.class );
 		 	serve("/hupa/downloadAttachmentServlet").with(DownloadAttachmentServlet.class);
 		 	serve("/hupa/uploadAttachmentServlet").with(UploadAttachmentServlet.class);
-		 	
+		 	serve("/hupa/messageSourceServlet").with(MessageSourceServlet.class);
 	    }
-	 
-	 
 }
Index: server/src/main/java/org/apache/hupa/server/handler/RenameFolderHandler.java
===================================================================
--- server/src/main/java/org/apache/hupa/server/handler/RenameFolderHandler.java	(revision 823413)
+++ server/src/main/java/org/apache/hupa/server/handler/RenameFolderHandler.java	(working copy)
@@ -29,7 +29,7 @@
 import org.apache.hupa.server.IMAPStoreCache;
 import org.apache.hupa.shared.data.IMAPFolder;
 import org.apache.hupa.shared.data.User;
-import org.apache.hupa.shared.rpc.EmptyResult;
+import org.apache.hupa.shared.rpc.GenericResult;
 import org.apache.hupa.shared.rpc.RenameFolder;
 
 import com.google.inject.Inject;
@@ -40,7 +40,7 @@
  * Handler which handle renaming of folders
  *
  */
-public class RenameFolderHandler extends AbstractSessionHandler<RenameFolder, EmptyResult>{
+public class RenameFolderHandler extends AbstractSessionHandler<RenameFolder, GenericResult>{
 
 	@Inject
 	public RenameFolderHandler(IMAPStoreCache cache, Log logger,
@@ -52,7 +52,7 @@
 	 * (non-Javadoc)
 	 * @see org.apache.hupa.server.handler.AbstractSessionHandler#executeInternal(org.apache.hupa.shared.rpc.Session, net.customware.gwt.dispatch.server.ExecutionContext)
 	 */
-	protected EmptyResult executeInternal(RenameFolder action,
+	protected GenericResult executeInternal(RenameFolder action,
 			ExecutionContext context) throws ActionException {
 		User user = getUser();
 		IMAPFolder folder = action.getFolder();
@@ -66,7 +66,7 @@
 				iFolder.close(false);
 			}
 			if (iFolder.renameTo(newFolder)) {
-				return new EmptyResult();
+				return new GenericResult();
 			}
 			throw new ActionException("Unable to rename Folder " + folder.getFullName() + " to " + newName + " for user " + user);
 
Index: server/src/main/java/org/apache/hupa/server/handler/TagMessagesHandler.java
===================================================================
--- server/src/main/java/org/apache/hupa/server/handler/TagMessagesHandler.java	(revision 823413)
+++ server/src/main/java/org/apache/hupa/server/handler/TagMessagesHandler.java	(working copy)
@@ -33,7 +33,7 @@
 import org.apache.hupa.server.IMAPStoreCache;
 import org.apache.hupa.shared.data.Tag;
 import org.apache.hupa.shared.data.User;
-import org.apache.hupa.shared.rpc.EmptyResult;
+import org.apache.hupa.shared.rpc.GenericResult;
 import org.apache.hupa.shared.rpc.TagMessage;
 
 import com.google.inject.Inject;
@@ -45,7 +45,7 @@
  * Handler which use user flags for supporting tagging of messages
  *
  */
-public class TagMessagesHandler extends AbstractSessionHandler<TagMessage, EmptyResult>{
+public class TagMessagesHandler extends AbstractSessionHandler<TagMessage, GenericResult>{
 
 	@Inject
 	public TagMessagesHandler(IMAPStoreCache cache, Log logger,
@@ -57,7 +57,7 @@
 	 * (non-Javadoc)
 	 * @see org.apache.hupa.server.handler.AbstractSessionHandler#executeInternal(org.apache.hupa.shared.rpc.Session, net.customware.gwt.dispatch.server.ExecutionContext)
 	 */
-	protected EmptyResult executeInternal(TagMessage action,
+	protected GenericResult executeInternal(TagMessage action,
 			ExecutionContext context) throws ActionException {
 		User user = getUser();
 		ArrayList<Long> uids = action.getMessageUids();
@@ -74,7 +74,7 @@
 				Message m = messages[i];
 				m.getFlags().add(tag.toString());
 			}
-			return new EmptyResult();
+			return new GenericResult();
 		} catch (MessagingException e) {
 			logger.error("Error while tag messages " + uids.toString() + " for user " + user + " of folder" + action.getFolder(), e);
 			throw new ActionException(e);
Index: server/src/main/java/org/apache/hupa/server/handler/AbstractSessionHandler.java
===================================================================
--- server/src/main/java/org/apache/hupa/server/handler/AbstractSessionHandler.java	(revision 823413)
+++ server/src/main/java/org/apache/hupa/server/handler/AbstractSessionHandler.java	(working copy)
@@ -54,14 +54,10 @@
 	}
 
 	/**
-	 * Check if the session is valid, if that is true execute executeInternal method
+	 * Execute executeInternal method
 	 */
 	public R execute(A action, ExecutionContext context) throws ActionException {
-		if (isValidSession()) {
-			return executeInternal(action, context);
-		} else {
-			throw new InvalidSessionException("Invalid Session");
-		}
+		return executeInternal(action, context);
 	}
 	
 	/**
@@ -79,17 +75,6 @@
 	protected abstract R executeInternal(A action, ExecutionContext context) throws ActionException;
 	
 	/**
-	 * Return if the given session id is still valid
-	 * 
-	 * @param sessionId
-	 * @return isValid
-	 */
-	protected boolean isValidSession() {
-		// TODO: MCM delete or implement this method
-		return true;
-	}
-	
-	/**
 	 * Return the User stored in session with the given id
 	 * 
 	 * @param sessionId 
Index: server/src/main/java/org/apache/hupa/server/handler/SetFlagsHandler.java
===================================================================
--- server/src/main/java/org/apache/hupa/server/handler/SetFlagsHandler.java	(revision 823413)
+++ server/src/main/java/org/apache/hupa/server/handler/SetFlagsHandler.java	(working copy)
@@ -35,14 +35,14 @@
 import org.apache.hupa.server.IMAPStoreCache;
 import org.apache.hupa.shared.data.IMAPFolder;
 import org.apache.hupa.shared.data.User;
-import org.apache.hupa.shared.rpc.EmptyResult;
+import org.apache.hupa.shared.rpc.GenericResult;
 import org.apache.hupa.shared.rpc.SetFlag;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.sun.mail.imap.IMAPStore;
 
-public class SetFlagsHandler extends AbstractSessionHandler<SetFlag, EmptyResult>{
+public class SetFlagsHandler extends AbstractSessionHandler<SetFlag, GenericResult>{
 
 	@Inject
 	public SetFlagsHandler(IMAPStoreCache cache, Log logger,
@@ -51,7 +51,7 @@
 	}
 
 	@Override
-	protected EmptyResult executeInternal(SetFlag action,
+	protected GenericResult executeInternal(SetFlag action,
 			ExecutionContext context) throws ActionException {
 		User user = getUser();
 		IMAPFolder folder = action.getFolder();
@@ -70,7 +70,7 @@
 			flags.add(flag);
 			
 			f.setFlags(msgs, flags, action.getValue());
-			return new EmptyResult();
+			return new GenericResult();
 		} catch (MessagingException e) {
 			String errorMsg = "Error while setting flags of messages with uids " + uids + " for user " + user;
 			logger.error(errorMsg,e);
Index: server/src/main/java/org/apache/hupa/server/handler/AbstractSendMessageHandler.java
===================================================================
--- server/src/main/java/org/apache/hupa/server/handler/AbstractSendMessageHandler.java	(revision 823413)
+++ server/src/main/java/org/apache/hupa/server/handler/AbstractSendMessageHandler.java	(working copy)
@@ -29,6 +29,7 @@
 import javax.activation.DataHandler;
 import javax.activation.DataSource;
 import javax.mail.Address;
+import javax.mail.AuthenticationFailedException;
 import javax.mail.Folder;
 import javax.mail.Message;
 import javax.mail.MessagingException;
@@ -48,12 +49,14 @@
 
 import org.apache.commons.fileupload.FileItem;
 import org.apache.commons.logging.Log;
+import org.apache.hupa.server.DemoModeSMTPTransport;
 import org.apache.hupa.server.FileItemRegistry;
 import org.apache.hupa.server.IMAPStoreCache;
+import org.apache.hupa.server.InMemoryIMAPStoreCache;
 import org.apache.hupa.shared.data.MessageAttachment;
 import org.apache.hupa.shared.data.SMTPMessage;
 import org.apache.hupa.shared.data.User;
-import org.apache.hupa.shared.rpc.EmptyResult;
+import org.apache.hupa.shared.rpc.GenericResult;
 import org.apache.hupa.shared.rpc.SendMessage;
 
 import com.google.inject.Inject;
@@ -66,7 +69,7 @@
  * Handle sending of email messages
  * 
  */
-public abstract class AbstractSendMessageHandler<A extends SendMessage> extends AbstractSessionHandler<A,EmptyResult> {
+public abstract class AbstractSendMessageHandler<A extends SendMessage> extends AbstractSessionHandler<A,GenericResult> {
 
 	private final FileItemRegistry registry;
 	private final Properties props = new Properties();
@@ -135,6 +138,15 @@
 		message.saveChanges();
 		return message;
 	}
+
+	protected void resetAttachments(A action) throws MessagingException, ActionException {
+		SMTPMessage m = action.getMessage();
+		ArrayList<MessageAttachment> attachments = m.getMessageAttachments();
+		if (attachments != null && ! attachments.isEmpty()) {
+			for(MessageAttachment attach : attachments) 
+				registry.remove(attach.getName());
+		}
+	}
 	
 	/**
 	 * Construct the multipart for the given attachments and return it
@@ -146,10 +158,12 @@
 	 */
 	protected Multipart handleAttachments(Multipart multipart, ArrayList<MessageAttachment> attachments) throws MessagingException {
 		if (attachments != null) {
-			// lopp over the attachments
-			for (int i = 0; i < attachments.size(); i++) {
+			for(MessageAttachment attachment: attachments) {
 				// get the attachment from the registry
-				FileItem fItem = registry.get(attachments.get(i).getName());
+				FileItem fItem = registry.get(attachment.getName());
+				if (fItem == null)
+					continue;
+				
 				// Part two is attachment
 				MimeBodyPart messageBodyPart = new MimeBodyPart();
 				DataSource source = new FileItemDataStore(fItem);
@@ -160,51 +174,54 @@
 		}
 		return multipart;
 	}
+
 	protected void sendMessage(User user, Session session, Message message) throws MessagingException {
 		Transport transport;
-		if (useSSL) {
+	
+		if (InMemoryIMAPStoreCache.DEMO_MODE.equals(address)) {
+			transport = new DemoModeSMTPTransport(session);
+		} else if (useSSL) {
 			transport = session.getTransport("smtps");
-
 		} else {
 			transport = session.getTransport("smtp");
 		}
-		// check if smtp auth is needed
+
 		if (auth) {
 			logger.debug("Use auth for smtp connection");
-
 			transport.connect(address,port,user.getName(), user.getPassword());
 		} else {
 			transport.connect(address, port, null,null);
 		}
+		
 		logger.info("Send message from " + message.getFrom()[0].toString()+ " to " + message.getRecipients(RecipientType.TO).toString());
 		transport.sendMessage(message, message.getAllRecipients());
-		
-		// store message in sent folder
-		IMAPStore iStore = cache.get(user);
-		IMAPFolder folder = (IMAPFolder) iStore.getFolder(user.getSettings().getSentFolderName());
-		
-		boolean exists = false;
-		if (folder.exists() == false) {
-			exists = folder.create(IMAPFolder.READ_WRITE);
-		} else {
-			exists = true;
-		}
-		if (exists) {
-			if (folder.isOpen() == false) {
-				folder.open(Folder.READ_WRITE);
-			}
-			message.setFlag(Flag.SEEN, true);
-			folder.appendMessages(new Message[] {message});
-			
-			try {
-				folder.close(false);
-			} catch (MessagingException e) {
-				// we don't care on close
-			}
+	}
 
-		}
-		
-	}
+	protected void saveSentMessage(User user, Message message) throws MessagingException {
+	    IMAPStore iStore = cache.get(user);
+	    IMAPFolder folder = (IMAPFolder) iStore.getFolder(user.getSettings().getSentFolderName());
+	    
+	    boolean exists = false;
+	    if (folder.exists() == false) {
+	    	exists = folder.create(IMAPFolder.READ_WRITE);
+	    } else {
+	    	exists = true;
+	    }
+	    if (exists) {
+	    	if (folder.isOpen() == false) {
+	    		folder.open(Folder.READ_WRITE);
+	    	}
+	    	message.setFlag(Flag.SEEN, true);
+	    	folder.appendMessages(new Message[] {message});
+	    	
+	    	try {
+	    		folder.close(false);
+	    	} catch (MessagingException e) {
+	    		// we don't care on close
+	    	}
+
+	    }
+    }
 	
 	
 
@@ -265,27 +282,35 @@
 
 
 	@Override
-	protected EmptyResult executeInternal(A action, ExecutionContext context)
+	protected GenericResult executeInternal(A action, ExecutionContext context)
 			throws ActionException {
+		GenericResult result = new GenericResult();
 		try {
 			Session session = Session.getDefaultInstance(props);
 
 			Message message = createMessage(session, action);
 			message = fillBody(message,action);
-			
+
 			sendMessage(getUser(),session, message);
-			
+			saveSentMessage(getUser(), message);
+			resetAttachments(action);
 		
+			// TODO: notify the user more accurately where is the error
+			// if the message was sent and the storage in the sent folder failed, etc.
 		} catch (AddressException e) {
+			result.setError("Error while parsing recipient: " + e.getMessage());
 			logger.error("Error while parsing recipient", e);
-			throw new ActionException("Error while parsing recipient");
+		} catch (AuthenticationFailedException e) {
+			result.setError("Error while sending message: SMTP Authentication error.");
+			logger.error("SMTP Authentication error", e);
 		} catch (MessagingException e) {
+			result.setError("Error while sending message: " + e.getMessage());
 			logger.error("Error while sending message", e);
-			throw new ActionException("Error while sending message");
-		} catch (NullPointerException e) {
-			e.printStackTrace();
+		} catch (Exception e) {
+			result.setError("Unexpected exception while sendig message: " + e.getMessage());
+			logger.error("Unexpected exception while sendig message: ", e);
 		}
-		return new EmptyResult();
+		return result;
 	}
 
 	/**
Index: server/src/main/java/org/apache/hupa/server/handler/DeleteFolderHandler.java
===================================================================
--- server/src/main/java/org/apache/hupa/server/handler/DeleteFolderHandler.java	(revision 823413)
+++ server/src/main/java/org/apache/hupa/server/handler/DeleteFolderHandler.java	(working copy)
@@ -30,7 +30,7 @@
 import org.apache.hupa.shared.data.IMAPFolder;
 import org.apache.hupa.shared.data.User;
 import org.apache.hupa.shared.rpc.DeleteFolder;
-import org.apache.hupa.shared.rpc.EmptyResult;
+import org.apache.hupa.shared.rpc.GenericResult;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -41,7 +41,7 @@
  * 
  *
  */
-public class DeleteFolderHandler extends AbstractSessionHandler<DeleteFolder, EmptyResult>{
+public class DeleteFolderHandler extends AbstractSessionHandler<DeleteFolder, GenericResult>{
 
 	@Inject
 	public DeleteFolderHandler(IMAPStoreCache cache, Log logger,
@@ -50,7 +50,7 @@
 	}
 
 	@Override
-	protected EmptyResult executeInternal(DeleteFolder action,
+	protected GenericResult executeInternal(DeleteFolder action,
 			ExecutionContext context) throws ActionException {
 		User user = getUser();
 		IMAPFolder folder = action.getFolder();
@@ -67,7 +67,7 @@
 			// recursive delete the folder
 			if (f.delete(true)) {
 				logger.info("Successfully delete folder " + folder + " for user " + user);
-				return new EmptyResult();
+				return new GenericResult();
 			} else {
 				throw new ActionException("Unable to delete folder " + folder + " for user " + user);
 			}
Index: server/src/main/java/org/apache/hupa/server/handler/CreateFolderHandler.java
===================================================================
--- server/src/main/java/org/apache/hupa/server/handler/CreateFolderHandler.java	(revision 823413)
+++ server/src/main/java/org/apache/hupa/server/handler/CreateFolderHandler.java	(working copy)
@@ -30,7 +30,7 @@
 import org.apache.hupa.shared.data.IMAPFolder;
 import org.apache.hupa.shared.data.User;
 import org.apache.hupa.shared.rpc.CreateFolder;
-import org.apache.hupa.shared.rpc.EmptyResult;
+import org.apache.hupa.shared.rpc.GenericResult;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -41,7 +41,7 @@
  * 
  *
  */
-public class CreateFolderHandler extends AbstractSessionHandler<CreateFolder, EmptyResult>{
+public class CreateFolderHandler extends AbstractSessionHandler<CreateFolder, GenericResult>{
 
 	@Inject
 	public CreateFolderHandler(IMAPStoreCache cache, Log logger,
@@ -50,7 +50,7 @@
 	}
 
 	@Override
-	protected EmptyResult executeInternal(CreateFolder action,
+	protected GenericResult executeInternal(CreateFolder action,
 			ExecutionContext context) throws ActionException {
 		User user = getUser();
 		IMAPFolder folder = action.getFolder();
@@ -60,7 +60,7 @@
 			Folder f = store.getFolder(folder.getFullName());
 			if (f.create(Folder.HOLDS_MESSAGES)) {
 				logger.info("Successfully create folder " + folder + " for user " + user);
-				return new EmptyResult();
+				return new GenericResult();
 			} else {
 				logger.info("Unable to create folder " + folder + " for user " + user);
 				throw new ActionException("Unable to create folder " + folder + " for user " + user);
Index: server/src/main/java/org/apache/hupa/server/DemoModeIMAPStore.java
===================================================================
--- server/src/main/java/org/apache/hupa/server/DemoModeIMAPStore.java	(revision 0)
+++ server/src/main/java/org/apache/hupa/server/DemoModeIMAPStore.java	(revision 0)
@@ -0,0 +1,136 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.hupa.server;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Vector;
+
+import javax.mail.Folder;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.URLName;
+
+import com.sun.mail.imap.IMAPFolder;
+import com.sun.mail.imap.IMAPStore;
+
+
+// TODO: implement full set of methods
+public class DemoModeIMAPStore extends IMAPStore {
+	
+	public static final String DEMO_MODE_DEFAULT_FOLDER = "/";
+	public static final String DEMO_MODE_INBOX_FOLDER = "Demo-Inbox";
+	public static final String DEMO_MODE_SENT_FOLDER = "Demo-Sent";
+	public static final String DEMO_MODE_TRASH_FOLDER = "Demo-Trash";
+	
+	
+	static final URLName demoUrl = new URLName(null, InMemoryIMAPStoreCache.DEMO_MODE, 143, null, null, null);
+	static final HashMap<String, Folder> folders = new HashMap<String, Folder>();
+
+	public DemoModeIMAPStore(Session session) {
+		super(session, demoUrl);
+	}
+
+	@Override
+	public boolean isConnected() {
+		return true;
+	}
+	
+	@Override
+	public void idle() throws MessagingException {
+	}
+
+	@Override
+	public Folder getFolder(String name) throws MessagingException {
+		Folder ret = folders.get(name) != null ? folders.get(name) : new DemoModeIMAPFolder(name, this) {};
+		folders.put(name, ret);
+		return ret;
+	}
+
+	@Override
+	public Folder getDefaultFolder() throws MessagingException {
+		return getFolder(DEMO_MODE_DEFAULT_FOLDER);
+	}
+
+	private class DemoModeIMAPFolder extends IMAPFolder {
+		String fullName = null;
+		IMAPStore store = null;
+		Vector<Message> messages = new Vector<Message>();
+
+		DemoModeIMAPFolder(String fullName, IMAPStore store) {
+			super(fullName, '/', store);
+			this.fullName = fullName;
+			this.store = store;
+		}
+
+		@Override
+		public void open(int mode) throws MessagingException {
+		}
+
+		@Override
+		public int getMessageCount() throws MessagingException {
+			return messages.size();
+		}
+
+		@Override
+		public int getUnreadMessageCount() throws MessagingException {
+			return 0;
+		}
+
+		@Override
+		public boolean delete(boolean recurse) throws MessagingException {
+			return true;
+		}
+
+		@Override
+		public Folder[] list(String pattern) throws MessagingException {
+			if (DEMO_MODE_DEFAULT_FOLDER.equals(fullName)) { 
+				return new Folder[] { 
+					store.getFolder(DEMO_MODE_INBOX_FOLDER), 
+					store.getFolder(DEMO_MODE_SENT_FOLDER), 
+					store.getFolder(DEMO_MODE_TRASH_FOLDER) 
+					};
+			}
+			return new Folder[0];
+		}
+		
+		@Override
+		public boolean create(int type) throws MessagingException {
+			return true;
+		}
+		
+		@Override
+	    public boolean exists() throws MessagingException {
+	    	return true;
+	    }
+		
+		@Override
+		public void appendMessages(Message[] msgs) {
+			messages.addAll(Arrays.asList(msgs));
+		}
+		
+		@Override
+		public void close(boolean expunge) throws MessagingException {
+		}
+		
+	}
+
+}
Index: shared/src/main/java/org/apache/hupa/shared/rpc/RenameFolder.java
===================================================================
--- shared/src/main/java/org/apache/hupa/shared/rpc/RenameFolder.java	(revision 824826)
+++ shared/src/main/java/org/apache/hupa/shared/rpc/RenameFolder.java	(working copy)
@@ -23,7 +23,7 @@
 
 import org.apache.hupa.shared.data.IMAPFolder;
 
-public class RenameFolder implements Action<EmptyResult>{
+public class RenameFolder implements Action<GenericResult>{
 
 	private static final long serialVersionUID = 1924419911921600320L;
 	private IMAPFolder folder;

Property changes on: shared/src/main/java/org/apache/hupa/shared/rpc/NoopResult.java
___________________________________________________________________
Added: svn:mergeinfo

Index: shared/src/main/java/org/apache/hupa/shared/rpc/MoveMessageResult.java
===================================================================
--- shared/src/main/java/org/apache/hupa/shared/rpc/MoveMessageResult.java	(revision 824826)
+++ shared/src/main/java/org/apache/hupa/shared/rpc/MoveMessageResult.java	(working copy)
@@ -19,7 +19,7 @@
 
 package org.apache.hupa.shared.rpc;
 
-public class MoveMessageResult extends EmptyResult{
+public class MoveMessageResult extends GenericResult{
 
 	/**
 	 * 

Property changes on: shared/src/main/java/org/apache/hupa/shared/rpc/Noop.java
___________________________________________________________________
Added: svn:mergeinfo

Index: shared/src/main/java/org/apache/hupa/shared/rpc/GenericResult.java
===================================================================
--- shared/src/main/java/org/apache/hupa/shared/rpc/GenericResult.java	(revision 0)
+++ shared/src/main/java/org/apache/hupa/shared/rpc/GenericResult.java	(revision 0)
@@ -0,0 +1,41 @@
+package org.apache.hupa.shared.rpc;
+
+import net.customware.gwt.dispatch.shared.Result;
+
+public class GenericResult implements Result{
+	
+	private static final long serialVersionUID = 405509532584299203L;
+	private String message = null;
+	private boolean success = true;
+
+	public GenericResult() {
+	}
+
+	public GenericResult(String message, boolean success) {
+		this.message = message;
+		this.success = success;
+	}
+
+	public String getMessage() {
+    	return message;
+    }
+
+	public boolean isSuccess() {
+    	return success;
+    }
+
+	public void setMessage(String message) {
+    	this.message = message;
+    }
+
+	public void setSuccess(boolean success) {
+    	this.success = success;
+    }
+	
+	public void setError(String message) {
+		setMessage(message);
+		setSuccess(false);
+	}
+	
+
+}
Index: shared/src/main/java/org/apache/hupa/shared/rpc/TagMessage.java
===================================================================
--- shared/src/main/java/org/apache/hupa/shared/rpc/TagMessage.java	(revision 824826)
+++ shared/src/main/java/org/apache/hupa/shared/rpc/TagMessage.java	(working copy)
@@ -27,7 +27,7 @@
 import org.apache.hupa.shared.data.IMAPFolder;
 import org.apache.hupa.shared.data.Tag;
 
-public class TagMessage implements Action<EmptyResult>{
+public class TagMessage implements Action<GenericResult>{
 
 	private static final long serialVersionUID = 4323236257115412763L;
 	private IMAPFolder folder;
Index: shared/src/main/java/org/apache/hupa/shared/rpc/EmptyResult.java
===================================================================
--- shared/src/main/java/org/apache/hupa/shared/rpc/EmptyResult.java	(revision 824826)
+++ shared/src/main/java/org/apache/hupa/shared/rpc/EmptyResult.java	(working copy)
@@ -1,16 +0,0 @@
-package org.apache.hupa.shared.rpc;
-
-import net.customware.gwt.dispatch.shared.Result;
-
-public class EmptyResult implements Result{
-	
-	/**
-	 * 
-	 */
-	private static final long serialVersionUID = 405509532584299203L;
-
-	public EmptyResult() {
-		
-	}
-
-}
Index: shared/src/main/java/org/apache/hupa/shared/rpc/CreateFolder.java
===================================================================
--- shared/src/main/java/org/apache/hupa/shared/rpc/CreateFolder.java	(revision 824826)
+++ shared/src/main/java/org/apache/hupa/shared/rpc/CreateFolder.java	(working copy)
@@ -23,7 +23,7 @@
 
 import org.apache.hupa.shared.data.IMAPFolder;
 
-public class CreateFolder implements Action<EmptyResult>{
+public class CreateFolder implements Action<GenericResult>{
 
 	private static final long serialVersionUID = -4966856616698265177L;
 	private IMAPFolder folder;
Index: shared/src/main/java/org/apache/hupa/shared/rpc/SetFlag.java
===================================================================
--- shared/src/main/java/org/apache/hupa/shared/rpc/SetFlag.java	(revision 824826)
+++ shared/src/main/java/org/apache/hupa/shared/rpc/SetFlag.java	(working copy)
@@ -26,7 +26,7 @@
 import org.apache.hupa.shared.data.IMAPFolder;
 import org.apache.hupa.shared.data.Message.IMAPFlag;
 
-public class SetFlag implements Action<EmptyResult>{
+public class SetFlag implements Action<GenericResult>{
 
 	private static final long serialVersionUID = 662741801793895357L;
 	private IMAPFlag flag;
Index: shared/src/main/java/org/apache/hupa/shared/rpc/SendMessage.java
===================================================================
--- shared/src/main/java/org/apache/hupa/shared/rpc/SendMessage.java	(revision 824826)
+++ shared/src/main/java/org/apache/hupa/shared/rpc/SendMessage.java	(working copy)
@@ -24,7 +24,7 @@
 
 import org.apache.hupa.shared.data.SMTPMessage;
 
-public class SendMessage implements Action<EmptyResult>{
+public class SendMessage implements Action<GenericResult>{
 	
 	private static final long serialVersionUID = 973668124208945015L;
 
Index: shared/src/main/java/org/apache/hupa/shared/rpc/DeleteFolder.java
===================================================================
--- shared/src/main/java/org/apache/hupa/shared/rpc/DeleteFolder.java	(revision 824826)
+++ shared/src/main/java/org/apache/hupa/shared/rpc/DeleteFolder.java	(working copy)
@@ -23,7 +23,7 @@
 
 import org.apache.hupa.shared.data.IMAPFolder;
 
-public class DeleteFolder implements Action<EmptyResult>{
+public class DeleteFolder implements Action<GenericResult>{
 
 	private static final long serialVersionUID = 7921329310932404439L;
 	
