Index: trunk/src/org/expeditee/auth/Mail.java
===================================================================
--- trunk/src/org/expeditee/auth/Mail.java	(revision 1320)
+++ trunk/src/org/expeditee/auth/Mail.java	(revision 1357)
@@ -33,4 +33,6 @@
 import javax.crypto.IllegalBlockSizeException;
 import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
 
 import org.expeditee.auth.gui.MailBay;
@@ -54,12 +56,47 @@
 	}
 	
+	public static void sendOneOffMail(MailEntry mail, String colleagueName, byte[] key) {
+		// Ensure dead drop area is set up.
+		Path databaseFileDirPath = ensureDeadDrops(colleagueName);
+		
+		// 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);
+	}
+	
 	public static void sendMail(MailEntry mail, String colleagueName) {
 		// Ensure dead drop area is set up.
-		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);
-		}
+		Path databaseFileDirPath = ensureDeadDrops(colleagueName);
+		
+		// Ensure the database file exists.
+		Path databaseFilePath = ensureDatabaseFile(colleagueName, databaseFileDirPath);
+		
+		// Obtain public key
+		PublicKey publicKey = null;
+		try {
+			publicKey = AuthenticatorBrowser.getInstance().getPublicKey(colleagueName);
+		} 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());
+			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?");
+			return;
+		}
+		
+		// Send message
+		sendMail(mail, publicKey, databaseFilePath);
+	}
+
+	private static Path ensureDatabaseFile(String colleagueName, Path databaseFileDirPath) {
 		Path databaseFilePath = databaseFileDirPath.resolve(colleagueName + ".db");
 		File databaseFile = databaseFilePath.toFile();
@@ -86,24 +123,15 @@
 			}
 		}
-		
-		// Obtain public key
-		PublicKey publicKey = null;
-		try {
-			publicKey = AuthenticatorBrowser.getInstance().getPublicKey(colleagueName);
-		} 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());
-			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?");
-			return;
-		}
-		
-		// Send message
-		sendMail(mail, publicKey, databaseFilePath);
+		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;
 	}
 	
@@ -111,8 +139,4 @@
 		try {
 			Cipher cipher = Cipher.getInstance(AsymmetricAlgorithm + AsymmetricAlgorithmParameters);
-			
-			// encrypt the necessary parts of the message
-			//cipher.init(Cipher.ENCRYPT_MODE, key);
-			//String time = Base64.getEncoder().encodeToString(cipher.doFinal(mail.timestamp.getBytes()));
 			cipher.init(Cipher.ENCRYPT_MODE, key);
 			String sender = Base64.getEncoder().encodeToString(cipher.doFinal(mail.sender.getBytes()));
@@ -134,19 +158,5 @@
 			
 			// write to mail database
-			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();
-			c.close();			
+			writeToMailDatabase(mail, databaseFile, sender, rec, message, message2, options);			
 		} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | SQLException e) {
 			e.printStackTrace();
@@ -154,4 +164,51 @@
 	}
 	
+	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();
+		c.close();
+	}
+		
 	/**
 	 * Gets the mail messages that the specified user is able to read.
@@ -230,4 +287,5 @@
 		public String message2;
 		public Map<String, String> options;
+		public MailEntry subEntry;
 		
 		public MailEntry(String timestamp, String sender, String rec, String message, String message2, Map<String, String> options) {
