Index: trunk/src/org/expeditee/auth/Actions.java
===================================================================
--- trunk/src/org/expeditee/auth/Actions.java	(revision 1503)
+++ trunk/src/org/expeditee/auth/Actions.java	(revision 1504)
@@ -9,17 +9,15 @@
 import java.nio.file.StandardCopyOption;
 import java.security.InvalidKeyException;
-import java.security.KeyFactory;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
 import java.security.PublicKey;
 import java.security.SecureRandom;
 import java.security.cert.CertificateException;
 import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
 import java.sql.SQLException;
 import java.text.ParseException;
 import java.util.Base64;
 import java.util.Collection;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
@@ -57,12 +55,10 @@
 import org.expeditee.items.Text;
 import org.expeditee.settings.UserSettings;
-import org.expeditee.settings.identity.secrets.KeyList;
-import org.expeditee.stats.Formatter;
 
 public class Actions implements CryptographyConstants {
-	
-	//	Start Debug Actions
-	public static void SendTestMessage(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, FileNotFoundException, KeyStoreException, CertificateException, ClassNotFoundException, IOException, SQLException {
-		String time = org.expeditee.stats.Formatter.getDateTime();
+
+	// Start Debug Actions
+	public static void SendTestMessage(String recipient) {
+		String time = Mail.FORMAT.format(new Date());
 		String sender = UserSettings.UserName.get();
 		String topic = "Test Message";
@@ -70,24 +66,20 @@
 		Map<String, String> options = new HashMap<String, String>();
 		options.put("Neat", "Beep");
-		MailEntry mail = new MailEntry(time, sender, colleagueName, topic, message, options);
-		Mail.sendMail(mail, colleagueName);
+		Mail mailClient = MailBay.getMailClient();
+		Mail.MailEntry mail = mailClient.new MailEntry(time, sender, recipient, topic, message, options);
+		mailClient.sendMail(mail, recipient);
 		MessageBay.displayMessage("Test message sent.");
 	}
-	
-	public static void SendTestMessageHemi(String param) {
-		String time = Formatter.getDateTime();
-		String sender = UserSettings.UserName.get();
-		String recipient = param.split(" ")[0];
-		String message = param.split(" ")[1];
-		Map<String, String> options = new HashMap<String, String>();
-		options.put("Accept", "beep");
-		options.put("Reject", "beep");
-		MailEntry mail = new MailEntry(time, sender, recipient, "Have a key", message, options);
-		Mail.sendMail(mail, recipient);
-		MessageBay.displayMessage("Test message sent.");
-	}
-	
-	public static void SendTestOneOffMessage(String colleagueName) {
-		String time = Formatter.getDateTime();
+		
+	public static void CheckMailTest() {
+		List<Mail.MailEntry> mail = MailBay.getMailClient().checkMail();
+		for (Mail.MailEntry entry: mail) {
+			MessageBay.displayMessage(entry.toString());
+		}
+		MessageBay.displayMessage(mail.size() + " new mail since last run.");
+	}
+	
+	public static void SendTestOneOffMessage(String recipient) {
+		String time = Mail.FORMAT.format(new Date());
 		String sender = UserSettings.UserName.get();
 		String topic = "Test Message";
@@ -95,10 +87,14 @@
 		Map<String, String> options = new HashMap<String, String>();
 		options.put("Neat", "Beep");
-		MailEntry mail = new MailEntry(time, sender, colleagueName, topic, message, options);
+		
 		Random rand = new SecureRandom();
-		byte[] key = new byte[16];
-		rand.nextBytes(key);
-		System.out.println(Base64.getEncoder().encodeToString(key));
-		Mail.sendOneOffMail(mail, colleagueName, key);
+		byte[] keyBytes = new byte[16];
+		rand.nextBytes(keyBytes);
+		SecretKey key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
+		System.out.println(Base64.getEncoder().encodeToString(keyBytes));
+		
+		Mail mailClient = MailBay.getMailClient();
+		Mail.MailEntry mail = mailClient.new MailEntry(time, sender, recipient, topic, message, options);
+		mailClient.sendOneOffMail(mail, recipient, key);
 		MessageBay.displayMessage("Test message sent.");
 	}
@@ -114,4 +110,8 @@
 	
 	//	Start Misc Auth Actions
+	public static void CheckForNewMail() {
+		MailBay.checkMail();
+	}
+	
 	/**
 	 * Action ran by user to read a message using a single use distributed Symmetric key 
@@ -124,5 +124,5 @@
 		SecretKey key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
 		List<String> data = actionItem.getData();
-		Mail.decryptOneOffSecureMessage(key, data);
+		MailBay.decryptOneOffSecureMessage(key, data);
 		StandardGestureActions.Refresh();
 	}
@@ -146,12 +146,7 @@
 	public static void ToggleBay() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, SQLException, IOException, ParseException, InvalidKeySpecException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
 		if (!AuthenticatorBrowser.isAuthenticated()) return;
-		if (!DisplayController.isMailMode()) {
-			MailBay.ensureLink();
-			Mail.clear();
-			String keyEncoded = KeyList.PrivateKey.get().getData().get(0);
-			byte[] keyBytes = Base64.getDecoder().decode(keyEncoded);
-			PrivateKey key = KeyFactory.getInstance(AsymmetricAlgorithm).generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
-			Mail.checkMail(key);
-		}
+		//if (!DisplayController.isMailMode()) {
+		//	MailBayV2.checkMail();
+		//}
 		DisplayController.ToggleMailMode();
 	}
@@ -558,16 +553,16 @@
 	@SuppressWarnings("unused")
 	private static boolean submitTrustedUsersPasswordRecovery(Map<AuthenticationTag, String> userData) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
-		String colleagueOne = userData.get(AuthenticationTag.TrustedUserOne);
-		String colleagueTwo = userData.get(AuthenticationTag.TrustedUserTwo);
-		PublicKey colleagueOneKey = AuthenticatorBrowser.getInstance().getPublicKey(colleagueOne);
-		PublicKey colleagueTwoKey = AuthenticatorBrowser.getInstance().getPublicKey(colleagueTwo);
+		String trustedUserOne = userData.get(AuthenticationTag.TrustedUserOne);
+		String trustedUserTwo = userData.get(AuthenticationTag.TrustedUserTwo);
+		PublicKey colleagueOneKey = AuthenticatorBrowser.getInstance().getPublicKey(trustedUserOne);
+		PublicKey colleagueTwoKey = AuthenticatorBrowser.getInstance().getPublicKey(trustedUserTwo);
 		if (colleagueOneKey == null) {
-			MessageBay.errorMessage("Unable to get public key for colleague: " + colleagueOne);
+			MessageBay.errorMessage("Unable to get public key for colleague: " + trustedUserOne);
 			return false;
 		} else if (colleagueTwoKey == null) {
-			MessageBay.errorMessage("Unable to get public key for colleague: " + colleagueTwo);
+			MessageBay.errorMessage("Unable to get public key for colleague: " + trustedUserTwo);
 			return false;
 		} else {
-			String time = org.expeditee.stats.Formatter.getDateTime();
+			String time = Mail.FORMAT.format(new Date());
 			String sender = userData.get(AuthenticationTag.Username);
 			String topic = "You have received a request for cooperation from your colleague " + sender;
@@ -576,8 +571,9 @@
 			arguments.put("I agree to assist " + sender + " if they loose access to their account.", "AuthConfirmPasswordColleagueRelationship " + sender);
 			arguments.put("I wish to excuse myself from this responsibility.", "AuthDenyPasswordColleagueRelationship " + sender);
-			MailEntry mail = new MailEntry(time, sender, colleagueOne, topic, message, arguments);
-			Mail.sendMail(mail, colleagueOne);
-			mail = new MailEntry(time, sender, colleagueTwo, topic, message, arguments);
-			Mail.sendMail(mail, colleagueTwo);
+			Mail outbox = MailBay.getMailClient();
+			MailEntry mail = outbox.new MailEntry(time, sender, trustedUserOne, topic, message, arguments);
+			outbox.sendMail(mail, trustedUserOne);
+			mail = outbox.new MailEntry(time, sender, trustedUserTwo, topic, message, arguments);
+			outbox.sendMail(mail, trustedUserTwo);
 			AuthenticatorBrowser.getInstance().markRequestedColleagues(UserSettings.UserName.get());
 			return true;
Index: trunk/src/org/expeditee/auth/AuthenticatorBrowser.java
===================================================================
--- trunk/src/org/expeditee/auth/AuthenticatorBrowser.java	(revision 1503)
+++ trunk/src/org/expeditee/auth/AuthenticatorBrowser.java	(revision 1504)
@@ -2,12 +2,9 @@
 
 import java.io.File;
-import java.io.FileFilter;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
-import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
-import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.security.KeyFactory;
@@ -22,20 +19,9 @@
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.X509EncodedKeySpec;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
 import java.util.Arrays;
 import java.util.Base64;
 import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
 import java.util.Scanner;
-import java.util.Set;
 import java.util.stream.Stream;
 
@@ -44,5 +30,4 @@
 
 import org.expeditee.actions.Actions;
-import org.expeditee.auth.mail.Mail;
 import org.expeditee.core.Dimension;
 import org.expeditee.core.Point;
@@ -67,5 +52,4 @@
 import org.expeditee.settings.UserSettings;
 import org.expeditee.settings.identity.secrets.KeyList;
-import org.expeditee.stats.Formatter;
 
 public final class AuthenticatorBrowser extends Browser implements CryptographyConstants {
@@ -195,122 +179,4 @@
 			}
 		}
-	}
-	
-	final void loadMailFromFile(Path dbFile) throws SQLException {
-		// Load in all mail.
-		Connection c = DriverManager.getConnection("jdbc:sqlite:" + dbFile.toAbsolutePath().toString());
-		String sql = "SELECT * FROM EXPMAIL";
-		PreparedStatement query = c.prepareStatement(sql);
-		ResultSet allMail = query.executeQuery();
-
-		// Construct all mail objects using content from database.
-		while(allMail.next()) {
-			String timestamp = allMail.getString("time");
-			String from = allMail.getString("snd");
-			String to = allMail.getString("rec");
-			String msg = allMail.getString("msg");
-			String msg2 = allMail.getString("msg2");
-			String[] opts = allMail.getString("opts").split(",");
-			opts[0] = opts[0].replace("[", "");
-			opts[opts.length - 1] = opts[opts.length - 1].replace("]", "");
-			String[] optsVal = allMail.getString("optsval").split(",");
-			optsVal[0] = optsVal[0].replace("[", "");
-			optsVal[optsVal.length - 1] = optsVal[optsVal.length - 1].replace("]", "");
-			
-			Map<String, String> options = new HashMap<String, String>();
-			for (int i = 0, o = 0; i < opts.length && o < optsVal.length; i++, o++) {
-				String key = opts[i].trim();
-				String val = optsVal[o].trim();
-				options.put(key, val);
-			}
-			
-			Mail.MailEntry mail = new Mail.MailEntry(timestamp, from, to, msg, msg2, options);
-			mail.deadDropSource = dbFile;
-			Mail.addEntry(mail);
-		}
-		
-		// Disconnect from database.
-		allMail.close();
-		query.close();
-		c.close();
-	}
-	
-	public final void loadMailDatabase() throws SQLException, FileNotFoundException, ParseException {
-		Path deadDropPath = Paths.get(FrameIO.DEAD_DROPS_PATH);
-		for (File connectionDir: deadDropPath.toFile().listFiles()) {
-			if (connectionDir.isDirectory()) {
-				Path deaddropforcontactPath = Paths.get(connectionDir.getAbsolutePath());
-				Path dbFile = deaddropforcontactPath.resolve(UserSettings.UserName.get() + ".db");
-				if (dbFile.toFile().exists()) {
-					loadMailFromFile(dbFile);
-				}
-				clearOldMailFromDatabase(deaddropforcontactPath);
-			}
-		}
-	}
-
-	public final void updateLastReadMailTime(Path deaddropforcontactPath) {
-		Path timestamp = deaddropforcontactPath.resolve(UserSettings.UserName.get() + ".last-accessed");
-		try(FileWriter out = new FileWriter(timestamp.toFile())) {
-			out.write(Formatter.getDateTime() + System.getProperty("line.separator"));
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-	}
-	
-	private void clearOldMailFromDatabase(Path directory) throws FileNotFoundException, ParseException, SQLException {
-		File[] files = directory.toFile().listFiles(new FileFilter() {
-			@Override
-			public boolean accept(File file) {
-				return !file.getName().startsWith(UserSettings.UserName.get());
-			}
-		});
-		
-		File dbFile = null;
-		File lastAccessedFile = null;
-		for (File file: files) {
-			if (file.getName().endsWith(".db")) {
-				dbFile = file;
-			} else {
-				lastAccessedFile = file;
-			}
-		}
-		
-		if (dbFile == null || lastAccessedFile == null) {
-			return; // Not the end of the world if we cannot clear out old messages, these files may not be present yet if the others are recently new.
-		}
-		
-		SimpleDateFormat format = new SimpleDateFormat("ddMMMyyyy[HH:mm]");
-		Date timestamp = null;
-		try(Scanner in = new Scanner(lastAccessedFile)) {
-			timestamp = format.parse(in.nextLine());
-		} catch (ParseException e) {
-			return; // Not the end of the world if we cannot clear out old messages, the database might be empty.
-		}
-		
-		Connection c = DriverManager.getConnection("jdbc:sqlite:" + dbFile.getAbsolutePath());
-		String sql = "SELECT * FROM EXPMAIL";
-		PreparedStatement query = c.prepareStatement(sql);
-		ResultSet allMail = query.executeQuery();
-		Set<String> oldTimestamps = new HashSet<String>();
-		
-		while (allMail.next()) {
-			String time = allMail.getString("time");
-			Date messageTimestamp = format.parse(time);
-			if (timestamp.after(messageTimestamp)) {
-				oldTimestamps.add(time);
-			}
-		}
-		
-		if (oldTimestamps.isEmpty()) {
-			return;
-		}
-		
-		for(String oldTimestamp: oldTimestamps) {
-			System.out.println("Deleting message with timestamp: " + oldTimestamp);
-			sql = "DELETE FROM EXPMAIL WHERE time='" + oldTimestamp + "'";
-			query = c.prepareStatement(sql);
-			query.executeUpdate();
-		}		
 	}
 	 
Index: trunk/src/org/expeditee/auth/account/Authenticate.java
===================================================================
--- trunk/src/org/expeditee/auth/account/Authenticate.java	(revision 1503)
+++ trunk/src/org/expeditee/auth/account/Authenticate.java	(revision 1504)
@@ -1,15 +1,4 @@
 package org.expeditee.auth.account;
 
-import java.io.IOException;
-import java.security.InvalidKeyException;
-import java.security.KeyFactory;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.cert.CertificateException;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.sql.SQLException;
-import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Base64;
@@ -18,7 +7,4 @@
 import java.util.Map;
 
-import javax.crypto.BadPaddingException;
-import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.NoSuchPaddingException;
 import javax.crypto.SecretKey;
 
@@ -96,5 +82,5 @@
 			MessageBay.clear();
 			MessageBay.updateFramesetLocation();
-			MailBay.disconnect();
+			MailBay.reconnectToUser(UserSettings.UserName.get());
 			
 			// Parse the users profile to refresh settings.
@@ -108,26 +94,6 @@
 			AuthenticationResult res = AuthenticationResult.SuccessLogin;
 			
-			// Check mail and update last read files.
-			MailBay.clear();
-			try {
-				Text keyItem = KeyList.PrivateKey.get();
-				if (keyItem.getData() != null) {
-					// Check mail.
-					String keyEncoded = keyItem.getData().get(0);
-					byte[] keyBytes = Base64.getDecoder().decode(keyEncoded);
-					PrivateKey key = KeyFactory.getInstance(AsymmetricAlgorithm).generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
-					org.expeditee.auth.mail.Mail.checkMail(key);
-				} else {
-					res.additionalInfo.add("No private key present: your communication with other Expeditee users will be limited until this is resolved.");
-				}
-			} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | ClassNotFoundException
-					| SQLException | ParseException | IOException | InvalidKeyException | NoSuchPaddingException | 
-					IllegalBlockSizeException | BadPaddingException e) {
-				res.additionalInfo.add("An error occured while attempting to load in mail sent to you by other Expeditee users.  See the exception for more information.");
-				e.printStackTrace();
-			} catch (InvalidKeySpecException e) {
-				res.additionalInfo.add("Stored data cannot be used to create a private key.  See exception for more information.");
-				e.printStackTrace();
-			}
+			// Check mail for new user.		
+			MailBay.checkMail();
 			
 			Collection<Item> usernameFields = Actions.getByData(FrameIO.LoadFrame("multiuser1"), "txtUsername");
@@ -155,5 +121,4 @@
 		UserSettings.setupDefaultFolders();
 		MessageBay.updateFramesetLocation();
-		MailBay.disconnect();
 		
 		// Reset all of the settings.
Index: trunk/src/org/expeditee/auth/account/Create.java
===================================================================
--- trunk/src/org/expeditee/auth/account/Create.java	(revision 1503)
+++ trunk/src/org/expeditee/auth/account/Create.java	(revision 1504)
@@ -46,5 +46,4 @@
 import org.expeditee.setting.TextSetting;
 import org.expeditee.settings.UserSettings;
-import org.expeditee.settings.folders.FolderSettings;
 import org.expeditee.settings.identity.secrets.KeyList;
 
Index: trunk/src/org/expeditee/auth/account/Password.java
===================================================================
--- trunk/src/org/expeditee/auth/account/Password.java	(revision 1503)
+++ trunk/src/org/expeditee/auth/account/Password.java	(revision 1504)
@@ -13,4 +13,5 @@
 import java.util.Base64;
 import java.util.Collection;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -33,4 +34,5 @@
 import org.expeditee.auth.mail.Mail;
 import org.expeditee.auth.mail.Mail.MailEntry;
+import org.expeditee.auth.mail.gui.MailBay;
 import org.expeditee.auth.tags.AuthenticationTag;
 import org.expeditee.encryption.CryptographyConstants;
@@ -44,5 +46,4 @@
 import org.expeditee.settings.identity.passwordrecovery.Colleagues;
 import org.expeditee.settings.identity.secrets.KeyList;
-import org.expeditee.stats.Formatter;
 
 import com.codahale.shamir.Scheme;
@@ -113,18 +114,20 @@
 		
 		// Get colleagues to distribute messages too.
-		String[] colleagues = getPasswordColleaguesFromUsername(username);
+		String[] trustedUsers = getPasswordColleaguesFromUsername(username);
 		// 	Send secure message to colleague one
-		String colleagueOne = colleagues[0];
-		String time = Formatter.getDateTime();
+		String trustedUserOne = trustedUsers[0];
+		String time = Mail.FORMAT.format(new Date());
 		String topic = "Password Recovery for " + username;
 		String message = "Your colleague " + username + " would like you to help them recover access to their account.";
 		Map<String, String> options = new HashMap<String, String>();
 		options.put("Provide assistance", "AuthEmailPasswordShare " + username); 
-		MailEntry mail = new MailEntry(time, username, colleagueOne, topic, message, options);
-		Mail.sendOneOffMail(mail, colleagueOne, Base64.getDecoder().decode(intergalacticNumber));
+		Mail outbox = MailBay.getMailClient(username);
+		MailEntry mail = outbox.new MailEntry(time, username, trustedUserOne, topic, message, options);
+		SecretKeySpec key = new SecretKeySpec(Base64.getDecoder().decode(intergalacticNumber), SymmetricAlgorithm);
+		outbox.sendOneOffMail(mail, trustedUserOne, key);
 		
 		//	Send secure message to colleague two
-		String colleagueTwo = colleagues[1];
-		Mail.sendOneOffMail(mail, colleagueTwo, Base64.getDecoder().decode(intergalacticNumber));
+		String trustedUserTwo = trustedUsers[1];
+		outbox.sendOneOffMail(mail, trustedUserTwo, key);
 		
 		String nl = System.getProperty("line.separator");
@@ -136,8 +139,8 @@
 		try {
 			//	Send email with key to colleague one
-			String colleagueOneEmail = colleagues[2];
+			String colleagueOneEmail = trustedUsers[2];
 			sendEmail(colleagueOneEmail, sb);
 			//	Send email with key to colleague two
-			String colleagueTwoEmail = colleagues[3];
+			String colleagueTwoEmail = trustedUsers[3];
 			sendEmail(colleagueTwoEmail, sb);
 			
@@ -250,5 +253,5 @@
 	}
 
-	public static void setPWColleagues(String colleagueOne, String colleagueTwo) {
+	public static void setPWColleagues(String trustedUserOne, String trustedUserTwo) {
 		// Get needed text items.
 		Frame pwRecoveryFrame = FrameIO.LoadFrame(UserSettings.UserName.get() + AuthenticatorBrowser.PASSWORD_RECOVERY_FRAME);
@@ -261,9 +264,9 @@
 			Text text = it.next();
 			if (text.getText().toLowerCase().startsWith("user_one:")) {
-				text.setText("User_one: " + colleagueOne);
-				Colleagues.User_One.set(colleagueOne);
+				text.setText("User_one: " + trustedUserOne);
+				Colleagues.User_One.set(trustedUserOne);
 			} else if (text.getText().toLowerCase().startsWith("user_two:")) {
-				text.setText("User_two: " + colleagueTwo);
-				Colleagues.User_Two.set(colleagueTwo);
+				text.setText("User_two: " + trustedUserTwo);
+				Colleagues.User_Two.set(trustedUserTwo);
 			}
 		}
@@ -281,24 +284,25 @@
 		// Create shares
 		Map<Integer, byte[]> shares = scheme.split(keyBytes);
-		String colleagueOneShare = Base64.getEncoder().encodeToString(shares.get(1));
-		String colleagueTwoShare = Base64.getEncoder().encodeToString(shares.get(2));
+		String trustedUserOneShare = Base64.getEncoder().encodeToString(shares.get(1));
+		String trustedUserTwoShare = Base64.getEncoder().encodeToString(shares.get(2));
 		
 		// Distribute share zero to colleague one
-		String time = org.expeditee.stats.Formatter.getDateTime();
+		String time = Mail.FORMAT.format(new Date());
 		String sender = UserSettings.UserName.get();
 		String topic = "Please help me secure my Expeditee account.";
 		String message = "Run the below action to store a secret key that will help me recover access to my account should I ever loose it.";
 		Map<String, String> options = new HashMap<String, String>();
-		options.put("Store Secret Key for " + sender, "AuthAddSecretKey " + sender + "PersonalKeyShare " + colleagueOneShare);
-		MailEntry mail = new MailEntry(time, sender, colleagueOne, topic, message, options);
-		Mail.sendMail(mail, colleagueOne);
+		options.put("Store Secret Key for " + sender, "AuthAddSecretKey " + sender + "PersonalKeyShare " + trustedUserOneShare);
+		Mail outbox = MailBay.getMailClient();
+		MailEntry mail = outbox.new MailEntry(time, sender, trustedUserOne, topic, message, options);
+		outbox.sendMail(mail, trustedUserOne);
 		
 		// Distribute share one to colleague two
 		options = new HashMap<String, String>();
-		options.put("Store Secret Key for " + sender, "AuthAddSecretKey " + sender + "PersonalKeyShare " + colleagueTwoShare);
-		mail = new MailEntry(time, sender, colleagueTwo, topic, message, options);
-		Mail.sendMail(mail, colleagueTwo);
-		
-		MessageBay.displayMessage("You PW Colleagues have been set to " + colleagueOne + " and " + colleagueTwo + ".  "
+		options.put("Store Secret Key for " + sender, "AuthAddSecretKey " + sender + "PersonalKeyShare " + trustedUserTwoShare);
+		mail = outbox.new MailEntry(time, sender, trustedUserTwo, topic, message, options);
+		outbox.sendMail(mail, trustedUserTwo);
+		
+		MessageBay.displayMessage("You Trusted Users have been set to " + trustedUserOne + " and " + trustedUserTwo + ".  "
 				+ "They have been sent a Expeditee mail that they can use to store a share of your secret key.");
 	}
Index: trunk/src/org/expeditee/auth/mail/Mail.java
===================================================================
--- trunk/src/org/expeditee/auth/mail/Mail.java	(revision 1503)
+++ trunk/src/org/expeditee/auth/mail/Mail.java	(revision 1504)
@@ -3,8 +3,11 @@
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.io.FileWriter;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyFactory;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
@@ -13,7 +16,9 @@
 import java.security.cert.CertificateException;
 import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
+import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
@@ -28,4 +33,5 @@
 import java.util.Map;
 import java.util.Scanner;
+import java.util.function.Supplier;
 
 import javax.crypto.BadPaddingException;
@@ -34,56 +40,25 @@
 import javax.crypto.NoSuchPaddingException;
 import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
 
 import org.expeditee.auth.AuthenticatorBrowser;
-import org.expeditee.auth.mail.gui.MailBay;
 import org.expeditee.encryption.CryptographyConstants;
 import org.expeditee.gui.FrameIO;
-import org.expeditee.settings.UserSettings;
+import org.expeditee.gui.MessageBay;
+import org.expeditee.items.Text;
+import org.expeditee.settings.identity.secrets.KeyList;
 
 public class Mail implements CryptographyConstants {
+	private String user;
+	public static final SimpleDateFormat FORMAT = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
+
+	public Mail(String user) {
+		this.user = user.toLowerCase();
+	}
 	
-	private static List<MailEntry> messages = new ArrayList<MailEntry>();
-	
-	/**
-	 * Add a piece of mail, used during initialisation.
-	 */
-	public static void addEntry(MailEntry mail) {
-		messages.add(mail);
-	}
-	
-	public static void clear() {
-		messages.clear();
-	}
-	
-	public static void sendOneOffMail(MailEntry mail, String colleagueName, byte[] key) {
-		// Ensure dead drop area is set up.
-		Path databaseFileDirPath = ensureDeadDrops(colleagueName, mail.sender);
-		
-		// Ensure the database file exists.
-		Path databaseFilePath = ensureDatabaseFile(colleagueName, databaseFileDirPath);
-		
-		// Create secret key.
-		SecretKey secretKey = new SecretKeySpec(key, SymmetricAlgorithm);
-		
-		// Send message
-		sendMail(mail, secretKey, databaseFilePath);
-		
-		// Do it all again if demo mode is on (ensures sync without having to move db files)
-		if (Boolean.getBoolean("expeditee.demo-mode")) {
-			databaseFileDirPath = ensureDeadDropsDemoMode(colleagueName, mail.sender);
-			databaseFilePath = ensureDatabaseFile(colleagueName, databaseFileDirPath);			
-			sendMail(mail, secretKey, databaseFilePath);
-		}
-	}
-	
-	public static void sendMail(MailEntry mail, String colleagueName) {
-		// Ensure dead drop area is set up.
-		Path databaseFileDirPath = ensureDeadDrops(colleagueName);
-		
-		// Ensure the database file exists.
-		Path databaseFilePath = ensureDatabaseFile(colleagueName, databaseFileDirPath);
-		
-		// Obtain public key
+	public void sendMail(MailEntry mail, String colleagueName) {
+		// Get database file to place mail into
+		Path databaseFilePath = getDatabaseFilePath(colleagueName);
+
+		// Obtain colleagues public key
 		PublicKey publicKey = null;
 		try {
@@ -91,345 +66,435 @@
 		} catch (InvalidKeySpecException | NoSuchAlgorithmException | KeyStoreException | CertificateException
 				| ClassNotFoundException | IOException | SQLException e) {
-			System.err.println("Error while sending message.  Unable to obtain public key for colleague " +  
-				colleagueName + ".  Exception message: " + e.getMessage());
+			System.err.println("Error while sending message.  Unable to obtain public key for colleague "
+					+ colleagueName + ".  Exception message: " + e.getMessage());
 			return;
 		}
-		
+
 		// Check we got public key
 		if (publicKey == null) {
-			System.err.println("Error while sending message.  Unable to obtain public key for colleague.  Have you exchanged contact details?");
+			System.err.println("Error while sending message.  " + "Unable to obtain public key for colleague.  "
+					+ "Have you exchanged contact details?");
 			return;
 		}
+
+		// Send message
+		MailEntry encryptedMailEntryForSending = mail.encryptMailEntry(publicKey, () -> {
+			try {
+				return Cipher.getInstance(AsymmetricAlgorithm + AsymmetricAlgorithmParameters);
+			} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+				e.printStackTrace();
+				return null;
+			}
+		}, "");
+		encryptedMailEntryForSending.writeToMailDatabase(databaseFilePath);
+
+		// Do it all again if demo mode is on (ensures sync without having to move db
+		// files)
+		if (Boolean.getBoolean("expeditee.demo-mode")) {
+			databaseFilePath = getDatabaseFilePath(colleagueName, true);
+			encryptedMailEntryForSending.writeToMailDatabase(databaseFilePath);
+		}
+	}
+
+	public void sendOneOffMail(MailEntry mail, String colleagueName, SecretKey key) {
+		// Get database file to place mail into
+		Path databaseFilePath = getDatabaseFilePath(colleagueName);
+
+		// Send message
+		MailEntry encryptedMailEntryForSending = mail.encryptMailEntry(key, () -> {
+			try {
+				return Cipher.getInstance(SymmetricAlgorithm + SymmetricAlgorithmParameters);
+			} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+				e.printStackTrace();
+				return null;
+			}
+		}, MailEntry.SINGLE_USE_SENDER_TAG);
+		encryptedMailEntryForSending.writeToMailDatabase(databaseFilePath);
+
+		// Do it all again if demo mode is on (ensures sync without having to move db
+		// files)
+		if (Boolean.getBoolean("expeditee.demo-mode")) {
+			databaseFilePath = getDatabaseFilePath(colleagueName, true);
+			encryptedMailEntryForSending.writeToMailDatabase(databaseFilePath);
+		}
+	}
+
+	public List<MailEntry> checkMail() {
+		PrivateKey key = getPrivateKey();
+		List<Path> databasePaths = getDatabaseInboxFiles();
+		List<MailEntry> receivedMailEncrypted = loadMailFromDatabases(databasePaths);
+		List<MailEntry> receivedMail = decryptMailEntries(receivedMailEncrypted, key);
+		// TODO: delete processed messages from database files
+		touchLastAccessedFiles(databasePaths);
+		return receivedMail;
+	}
+
+	public class MailEntry {
+		private static final String SINGLE_USE_SENDER_TAG = "=";
+		private String timestamp;
+		private String sender;
+		private String receiver;
+		private String subject;
+		private String message;
+		private Map<String, String> options;
+		private Path source;
+
+		public MailEntry(String timestamp, String sender, String receiver, String subject, String message,
+				Map<String, String> options) {
+			this.timestamp = timestamp;
+			this.sender = sender;
+			this.receiver = receiver;
+			this.subject = subject;
+			this.message = message;
+			this.options = options;
+		}
+
+		//@formatter:off
+		public String getTimestamp() { return timestamp; }
+		public String getSender() { return sender; }
+		public String getReceiver() { return receiver; }
+		public String getSubject() { return subject; }
+		public String getMessage() { return message; }
+		public Map<String, String> getOptionsTextActionMap() { return options; }
+		public Path getDatabaseSource() { return source; }
+		public void setDatabaseSource(Path source) { this.source = source; }
+		public boolean isSingleUseEncryption() {
+			return sender.startsWith(MailEntry.SINGLE_USE_SENDER_TAG);
+		}
+		//@formatter:on
+
+		private MailEntry encryptMailEntry(Key key, Supplier<Cipher> generateCipher, String markSender) {
+			if (markSender == null)
+				markSender = "";
+			try {
+				// Encrypt sender, receiver, subject and message
+				Cipher cipher = generateCipher.get();
+				cipher.init(Cipher.ENCRYPT_MODE, key);
+				String sender = markSender + Base64.getEncoder().encodeToString(cipher.doFinal(getSender().toLowerCase().getBytes()));
+				cipher.init(Cipher.ENCRYPT_MODE, key);
+				String receiver = Base64.getEncoder().encodeToString(cipher.doFinal(getReceiver().getBytes()));
+				cipher.init(Cipher.ENCRYPT_MODE, key);
+				String subject = Base64.getEncoder().encodeToString(cipher.doFinal(getSubject().getBytes()));
+				cipher.init(Cipher.ENCRYPT_MODE, key);
+				String message = Base64.getEncoder().encodeToString(cipher.doFinal(getMessage().getBytes()));
+
+				// Encrypt reply options to be provided to receiver
+				Map<String, String> optionsTextActionMap = new HashMap<String, String>();
+				Map<String, String> toEncOptionsTextActionMap = getOptionsTextActionMap();
+				for (String text : toEncOptionsTextActionMap.keySet()) {
+					cipher.init(Cipher.ENCRYPT_MODE, key);
+					String textEncrypted = Base64.getEncoder().encodeToString(cipher.doFinal(text.getBytes()));
+					cipher.init(Cipher.ENCRYPT_MODE, key);
+					String toEncAction = toEncOptionsTextActionMap.get(text);
+					String actionEncrypted = Base64.getEncoder().encodeToString(cipher.doFinal(toEncAction.getBytes()));
+					optionsTextActionMap.put(textEncrypted, actionEncrypted);
+				}
+
+				return new MailEntry(getTimestamp(), sender, receiver, subject, message, optionsTextActionMap);
+			} catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
+				e.printStackTrace();
+				return null;
+			}
+		}
+
+		private void writeToMailDatabase(Path databaseFile) {
+			try {
+				Connection c = DriverManager.getConnection("jdbc:sqlite:" + databaseFile);
+				String sql = "INSERT INTO EXPMAIL (TIME,SND,REC,SUB,MSG,OPTS,OPTSVAL) VALUES (?, ?, ?, ?, ?, ?, ?);";
+				PreparedStatement statement = c.prepareStatement(sql);
+				statement.setString(1, getTimestamp());
+				statement.setString(2, getSender());
+				statement.setString(3, getReceiver());
+				statement.setString(4, getSubject());
+				statement.setString(5, message);
+				String opts = Arrays.toString(getOptionsTextActionMap().keySet().toArray());
+				statement.setString(6, opts);
+				String optsVal = Arrays.toString(getOptionsTextActionMap().values().toArray());
+				statement.setString(7, optsVal);
+				statement.execute();
+				statement.close();
+			} catch (SQLException e) {
+				e.printStackTrace();
+			}
+		}
+
+		private MailEntry decryptMailEntry(Key key, Supplier<Cipher> generateCipher, String senderMarkFilter) {
+			Cipher cipher = generateCipher.get();
+			try {
+				// Confirm this is a message is intended for this recipient
+				cipher.init(Cipher.DECRYPT_MODE, key);
+				byte[] receiverBytes = Base64.getDecoder().decode(getReceiver());
+				String receiver = new String(cipher.doFinal(receiverBytes));
+				if (!receiver.toLowerCase().equals(user)) {
+					return null;
+				}
+
+				// Decrypt remainder of message
+				cipher.init(Cipher.DECRYPT_MODE, key);
+				byte[] senderBytes = Base64.getDecoder().decode(getSender());
+				String sender = new String(cipher.doFinal(senderBytes));
+				cipher.init(Cipher.DECRYPT_MODE, key);
+				byte[] subjectBytes = Base64.getDecoder().decode(getSubject());
+				String subject = new String(cipher.doFinal(subjectBytes));
+
+				cipher.init(Cipher.DECRYPT_MODE, key);
+				byte[] messageBytes = Base64.getDecoder().decode(getMessage());
+				String message = new String(cipher.doFinal(messageBytes));
+
+				Map<String, String> options = new HashMap<String, String>();
+				for (String text : getOptionsTextActionMap().keySet()) {
+					cipher.init(Cipher.DECRYPT_MODE, key);
+					byte[] textBytes = Base64.getDecoder().decode(text);
+					String k = new String(cipher.doFinal(textBytes));
+					cipher.init(Cipher.DECRYPT_MODE, key);
+					byte[] actionBytes = Base64.getDecoder().decode(getOptionsTextActionMap().get(text));
+					String v = new String(cipher.doFinal(actionBytes));
+					options.put(k, v);
+				}
+
+				return new MailEntry(getTimestamp(), sender, receiver, subject, message, options);
+			} catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException e) {
+				e.printStackTrace();
+				return null;
+			}
+		}
+
+		public String toString() {
+			StringBuilder sb = new StringBuilder("MailEntry { ");
+			
+			sb.append("[timestamp: " + getTimestamp() + "], ");
+			sb.append("[sender: " + getSender() + "], ");
+			sb.append("[receiver: " + getReceiver() + "], ");
+			sb.append("[subject: " + getSubject() + "], ");
+			sb.append("[message: " + getMessage() + "], ");
+			
+			sb.append(" }");
+			return sb.toString();
+		}
+	}
+
+	private Path getDatabaseFilePath(String colleagueName) {
+		return getDatabaseFilePath(colleagueName, false);
+	}
+
+	private Path getDatabaseFilePath(String colleagueName, boolean demoMode) {
+		String deadDropsPath = Paths.get(FrameIO.PARENT_FOLDER).resolve("resources-" + user).resolve("deaddrops").toAbsolutePath().toString();//FrameIO.DEAD_DROPS_PATH;
 		
-		// Send message
-		sendMail(mail, publicKey, databaseFilePath);
+//		if (deadDropsPath == null) {
+//			deadDropsPath = Paths.get(FrameIO.PARENT_FOLDER).resolve("resources-" + colleagueName).resolve("deadrops").toAbsolutePath().toString();
+//		} else if (demoMode) {
+//			deadDropsPath = deadDropsPath.replace(user, colleagueName);
+//		}
 		
-		// Do it all again if demo mode is on (ensures sync without having to move db files)
-		if (Boolean.getBoolean("expeditee.demo-mode")) {
-			databaseFileDirPath = ensureDeadDropsDemoMode(colleagueName);
-			databaseFilePath = ensureDatabaseFile(colleagueName, databaseFileDirPath);			
-			sendMail(mail, publicKey, databaseFilePath);
-		}
-	}
-
-	private static Path ensureDatabaseFile(String colleagueName, Path databaseFileDirPath) {
-		Path databaseFilePath = databaseFileDirPath.resolve(colleagueName + ".db");
-		File databaseFile = databaseFilePath.toFile();
-		if (!databaseFile.exists()) {
-			databaseFileDirPath.toFile().mkdirs();
-			String sql = 
-					"CREATE TABLE EXPMAIL (" +
-					"TIME		TEXT					NOT NULL, " +
-					"SND		TEXT					NOT NULL, " + 
-					"REC		TEXT					NOT NULL, " + 
-					"MSG		TEXT					NOT NULL, " +
-					"MSG2		TEXT					NOT NULL, " + 
-					"OPTS		ARRAY					NOT NULL, " +
-					"OPTSVAL	ARRAY					NOT NULL)";
-			try {
-				Connection c = DriverManager.getConnection("jdbc:sqlite:" + databaseFile.getAbsolutePath());
-				Statement createTable = c.createStatement();
-				createTable.executeUpdate(sql);
-				createTable.close();
-				c.close();
+		if (demoMode) {
+			deadDropsPath = deadDropsPath.replace(user, colleagueName);
+		}
+
+		Path databaseFileDirectoryPath = Paths.get(deadDropsPath).resolve(user + "+" + colleagueName);
+		if (!databaseFileDirectoryPath.toFile().exists()) {
+			databaseFileDirectoryPath = Paths.get(deadDropsPath).resolve(colleagueName + "+" + user);
+		}
+		
+		if (!databaseFileDirectoryPath.toFile().exists()) {
+			databaseFileDirectoryPath.toFile().mkdirs();
+		}
+
+		Path databaseFilePath = databaseFileDirectoryPath.resolve(colleagueName + ".db");
+		if (!databaseFilePath.toFile().exists()) {
+			createMailDatabaseFile(databaseFilePath);
+		}
+		return databaseFilePath;
+	}
+
+	private void createMailDatabaseFile(Path databaseFilePath) {
+		databaseFilePath.getParent().toFile().mkdir();
+		//@formatter:off
+		String sql = 
+				"CREATE TABLE EXPMAIL (" +
+				"TIME		TEXT					NOT NULL, " +
+				"SND		TEXT					NOT NULL, " + 
+				"REC		TEXT					NOT NULL, " + 
+				"SUB		TEXT					NOT NULL, " +
+				"MSG		TEXT					NOT NULL, " + 
+				"OPTS		ARRAY					NOT NULL, " +
+				"OPTSVAL	ARRAY					NOT NULL)";
+		//@formatter:on
+		try (Connection c = DriverManager.getConnection("jdbc:sqlite:" + databaseFilePath.toAbsolutePath())) {
+			Statement createTable = c.createStatement();
+			createTable.executeUpdate(sql);
+			createTable.close();
+		} catch (SQLException e) {
+			System.err.println("Error while creating database file.");
+			e.printStackTrace();
+		}
+	}
+
+	private PrivateKey getPrivateKey() {
+		Text keyItem = KeyList.PrivateKey.get();
+		String noKeyMessage = "No private key present: your communication with other Expeditee users will be limited until this is resolved.";
+		if (keyItem.getData() != null) {
+			// Check mail.
+			String keyEncoded = keyItem.getData().get(0);
+			byte[] keyBytes = Base64.getDecoder().decode(keyEncoded);
+			try {
+				return KeyFactory.getInstance(AsymmetricAlgorithm).generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
+			} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
+				MessageBay.errorMessage(noKeyMessage);
+				MessageBay.errorMessage("See exception stack trace for more information.");
+				e.printStackTrace();
+				return null;
+			}
+		} else {
+			MessageBay.errorMessage(noKeyMessage);
+			return null;
+		}
+	}
+
+	private List<Path> getDatabaseInboxFiles() {
+		List<Path> databaseFiles = new ArrayList<Path>();
+		Path deadDropPath = Paths.get(FrameIO.DEAD_DROPS_PATH);
+		File deadDropDirectory = deadDropPath.toFile();
+		if (!deadDropDirectory.exists()) { return databaseFiles; }
+		for (File partnershipDirectoryCanditate : deadDropDirectory.listFiles()) {
+			if (partnershipDirectoryCanditate.isDirectory()) {
+				Path partnershipDirectory = Paths.get(partnershipDirectoryCanditate.getAbsolutePath());
+				Path dbFile = partnershipDirectory.resolve(user + ".db");
+				if (dbFile.toFile().exists()) {
+					databaseFiles.add(dbFile);
+				}
+			}
+		}
+		return databaseFiles;
+	}
+
+	private List<MailEntry> loadMailFromDatabases(List<Path> databasePaths) {
+		List<MailEntry> mail = new ArrayList<MailEntry>();
+
+		for (Path dbPath : databasePaths) {
+			try {
+				mail.addAll(loadMailFromDatabase(dbPath));
 			} catch (SQLException e) {
-				System.err.println("Error while creating database file.");
-				e.printStackTrace();
-			}
-		}
-		return databaseFilePath;
-	}
-
-	private static Path ensureDeadDrops(String colleagueName) {
-		String me = UserSettings.UserName.get().toLowerCase();
-		String them = colleagueName.toLowerCase();
-		Path databaseFileDirPath = Paths.get(FrameIO.DEAD_DROPS_PATH).resolve(me + "+" + them);
-		if (!databaseFileDirPath.toFile().exists()) {
-			databaseFileDirPath = Paths.get(FrameIO.DEAD_DROPS_PATH).resolve(them + "+" + me);
-		}
-		return databaseFileDirPath;
-	}
-	
-	private static Path ensureDeadDropsDemoMode(String colleagueName) {
-		String me = UserSettings.UserName.get().toLowerCase();
-		String them = colleagueName.toLowerCase();
-		String demoModeDeadDropsPath = FrameIO.DEAD_DROPS_PATH.replace(me, them);
-		Path databaseFileDirPath = Paths.get(demoModeDeadDropsPath).resolve(me + "+" + them);
-		if (!databaseFileDirPath.toFile().exists()) {
-			databaseFileDirPath = Paths.get(demoModeDeadDropsPath).resolve(them + "+" + me);
-		}
-		return databaseFileDirPath;
-	}
-	
-	private static Path ensureDeadDrops(String colleagueName, String sender) {
-		String me = sender.toLowerCase();
-		String them = colleagueName.toLowerCase();
-		Path parent = Paths.get(FrameIO.PARENT_FOLDER).resolve("resources-" + sender).resolve("deaddrops");
-		Path databaseFileDirPath = parent.resolve(me + "+" + them);
-		if (!databaseFileDirPath.toFile().exists()) {
-			databaseFileDirPath = parent.resolve(them + "+" + me);
-		}
-		return databaseFileDirPath;
-	}
-	
-	private static Path ensureDeadDropsDemoMode(String colleagueName, String sender) {
-		String me = sender.toLowerCase();
-		String them = colleagueName.toLowerCase();
-		Path parent = Paths.get(FrameIO.PARENT_FOLDER).resolve("resources-" + them).resolve("deaddrops");
-		Path databaseFileDirPath = parent.resolve(me + "+" + them);
-		if (!databaseFileDirPath.toFile().exists()) {
-			databaseFileDirPath = parent.resolve(them + "+" + me);
-		}
-		return databaseFileDirPath;
-	}
-	
-	private static void sendMail(MailEntry mail, PublicKey key, Path databaseFile) {
-		try {
-			Cipher cipher = Cipher.getInstance(AsymmetricAlgorithm + AsymmetricAlgorithmParameters);
-			cipher.init(Cipher.ENCRYPT_MODE, key);
-			String sender = Base64.getEncoder().encodeToString(cipher.doFinal(mail.sender.getBytes()));
-			cipher.init(Cipher.ENCRYPT_MODE, key);
-			String rec = Base64.getEncoder().encodeToString(cipher.doFinal(mail.receiver.getBytes()));
-			cipher.init(Cipher.ENCRYPT_MODE, key);
-			String message = Base64.getEncoder().encodeToString(cipher.doFinal(mail.message.getBytes()));
-			cipher.init(Cipher.ENCRYPT_MODE, key);
-			String message2 = Base64.getEncoder().encodeToString(cipher.doFinal(mail.message2.getBytes()));
+				e.printStackTrace();
+			}
+		}
+
+		return mail;
+	}
+
+	private List<MailEntry> loadMailFromDatabase(Path dbPath) throws SQLException {
+		List<MailEntry> mail = new ArrayList<MailEntry>();
+
+		Connection c = DriverManager.getConnection("jdbc:sqlite:" + dbPath.toAbsolutePath());
+		String sql = "SELECT * FROM EXPMAIL";
+		PreparedStatement query = c.prepareStatement(sql);
+		ResultSet results = query.executeQuery();
+
+		while (results.next()) {
+			String timestamp = results.getString("TIME");
 			
-			Map<String, String> options = new HashMap<String, String>(); 
-			for (String label: mail.options.keySet()) {
-				cipher.init(Cipher.ENCRYPT_MODE, key);
-				String labelEncrypted = Base64.getEncoder().encodeToString(cipher.doFinal(label.getBytes()));
-				cipher.init(Cipher.ENCRYPT_MODE, key);
-				String actionNameEncrypted = Base64.getEncoder().encodeToString(cipher.doFinal(mail.options.get(label).getBytes()));
-				options.put(labelEncrypted, actionNameEncrypted);
+			Path lastAccessedPath = dbPath.getParent().resolve(user + ".last-accessed");
+			try (Scanner in = new Scanner(lastAccessedPath.toFile())) {
+				Date lastAccessedTimestamp = FORMAT.parse(in.nextLine());
+				Date mailTimestamp = FORMAT.parse(timestamp);
+				if (mailTimestamp.before(lastAccessedTimestamp)) {
+					continue;
+				}
+			} catch (FileNotFoundException | ParseException e) {
+				// It may not have been created yet, then err on the safe side and add it in.
+				// If it fails to parse then we again err on the safe side.
+			} catch (RuntimeException e) {
+				e.printStackTrace();
+				continue;
 			}
 			
-			// write to mail database
-			writeToMailDatabase(mail, databaseFile, sender, rec, message, message2, options);			
-		} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | SQLException e) {
-			e.printStackTrace();
-		}
-	}
-	
-	private static void sendMail(MailEntry mail, SecretKey key, Path databaseFile) {
-		try {
-			//	Encrypt message.
-			Cipher cipher = Cipher.getInstance(SymmetricAlgorithm + SymmetricAlgorithmParameters);
-			cipher.init(Cipher.ENCRYPT_MODE, key);
-			String sender = "=" + Base64.getEncoder().encodeToString(cipher.doFinal(mail.sender.getBytes()));
-			cipher.init(Cipher.ENCRYPT_MODE, key);
-			String rec = Base64.getEncoder().encodeToString(cipher.doFinal(mail.receiver.getBytes()));
-			cipher.init(Cipher.ENCRYPT_MODE, key);
-			String message = Base64.getEncoder().encodeToString(cipher.doFinal(mail.message.getBytes()));
-			cipher.init(Cipher.ENCRYPT_MODE, key);
-			String message2 = Base64.getEncoder().encodeToString(cipher.doFinal(mail.message2.getBytes()));			
-			Map<String, String> options = new HashMap<String, String>(); 
-			for (String label: mail.options.keySet()) {
-				cipher.init(Cipher.ENCRYPT_MODE, key);
-				String labelEncrypted = Base64.getEncoder().encodeToString(cipher.doFinal(label.getBytes()));
-				cipher.init(Cipher.ENCRYPT_MODE, key);
-				String actionNameEncrypted = Base64.getEncoder().encodeToString(cipher.doFinal(mail.options.get(label).getBytes()));
-				options.put(labelEncrypted, actionNameEncrypted);
-			}
-			
-			//	Write to mail database.
-			writeToMailDatabase(mail, databaseFile, sender, rec, message, message2, options);
-		} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | SQLException e) {
-			e.printStackTrace();
-		}
-	}
-
-	private static void writeToMailDatabase(MailEntry mail, Path databaseFile, String sender, String rec,
-			String message, String message2, Map<String, String> options) throws SQLException {
-		Connection c = DriverManager.getConnection("jdbc:sqlite:" + databaseFile);
-		String sql = "INSERT INTO EXPMAIL (TIME,SND,REC,MSG,MSG2,OPTS,OPTSVAL) VALUES (?, ?, ?, ?, ?, ?, ?);";
-		PreparedStatement statement = c.prepareStatement(sql);
-		statement.setString(1, mail.timestamp);
-		statement.setString(2, sender);
-		statement.setString(3, rec);
-		statement.setString(4, message);
-		statement.setString(5, message2);
-		String opts = Arrays.toString(options.keySet().toArray());
-		statement.setString(6, opts);
-		String optsval = Arrays.toString(options.values().toArray());
-		statement.setString(7, optsval);
-		statement.execute();
-		statement.close();
+			String from = results.getString("SND");
+			String to = results.getString("REC");
+			String subject = results.getString("SUB");
+			String message = results.getString("MSG");
+			String[] opts = results.getString("opts").split(",");
+			opts[0] = opts[0].replace("[", "");
+			opts[opts.length - 1] = opts[opts.length - 1].replace("]", "");
+			String[] optsVal = results.getString("optsval").split(",");
+			optsVal[0] = optsVal[0].replace("[", "");
+			optsVal[optsVal.length - 1] = optsVal[optsVal.length - 1].replace("]", "");
+			Map<String, String> options = new HashMap<String, String>();
+			for (int i = 0; i < opts.length; i++) {
+				String key = opts[i].trim();
+				String val = optsVal[i].trim();
+				options.put(key, val);
+			}
+
+			MailEntry mailEntry = new MailEntry(timestamp, from, to, subject, message, options);
+			mailEntry.setDatabaseSource(dbPath);
+			mail.add(mailEntry);
+		}
+
+		results.close();
+		query.close();
 		c.close();
-		System.err.println("Message written to database: " + databaseFile.toString());
-	}
-		
-	/**
-	 * Gets the mail messages that the specified user is able to read.
-	 * The caller supplies their username and private key.  
-	 * If the private key can decrypt a message, then it was encrypted using the users public key, and is therefore for them.
-	 */
-	private static List<MailEntry> getEntries(String name, PrivateKey key) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException {
-		List<MailEntry> filtered = new ArrayList<MailEntry>();
-		
-		for (MailEntry mail: messages) {
-			if (isEncryptedOneOffMessage(mail)) {
-				getOneOffSecureMail(name, filtered, mail);
+
+		return mail;
+	}
+
+	private List<MailEntry> decryptMailEntries(List<MailEntry> encryptedMailMessages, PrivateKey key) {
+		List<MailEntry> mail = new ArrayList<MailEntry>();
+
+		for (MailEntry encMail : encryptedMailMessages) {
+			if (encMail.isSingleUseEncryption()) {
+				MailEntry oneOffSecureSubstitute = generateOneOffSecureSubstitute(encMail);
+				if (oneOffSecureSubstitute != null) {
+					mail.add(oneOffSecureSubstitute);
+				}
 			} else {
-				getStandardSecureMail(name, key, filtered, mail);
-			}
-		}
-		
-		return filtered;
-	}
-
-	private static void getOneOffSecureMail(String name, List<MailEntry> filtered, MailEntry mail) {
+				MailEntry decryptMailEntry = encMail.decryptMailEntry(key, () -> {
+					try {
+						return Cipher.getInstance(AsymmetricAlgorithm + AsymmetricAlgorithmParameters);
+					} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+						e.printStackTrace();
+						return null;
+					}
+				}, "");
+				if (decryptMailEntry != null) {
+					mail.add(decryptMailEntry);
+				}
+			}
+		}
+
+		return mail;
+	}
+
+	private void touchLastAccessedFiles(List<Path> databasePaths) {
+		for (Path databasePath : databasePaths) {
+			Path lastAccessedFilePath = databasePath.getParent().resolve(user + ".last-accessed");
+			try (FileWriter out = new FileWriter(lastAccessedFilePath.toFile())) {
+				out.write(Mail.FORMAT.format(new Date()) + System.getProperty("line.separator"));
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+	private MailEntry generateOneOffSecureSubstitute(MailEntry toWrap) {
 		StringBuilder sb = new StringBuilder();
 		String sep = ":::";
 		sb.append("Read one-off secure message." + sep);
-		sb.append(mail.timestamp + sep);
-		sb.append(mail.sender.substring(1) + sep);
-		sb.append(mail.receiver + sep);
-		sb.append(mail.message + sep);
-		sb.append(mail.message2 + sep);
-		for (String k: mail.options.keySet()) {
-			sb.append(k + sep + mail.options.get(k) + sep);
+		sb.append(toWrap.timestamp + sep);
+		sb.append(toWrap.sender.substring(1) + sep);
+		sb.append(toWrap.receiver + sep);
+		sb.append(toWrap.subject + sep);
+		sb.append(toWrap.message + sep);
+		for (String k: toWrap.options.keySet()) {
+			sb.append(k + sep + toWrap.options.get(k) + sep);
 		}
 		sb.reverse().delete(0, 3).reverse();
 		Map<String, String> options = new HashMap<String, String>();
 		options.put(sb.toString(), "AuthOneOffSecureMessage");
-		String currentTime = org.expeditee.stats.Formatter.getDateTime();
-		MailEntry mailOuter = new MailEntry(currentTime, "Unknown", name, "You have received a one-off secure message.", "Check your email for more details.", options);
-		
-		if (mail.deadDropSource != null) {
-			Path lastAccessedFile = mail.deadDropSource.getParent().resolve(name + ".last-accessed");
-			SimpleDateFormat format = new SimpleDateFormat("ddMMMyyyy[HH:mm]");
-			try (Scanner in = new Scanner(lastAccessedFile.toFile())) {
-				Date lastAccessedTimestamp = format.parse(in.nextLine());
-				Date mailTimestamp = format.parse(mail.timestamp);
-				if (mailTimestamp.after(lastAccessedTimestamp)) {
-					filtered.add(mailOuter);
-				}
-			} catch (FileNotFoundException e) {
-				// It may not have been created yet, then err on the safe side and add it in.
-				filtered.add(mailOuter);
-			} catch (ParseException e) {
-				// If we fail to parse, then err on the safe side and add it in.
-				filtered.add(mailOuter);
-			}
-		}
-	}
-
-	private static void getStandardSecureMail(String name, PrivateKey key, List<MailEntry> filtered, MailEntry mail)
-			throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, InvalidKeyException,
-			BadPaddingException {
-		// confirm this is a message for the requester of entries
-		String receiver = mail.receiver;
-		byte[] receiverBytes = Base64.getDecoder().decode(receiver);
-		String receiverDecrypted = null;
-		Cipher c = Cipher.getInstance(AsymmetricAlgorithm + AsymmetricAlgorithmParameters);
-		try {
-			c.init(Cipher.DECRYPT_MODE, key);
-			receiverDecrypted = new String(c.doFinal(receiverBytes));
-		} catch (InvalidKeyException | BadPaddingException e) {
-			return;
-		}
-		
-		// add an unencrypted version of the message to the return list
-		if (receiverDecrypted.compareToIgnoreCase(name) == 0) {
-			c.init(Cipher.DECRYPT_MODE, key);
-			String sender = new String(c.doFinal(Base64.getDecoder().decode(mail.sender)));
-			c.init(Cipher.DECRYPT_MODE, key);
-			String message = new String(c.doFinal(Base64.getDecoder().decode(mail.message)));
-			c.init(Cipher.DECRYPT_MODE, key);
-			String message2 = new String(c.doFinal(Base64.getDecoder().decode(mail.message2)));
-			
-			Map<String, String> options = new HashMap<String, String>();
-			for (String label: mail.options.keySet()) {
-				c.init(Cipher.DECRYPT_MODE, key);
-				String labelDecrypted = new String(c.doFinal(Base64.getDecoder().decode(label)));
-				c.init(Cipher.DECRYPT_MODE, key);
-				String actionNameDecrypted = new String(c.doFinal(Base64.getDecoder().decode(mail.options.get(label))));
-				options.put(labelDecrypted, actionNameDecrypted);
-			}
-			
-			Path lastAccessedFile = Paths.get(FrameIO.DEAD_DROPS_PATH).resolve(UserSettings.UserName.get() + "+" + sender).resolve(name + ".last-accessed");
-			if (!lastAccessedFile.toFile().exists()) {
-				lastAccessedFile = Paths.get(FrameIO.DEAD_DROPS_PATH).resolve(sender + "+" + UserSettings.UserName.get()).resolve(name + ".last-accessed");
-			}
-			SimpleDateFormat format = new SimpleDateFormat("ddMMMyyyy[HH:mm]");
-			MailEntry mailEntry = new MailEntry(mail.timestamp, sender, receiverDecrypted, message, message2, options);
-			try (Scanner in = new Scanner(lastAccessedFile.toFile())) {
-				Date lastAccessedTimestamp = format.parse(in.nextLine());
-				Date mailTimestamp = format.parse(mail.timestamp);
-				if (mailTimestamp.after(lastAccessedTimestamp)) {
-					filtered.add(mailEntry);
-				}
-			} catch (FileNotFoundException e) {
-				// It may not have been created yet, then err on the safe side and add it in.
-				filtered.add(mailEntry);
-			} catch (ParseException e) {
-				// If we fail to parse, then err on the safe side and add it in.
-				filtered.add(mailEntry);
-			}			
-			
-		}
-	}
-	
-	private static boolean isEncryptedOneOffMessage(MailEntry mail) {
-		return mail.sender.charAt(0) == '=';
-	}
-	
-	/**
-	 * Describes a piece of mail, either encrypted or decrypted.
-	 */
-	public static class MailEntry {
-		public String timestamp;
-		public String sender;
-		public String receiver;
-		public String message;
-		public String message2;
-		public Map<String, String> options;
-		public Path deadDropSource;
-		
-		public MailEntry(String timestamp, String sender, String rec, String message, String message2, Map<String, String> options) {
-			this.timestamp = timestamp;
-			this.sender = sender;
-			this.receiver = rec;
-			this.message = message;
-			this.message2 = message2;
-			this.options = options;
-		}
-	}
-
-	public static void checkMail(PrivateKey key) throws NoSuchAlgorithmException, NoSuchPaddingException,
-			IllegalBlockSizeException, BadPaddingException, InvalidKeyException, KeyStoreException,
-			FileNotFoundException, CertificateException, IOException, ClassNotFoundException, SQLException, ParseException {
-		MailBay.clear();
-		AuthenticatorBrowser.getInstance().loadMailDatabase();
-		List<MailEntry> mailForLoggingInUser = Mail.getEntries(UserSettings.UserName.get(), key);			
-		for (MailEntry mail: mailForLoggingInUser) {
-			MailBay.addMessage(mail.timestamp, mail.sender, mail.message, mail.message2, mail.options);
-		}
-		
-		// Update last read files.
-		Path deadDropPath = Paths.get(FrameIO.DEAD_DROPS_PATH);
-		for (File connectionDir: deadDropPath.toFile().listFiles()) {
-			if (connectionDir.isDirectory()) {
-				Path deaddropforcontactPath = Paths.get(connectionDir.getAbsolutePath());
-				AuthenticatorBrowser.getInstance().updateLastReadMailTime(deaddropforcontactPath);
-			}
-		}
-	}
-
-	public static void decryptOneOffSecureMessage(SecretKey key, List<String> data) {
-		byte[] topicBytes = Base64.getDecoder().decode(data.get(3));
-		String topic = new String(org.expeditee.encryption.Actions.DecryptSymmetric(topicBytes, key));
-		byte[] messageBytes = Base64.getDecoder().decode(data.get(4));
-		String message = new String(org.expeditee.encryption.Actions.DecryptSymmetric(messageBytes, key));
-		Map<String, String> options = new HashMap<String, String>();
-		for (int i = 5; i < data.size(); i+=2) {
-			byte[] optionKeyBytes = Base64.getDecoder().decode(data.get(i));
-			String k = new String(org.expeditee.encryption.Actions.DecryptSymmetric(optionKeyBytes, key));
-			byte[] optionValueBytes = Base64.getDecoder().decode(data.get(i + 1));
-			String v = new String(org.expeditee.encryption.Actions.DecryptSymmetric(optionValueBytes, key));
-			options.put(k, v);
-		}
-		MailBay.addMessage(data.get(0), "Single-use Secure (encrypted sender)", topic, message, options);
+		MailEntry mailOuter = new MailEntry(toWrap.timestamp, "Unknown", user, "You have received a one-off secure message.",
+				"Check your email for more details.", options);
+		return mailOuter;
+	}
+
+	public String getUser() {
+		return user;
 	}
 }
Index: trunk/src/org/expeditee/auth/mail/gui/MailBay.java
===================================================================
--- trunk/src/org/expeditee/auth/mail/gui/MailBay.java	(revision 1503)
+++ trunk/src/org/expeditee/auth/mail/gui/MailBay.java	(revision 1504)
@@ -4,10 +4,16 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.LinkedList;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Scanner;
 
+import javax.crypto.SecretKey;
+
 import org.expeditee.auth.AuthenticatorBrowser;
+import org.expeditee.auth.mail.Mail;
+import org.expeditee.auth.mail.Mail.MailEntry;
 import org.expeditee.core.Clip;
 import org.expeditee.core.Colour;
@@ -15,4 +21,5 @@
 import org.expeditee.core.Font;
 import org.expeditee.core.Image;
+import org.expeditee.encryption.Actions;
 import org.expeditee.gio.EcosystemManager;
 import org.expeditee.gio.GraphicsManager;
@@ -24,101 +31,148 @@
 import org.expeditee.items.Item;
 import org.expeditee.items.Text;
-import org.expeditee.settings.UserSettings;
 
 public class MailBay {
+	// Frameset name for mail
 	public static final String EXPEDITEE_MAIL_FRAMESET_NAME = "expediteemail";
-
-	/** The y position of the header to the mail bay. */
-	private static final int HEADER_OFFSET_Y = 15;
-	
-	/** Space between mail messages */
+	
+	// Font used for messages in the MailBay
+	private static final Font MESSAGE_FONT = new Font("Serif-Plain-16");
+	
+	// Bay preview area constants.
 	private static final int SPACING = 25;
-	
-	/** The (x,y) of the top message. */
-	private static final int MESSAGE_OFFSET_Y = 15 + SPACING;
+	private static final int OFFSET_Y = 15;
 	private static final int OFFSET_X = 20;
-
-	/** Buffer image of the mail window. */
-	private static Image _mailBuffer;
-	
-	/** The list of messages shown in the mail bay. */
-	private static List<Item> _previewMessages = new LinkedList<Item>();
-	private static List<Item> _messages = new LinkedList<Item>();
-	
-	/** Font used for mail messages. */
-	private static Font _messageFont = new Font("Serif-Plain-16");
-
-	/** Used to number messages. */
-	private static int _messageCount;
-	
-	/** Creator for creating the mail frames. */
-	private static FrameCreator _creator = null;
-	
-	/** The currently logged in user, consulted when deciding if a new FrameCreator is needed. */
-	private static String _forUser = UserSettings.UserName.get();
-	
-	/** The link that the preview pane displays pointing towards unprocessed messages. */
-	private static Text _mailLink = new Text(-2, "@Mail", Colour.BLACK, Colour.WHITE);
-
-	/** Wether the link has been drawn before. */
-	private static boolean isLinkInitialized = false;
-
-	/** The position of the mail link. */
-	private static int MAIL_LINK_Y_OFFSET = 100;
-	private static int MAIL_LINK_X = 50;
-	
-	/**
-	 * Obtain the two messages shown at the bottom of the screen as a preview to the entire collection of mail.
-	 * @return
-	 */
-	public static List<Item> getPreviewMessages() {
-		return _previewMessages;
-	}
-	
-	/**
-	 * An item is a 'preview mail item' if it is currently being previewed at the bottom of the screen.
-	 * @param i
-	 * @return
-	 */
-	public static boolean isPreviewMailItem(Item i) {
-		return _previewMessages.contains(i) || i == _mailLink;
-	}
-	
-	public static void disconnect() {
-		if (_forUser != UserSettings.UserName.get()) {
-			_creator = null;
-			_forUser = UserSettings.UserName.get();
-		}
-	}
-		
-	/**
-	 * Adds a message to the MailBay.
-	 * @param message The basic text of the message, what is displayed in the bay window down the bottom.
-	 * @options A map describing the buttons to be provided as reply options (Button Text, Action to run)
-	 * @return
-	 */
-	public synchronized static Text addMessage(String timestamp, String sender, String message, String message2, Map<String, String> options) {
+	
+	private static final int MAIL_LINK_X = 50;
+
+	private static List<Item> previewMessages = new ArrayList<Item>();
+	private static FrameCreator creator;
+	private static Mail mail;
+	private static Text mailLink;
+	private static Text checkMailAction;
+	
+	private static Image mailBufferImage;
+	
+	public static Mail getMailClient() {
+		return mail;
+	}
+	
+	public static Mail getMailClient(String user) {
+		boolean restore = mail != null;
+		String oldUser = restore ? mail.getUser() : null;
+		MailBay.reconnectToUser(user);
+		Mail ret = mail;
+		if (restore) {
+			MailBay.reconnectToUser(oldUser);
+		}
+		return ret;
+	}
+
+	public static List<Item> getPreviewMessages() { 
+		return previewMessages;
+	}
+	
+	public static boolean isPreviewMailItem(Item i) { 
+		return previewMessages.contains(i) || i == getMailLink() || i == checkMailAction;
+	}
+	
+	public static Image getImage(Clip clip, Dimension size) { 
+		// Can't get an image with an invalid size
+		if (size == null || size.width <= 0 || size.height <= 0) {
+			return null;
+		}
+		
+		// Update the buffer
+		updateBuffer(Item.DEFAULT_BACKGROUND, clip, size);
+		
+		// Return the image buffer
+		return mailBufferImage;
+	}
+	
+	public static Item getMailLink() { 
+		return mailLink;
+	}
+	
+	public static Item getCheckMailAction() {
+		return checkMailAction;
+	}
+	
+	public static void reconnectToUser(String user) {
+		mail = new Mail(user);
+		creator = new FrameCreator(EXPEDITEE_MAIL_FRAMESET_NAME, FrameIO.MAIL_PATH, 
+				EXPEDITEE_MAIL_FRAMESET_NAME, FrameCreator.ExistingFramesetOptions.AppendAfterLastItem,
+				false, AuthenticatorBrowser.PROFILEENCRYPTIONLABEL);
+		updateLink();
+	}
+	
+	public static void checkMail() {
 		// Invalidate whole area
 		DisplayController.invalidateArea(DisplayController.getMessageBayPaintArea());
-		
-		// Ensure frame creator
-		if (_creator == null || _forUser != UserSettings.UserName.get()) {
-			_forUser = UserSettings.UserName.get();
-			_creator = new FrameCreator(EXPEDITEE_MAIL_FRAMESET_NAME, FrameIO.MAIL_PATH, EXPEDITEE_MAIL_FRAMESET_NAME, FrameCreator.ExistingFramesetOptions.AppendAfterLastItem, false, AuthenticatorBrowser.PROFILEENCRYPTIONLABEL);
-		}
-				
-		// We have enough space for the header + 2 preview messages
-		if (_previewMessages.size() >= 2) {
-			_previewMessages.remove(0);
-			for (Item i : _previewMessages) {
-				i.setY(i.getY() - SPACING);
-			}
-		}
-				
-		// Add new message
-		Mail mail = new Mail(message, message2, options);
-		Text t = mail.getPreviewMessage(true);
-		_messages.add(t);
-		Text header = _creator.addText(timestamp + " (From: " + sender + ")", Colour.BLACK, null, null, false);
+		previewMessages.clear();
+		
+		// Get new mail since last time we checked for mail
+		List<MailEntry> newMail = mail.checkMail();
+		
+		// Place up to two previews
+		Map<String, Integer> countBySender = countBySender(newMail);
+		String[] senders = countBySender.keySet().toArray(new String[] {});	
+		for (int i = 0; i < senders.length && i < 3; i++) {
+			String sender = senders[i];
+			Text text = new Text("You have received " + countBySender.get(sender) + " new messages from " + sender);
+			text.setFont(MESSAGE_FONT);
+			text.setPosition(MAIL_LINK_X, OFFSET_Y + (SPACING * (i + 1)));
+			previewMessages.add(text);
+		}
+		
+		// Add new mail to creator
+		for (MailEntry mail: newMail) {
+			String timestamp = mail.getTimestamp();
+			String sender = mail.getSender();
+			generateMailHeader(timestamp, sender);
+			creator.addText("Subject: " + mail.getSubject(), Colour.BLACK, null, null, false).setFont(MESSAGE_FONT);
+			creator.addText(mail.getMessage(), Colour.BLACK, null, null, false).setFont(MESSAGE_FONT);
+			Map<String, String> optionsTextActionMap = mail.getOptionsTextActionMap();
+			String[] optionsTextActionMapKeyset = optionsTextActionMap.keySet().toArray(new String[] {});
+			for (int i = 0; i < optionsTextActionMapKeyset.length; i++) {
+				String text = optionsTextActionMapKeyset[i];
+				String[] split = text.split(":::");
+				String action = optionsTextActionMap.get(text);
+				Text t = new Text(split[0]);
+				for (int o = 1; o < split.length; o++) {
+					t.addToData(split[o]);
+				}
+				int y = OFFSET_Y + (previewMessages.size() + i) * SPACING;
+				t.setPosition(OFFSET_X, y);
+				t.setColor(Colour.BLUE);
+				t.setFont(MESSAGE_FONT);
+				t.setAction(action);
+				creator.addItem(t, false);
+			}
+		}
+
+		DisplayController.requestRefresh(true);
+	}
+		
+	public static void decryptOneOffSecureMessage(SecretKey key, List<String> data) {
+		byte[] subjectBytes = Base64.getDecoder().decode(data.get(3));
+		String subject = new String(Actions.DecryptSymmetric(subjectBytes, key));
+		byte[] messageBytes = Base64.getDecoder().decode(data.get(4));
+		String message = new String(Actions.DecryptSymmetric(messageBytes, key));
+		
+		creator.addText(data.get(0) + " (Single-use encrypted message)", Colour.BLACK, null, null, false);
+		creator.addText(subject, Colour.BLACK, null, null, false).setFont(MESSAGE_FONT);
+		creator.addText(message, Colour.BLACK, null, null, false).setFont(MESSAGE_FONT);
+		
+		for (int i = 5; i < data.size(); i += 2) {
+			byte[] optionKeyBytes = Base64.getDecoder().decode(data.get(i));
+			String k = new String(org.expeditee.encryption.Actions.DecryptSymmetric(optionKeyBytes, key));
+			byte[] optionValueBytes = Base64.getDecoder().decode(data.get(i + 1));
+			String v = new String(org.expeditee.encryption.Actions.DecryptSymmetric(optionValueBytes, key));
+			creator.addText(k, Colour.BLACK, null, v, false).setFont(MESSAGE_FONT);
+		}
+	}
+
+	private static void generateMailHeader(String timestamp, String sender) {
+		Text header = creator.addText(timestamp + " (From: " + sender + ")", Colour.BLACK, null, null, false);
 		Path credentialsFilePath = Paths.get(FrameIO.CONTACTS_PATH).resolve(sender + "-credentials").resolve("credentials.inf");
 		if (credentialsFilePath.toFile().exists()) {
@@ -131,59 +185,10 @@
 			}
 		}
-		for (Text line: mail.getMessage()) {
-			_creator.addItem(line.copy(), false);
-		}
-		t.setLink(_creator.getCurrentFrame().getName());
-		_previewMessages.add(t);
-		_creator.addSpace(SPACING);
-		_creator.save();
-		
-		// Make sure the link points to the latest frame
-		_mailLink.setLink(_creator.getCurrent());
-		
-		DisplayController.requestRefresh(true);
-		
-		return t;
-	}
-
-	/**
-	 * Obtains the image item that is drawn to display the mail bay.
-	 * @param clip
-	 * @param size
-	 * @return
-	 */
-	public static Image getImage(Clip clip, Dimension size) {
-		// Can't get an image with an invalid size
-		if (size == null || size.width <= 0 || size.height <= 0) {
-			return null;
-		}
-		
-		// Update the buffer
-		updateBuffer(Item.DEFAULT_BACKGROUND, clip, size);
-		
-		// Return the image buffer
-		return _mailBuffer;
-	}
-	
-	public static void clear() {
-		getPreviewMessages().clear();
-		_messageCount = 0;
-	}
-	
-	public static Item getMailLink() {
-		return _mailLink;
-	}
-	
-	public static void ensureLink() {
-		if (_mailLink.getLink() == null && FrameIO.canAccessFrame(MailBay.EXPEDITEE_MAIL_FRAMESET_NAME + 1)) {
-			_mailLink.setLink(MailBay.EXPEDITEE_MAIL_FRAMESET_NAME + 1);
-		}
-	}	
-	
-	/** Updates the image buffer to reflect the current state of the mail bay. */
+	}
+	
 	private synchronized static void updateBuffer(Colour background, Clip clip, Dimension size) {
 		// If the buffer doesn't exist or is the wrong size, recreate it
-		if (_mailBuffer == null || !_mailBuffer.getSize().equals(size)) {
-			_mailBuffer = Image.createImage(size, true);
+		if (mailBufferImage == null || !mailBufferImage.getSize().equals(size)) {
+			mailBufferImage = Image.createImage(size, true);
 			clip = null; // Need to recreate the entire image;
 			updateSize();
@@ -192,5 +197,5 @@
 		// Prepare graphics
 		GraphicsManager g = EcosystemManager.getGraphicsManager();
-		g.pushDrawingSurface(_mailBuffer);
+		g.pushDrawingSurface(mailBufferImage);
 		if (clip != null) {
 			g.pushClip(clip);
@@ -198,15 +203,15 @@
 		g.setAntialiasing(true);
 		g.clear(background);
-		g.setFont(_messageFont);
+		g.setFont(MESSAGE_FONT);
 		
 		// Paint header
-		FrameGraphics.PaintItem(getHeader(Colour.BLACK));
-		
-		// Paint the mail messages to the screen (preview)
-		for (Item message : _previewMessages) {
-			if (message != null) {
-				if (clip == null || clip.isNotClipped() || message.isInDrawingArea(clip.getBounds())) {
-					FrameGraphics.PaintItem(message);
-				}
+		FrameGraphics.PaintItem(getHeader());
+		
+		// Paint the mail messages to the bay
+		for (Item message: previewMessages) {
+			if (message == null) { continue; }
+			
+			if (clip == null || clip.isNotClipped() || message.isInDrawingArea(clip.getBounds())) {
+				FrameGraphics.PaintItem(message);
 			}
 		}
@@ -219,6 +224,11 @@
 		
 		// Paint the link to the mail frame
-		if (clip == null || clip.isNotClipped() || _mailLink.isInDrawingArea(clip.getBounds())) {
-			FrameGraphics.PaintItem(_mailLink);
+		if (clip == null || clip.isNotClipped() || mailLink.isInDrawingArea(clip.getBounds())) {
+			FrameGraphics.PaintItem(mailLink);
+		}
+		
+		// Paint the action item to check for new mail
+		if (clip == null || clip.isNotClipped() || checkMailAction.isInDrawingArea(clip.getBounds())) {
+			FrameGraphics.PaintItem(checkMailAction);
 		}
 		
@@ -226,7 +236,6 @@
 	}
 	
-	/** Syncs message bay size according to FrameGraphics max size. */
 	private static void updateSize() {
-		for (Item i : _previewMessages) {
+		for (Item i: previewMessages) {
 			if (i != null) {
 				i.setOffset(0, -DisplayController.getMessageBayPaintArea().getMinY());
@@ -234,98 +243,49 @@
 		}
 		
-		_mailLink.setOffset(0, -DisplayController.getMessageBayPaintArea().getMinY());
 		updateLink();
 	}
 	
 	private static void updateLink() {
-		if (!isLinkInitialized && DisplayController.getFramePaintArea() != null
-				&& DisplayController.getFramePaintAreaWidth() > 0) {
-			// set up 'Messages' link on the right hand side
-			_mailLink.setPosition(DisplayController.getMessageBayPaintArea().getWidth() - MAIL_LINK_Y_OFFSET,
-					MAIL_LINK_X);
-			_mailLink.setOffset(0, -DisplayController.getMessageBayPaintArea().getMinY());
-			isLinkInitialized = true;
-		} else {
-			_mailLink.setPosition(DisplayController.getMessageBayPaintArea().getWidth() - MAIL_LINK_Y_OFFSET,
-					MAIL_LINK_X);
-		}
-	}
-
-	private static Text getHeader(Colour fontColor) {
-		Text t = new Text("You have [" + _messages.size() + "] unprocessed messages waiting.");
-		if (_messages.size() >= 2) {
-			t.setText(t.getText() + "  Two latest below:");
-		}
-		t.setPosition(OFFSET_X, HEADER_OFFSET_Y);
-		t.setOffset(0, -DisplayController.getFramePaintAreaHeight());
-		t.setColor(fontColor);
-		t.setFont(_messageFont.clone());
-		return t;
-	}
-	
-	private static String getMessagePrefix() {
-		_messageCount++;
-		return "@" + _messageCount + ": ";
-	}
-	
-	private static class Mail {
-		private String message;
-		private Map<String, String> options;
-		private String message2;
-
-		private Mail(String message, String message2, Map<String, String> options) {
-			this.message = message;
-			this.message2 = message2;
-			this.options = options;
-		}
-		
-		private Text getPreviewMessage(boolean usePrefix) {
-			Text t = usePrefix ? new Text(getMessagePrefix() + message)	: new Text(message);
-			int y = MESSAGE_OFFSET_Y + _previewMessages.size() * SPACING;
-			t.setPosition(OFFSET_X, y);
-			t.setColor(Colour.BLACK);
-			t.setFont(_messageFont.clone());
-			return t;
-		}
-		
-		private Text getDetailLine() {
-			if (message2 == null || message2.isEmpty()) { 
-				return null;
-			}
-			Text t = new Text(message2);
-			int y = MESSAGE_OFFSET_Y + _previewMessages.size() * SPACING;
-			t.setPosition(OFFSET_X, y);
-			t.setColor(Colour.BLACK);
-			t.setFont(_messageFont.clone());
-			return t;
-		}
-		
-		private Text[] getMessage() {
-			List<Text> items = new LinkedList<Text>();
-			items.add(getPreviewMessage(false));
-			Text detail = getDetailLine();
-			if (detail != null) {
-				items.add(detail);
+		mailLink = new Text(-2, "See Mail", Colour.BLACK, Colour.WHITE);
+		mailLink.setFont(MESSAGE_FONT);
+		mailLink.setOffset(0, -DisplayController.getMessageBayPaintArea().getMinY());
+		mailLink.setAnchorRight(OFFSET_X);
+		mailLink.setAnchorTop(OFFSET_Y);
+		mailLink.setLink(creator.getCurrent());
+		
+		checkMailAction = new Text(-2, "Get New Mail", Colour.BLACK, Colour.WHITE);
+		checkMailAction.setFont(MESSAGE_FONT);
+		checkMailAction.setOffset(0, -DisplayController.getMessageBayPaintArea().getMinY());
+		checkMailAction.setAnchorRight(OFFSET_X);
+		checkMailAction.setAnchorTop(OFFSET_Y + SPACING);
+		checkMailAction.setAction("CheckForNewMail");
+	}
+
+	private static Text getHeader() {
+		Text header = new Text("You have [" + previewMessages.size() + "] new messages since last you check.");
+		header.setPosition(OFFSET_X, OFFSET_Y);
+		header.setOffset(0, -DisplayController.getFramePaintAreaHeight());
+		header.setFont(MESSAGE_FONT);
+		return header;
+	}
+
+	private static Map<String, Integer> countBySender(List<MailEntry> newMail) {
+		Map<String, Integer> bySenderCount = new HashMap<String, Integer>();
+		
+		for (MailEntry mail: newMail) {
+			String sender = mail.getSender();
+			if (mail.isSingleUseEncryption()) {
+				sender = "Encrypted Sender";
 			}
 			
-			int i = items.size();
-			for (String content: options.keySet()) {
-				String[] split = content.split(":::");
-				String action = options.get(content);
-				Text t = new Text(split[0]);
-				for (int o = 1; o < split.length; o++) {
-					t.addToData(split[o]);
-				}
-				int y = MESSAGE_OFFSET_Y + (_previewMessages.size() + i) * SPACING;
-				t.setPosition(OFFSET_X, y);
-				t.setColor(Colour.BLUE);
-				t.setFont(_messageFont.clone());
-				t.setAction(action);
-				items.add(t);
-				i++;
-			}
-			
-			return items.toArray(new Text[] {});
-		}
+			if (bySenderCount.containsKey(sender)) {
+				Integer newValue = bySenderCount.get(sender) + 1;
+				bySenderCount.put(sender, newValue);
+			} else {
+				bySenderCount.put(sender, 1);
+			}
+		}
+		
+		return bySenderCount;
 	}
 }
Index: trunk/src/org/expeditee/gui/FrameIO.java
===================================================================
--- trunk/src/org/expeditee/gui/FrameIO.java	(revision 1503)
+++ trunk/src/org/expeditee/gui/FrameIO.java	(revision 1504)
@@ -52,5 +52,4 @@
 import org.expeditee.agents.InvalidFramesetNameException;
 import org.expeditee.auth.AuthenticatorBrowser;
-import org.expeditee.auth.mail.gui.MailBay;
 import org.expeditee.encryption.io.EncryptedExpReader;
 import org.expeditee.encryption.io.EncryptedExpWriter;
Index: trunk/src/org/expeditee/gui/FrameUtils.java
===================================================================
--- trunk/src/org/expeditee/gui/FrameUtils.java	(revision 1503)
+++ trunk/src/org/expeditee/gui/FrameUtils.java	(revision 1504)
@@ -1286,8 +1286,10 @@
 
 			// check the link to the message/mail frame
-			Item linkItem = DisplayController.isMailMode() ? MailBay.getMailLink() : MessageBay.getMessageLink();
-			if (linkItem != null && linkItem.contains(new Point(x, y))) {
-				linkItem.setOverlayPermission(UserAppliedPermission.copy);
-				possibles.add(linkItem);
+			Item[] linkItems = DisplayController.isMailMode() ? new Item[] { MailBay.getMailLink(), MailBay.getCheckMailAction() } : new Item[] { MessageBay.getMessageLink() };
+			for (Item linkItem: linkItems) {
+				if (linkItem != null && linkItem.contains(new Point(x, y))) {
+					linkItem.setOverlayPermission(UserAppliedPermission.copy);
+					possibles.add(linkItem);
+				}
 			}
 
