final implementation

This commit is contained in:
2024-11-04 21:51:00 +05:30
commit e0dd0c850a
85 changed files with 2966 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
.classpath
/.metadata/
.project
/.settings/
/target/

157
pom.xml Normal file
View File

@@ -0,0 +1,157 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>secure_mailer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>secure_mailer</name>
<url>http://maven.apache.org</url>
<properties>
<configuration-mainClass>com.secure_mailer.backend.MainClass</configuration-mainClass>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<resources>
<resource>
<!-- Path to your resources folder -->
<directory>src/main/resources</directory>
<!-- Optional: Include only specific files -->
<includes>
<include>**/*.png</include> <!-- Only PNG files -->
<include>**/*.css</include> <!-- Only CSS files -->
<include>**/*.fxml</include>
<include>**/*.ttf</include>
<include>**/*.otf</include>
<include>**/*.default.address.map</include>
</includes>
<!-- Optional: Exclude specific files -->
<excludes>
<exclude>**/test/**</exclude> <!-- Exclude test resources, if any -->
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.5</version>
<executions>
<execution>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<mainClass>com.secure_mailer.App</mainClass> <!-- Replace with your main class -->
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version> <!-- or later -->
<configuration>
<source>17</source> <!-- Use 15 or higher, e.g., 17 if using Java 17 -->
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
</dependency>
<dependency>
<groupId>com.gluonhq</groupId>
<artifactId>gluonfx-maven-plugin</artifactId>
<version>1.0.24</version>
</dependency>
<!-- JavaFX dependencies (adjust for specific modules you need) -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>23</version> <!-- Adjust this version based on your setup -->
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>23</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>23</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>23</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-swing</artifactId>
<version>23</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<version>23</version>
</dependency>
<!-- JavaMail Dependency -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
<version>1.6.2</version> <!-- A stable version of JavaMail -->
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version> <!-- Ensures the implementation is included -->
</dependency>
<!-- javax.activation Dependency -->
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version> <!-- A stable version of Activation -->
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,19 @@
package com.secure_mailer;
import com.secure_mailer.backend.EmailManager;
import com.secure_mailer.frontend.ViewGenerator;
import javafx.application.Application;
import javafx.stage.Stage;
public class App extends Application {
public static void main(String... args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
EmailManager em = new EmailManager();
ViewGenerator.initialize(em);
}
}

View File

@@ -0,0 +1,18 @@
package com.secure_mailer.backend;
public class BaseController {
private String fxml;
private EmailManager emailManager;
protected String emailID;
public BaseController(String fxml, EmailManager emailManager) {
this.fxml = fxml;
this.emailManager = emailManager;
}
public String getEmailID() { return this.emailID; }
public String getFXML() { return fxml; }
public EmailManager getEmailManager() { return emailManager; }
}

View File

@@ -0,0 +1,37 @@
package com.secure_mailer.backend;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class DatabaseSetup {
private static final String DB_URL = "jdbc:h2:~/email_client_db"; // URL for H2 database
private static final String USER = "sa"; // Default user for H2
private static final String PASSWORD = ""; // Default password for H2
/**
* Sets up the database and creates the SecretCodes table if it does not exist.
*/
public static void setupDatabase() {
// Using try-with-resources to ensure resources are closed properly
try (Connection connection = DriverManager.getConnection(DB_URL, USER, PASSWORD);
Statement stmt = connection.createStatement()) {
// SQL statement to create the SecretCodes table if it doesn't exist
String createTable = "CREATE TABLE IF NOT EXISTS SecretCodes (" +
"email VARCHAR(255) PRIMARY KEY, " +
"secretCode VARCHAR(255) NOT NULL)";
stmt.execute(createTable); // Execute the create table statement
System.out.println("Database setup completed successfully.");
} catch (SQLException e) {
System.err.println("Database setup failed: " + e.getMessage());
}
}
public static void main(String[] args) {
setupDatabase(); // Call the setupDatabase method
}
}

View File

@@ -0,0 +1,52 @@
package com.secure_mailer.backend;
import java.util.ArrayList;
import java.util.Properties;
import javax.mail.Folder;
import javax.mail.Session;
import javax.mail.Store;
public class EmailAccount {
private String address;
private String password;
private Properties properties;
private Store store;
private Session session;
private ArrayList<Folder> folders = new ArrayList<Folder>();
public EmailAccount(String address, String password) {
this.address = address;
this.password = password;
properties = new Properties();
properties.put("incomingHost", "peachy.in.net");
properties.put("mail.store.protocol", "imaps");
properties.put("mail.transport.protocol", "smtps");
properties.put("mail.smtps.host", "peachy.in.net");
properties.put("mail.smtps.auth", "true");
properties.put("outgoingHost", "peachy.in.net");
//properties.put("mail.imap.host", "peachy.in.net"); // Replace with your IMAP server
properties.put("mail.imaps.port", "993"); // Common port for IMAP SSL
properties.put("mail.imaps.ssl.enable", "true");
properties.put("mail.imaps.auth", "true");
//properties.put("mail.smtp.host", "peachy.in.net"); // Replace with your SMTP server
properties.put("mail.smtps.port", "465"); // Common port for SMTP SSL; check with your server if different
properties.put("mail.smtps.auth", "true");
properties.put("mail.smtps.ssl.enable", "true");
//properties.put("mail.smtp.starttls.enable", "true"); // Optional if the server supports STARTTLS
}
public String getAddress() {return address;}
public String getPassword() {return password;}
public Properties getProperties() {return properties;}
public Store getStore() {return store;}
public Session getSession() {return session;}
public ArrayList<Folder> getFolders() {return folders;}
public void setProperties(Properties properties) {this.properties = properties;}
public void setStore(Store store) {this.store = store;}
public void setSession(Session session) {this.session = session;}
@Override public String toString() {return address;}
}

View File

@@ -0,0 +1,36 @@
package com.secure_mailer.backend;
import com.secure_mailer.backend.service.FetchFolderService;
import com.secure_mailer.backend.service.LoginService;
import com.secure_mailer.frontend.FolderTreeItem;
import com.secure_mailer.frontend.EmailMessage;
import com.secure_mailer.frontend.ViewGenerator;
public class EmailManager {
private static final String LOCATION_OF_DOWNLOADS = System.getProperty("user.home") + "/Downloads/";
private EmailAccount emailAccount;
private FolderTreeItem foldersRoot = new FolderTreeItem();
private FolderTreeItem selectedFolder;
private EmailMessage selectedMessage;
public void login(String account, String password) {
emailAccount = new EmailAccount(account, password);
new LoginService(emailAccount);
}
public void fetchFolders() {
FetchFolderService ffs = new FetchFolderService(emailAccount.getStore(), foldersRoot, emailAccount.getFolders());
ffs.setOnSucceeded(e -> ViewGenerator.showMainWindow(this));
ffs.start();
}
public static String getDownloadPath() { return LOCATION_OF_DOWNLOADS; }
public FolderTreeItem getFolderRoot() { return foldersRoot; }
public void setSelectedFolder(FolderTreeItem item) { selectedFolder = item; }
public void setSelectedMessage(EmailMessage emailMessage) { this.selectedMessage = emailMessage; }
public EmailMessage getSelectedMessage() { return selectedMessage; }
public FolderTreeItem getSelectedFolder() { return selectedFolder; }
public EmailAccount getEmailAccount() { return emailAccount; }
}

View File

@@ -0,0 +1,30 @@
package com.secure_mailer.backend;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class EmailSecretCode {
private final StringProperty email;
private final StringProperty secretCode;
public EmailSecretCode(String email, String secretCode) {
this.email = new SimpleStringProperty(email);
this.secretCode = new SimpleStringProperty(secretCode);
}
public String getEmail() {
return email.get();
}
public StringProperty emailProperty() {
return email;
}
public String getSecretCode() {
return secretCode.get();
}
public StringProperty secretCodeProperty() {
return secretCode;
}
}

View File

@@ -0,0 +1,31 @@
package com.secure_mailer.backend;
import javafx.fxml.FXML;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
public class LoginController extends BaseController{
@FXML private TextField emailField;
@FXML private PasswordField passwordField;
private EmailManager em;
public LoginController(EmailManager emailManager) {
super("/fxml/login.fxml", emailManager);
em = emailManager;
}
@FXML void loginAction() {
String email = emailField.getText();
String password = passwordField.getText();
saveEmailID(email);
em.login(email, password);
em.fetchFolders();
}
private void saveEmailID(String username) {
this.emailID = username;
}
}

View File

@@ -0,0 +1,96 @@
package com.secure_mailer.backend;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.sql.SQLException;
public class SecretCodeController {
@FXML private TextField emailField;
@FXML private TextField secretCodeField;
@FXML private TableView<EmailSecretCode> secretCodesTable;
@FXML private TableColumn<EmailSecretCode, String> emailColumn;
@FXML private TableColumn<EmailSecretCode, String> secretCodeColumn;
private ObservableList<EmailSecretCode> dataList;
public void initialize() {
dataList = FXCollections.observableArrayList();
secretCodesTable.setItems(dataList);
emailColumn.setCellValueFactory(cellData -> cellData.getValue().emailProperty());
secretCodeColumn.setCellValueFactory(cellData -> cellData.getValue().secretCodeProperty());
loadAllEntries();
}
@FXML
private void handleAdd() {
String email = emailField.getText();
String secretCode = secretCodeField.getText();
try {
SecretCodeDAO.addSecretCode(email, secretCode);
//dataList.add(new EmailSecretCode(email, secretCode));
clearFields();
} catch (SQLException e) {
showAlert("Error", "Could not add secret code.");
e.printStackTrace();
}
}
@FXML
private void handleUpdate() {
String email = emailField.getText();
String secretCode = secretCodeField.getText();
try {
SecretCodeDAO.updateSecretCode(email, secretCode);
//loadAllEntries();
clearFields();
} catch (SQLException e) {
showAlert("Error", "Could not update secret code.");
e.printStackTrace();
}
}
@FXML
private void handleDelete() {
String email = emailField.getText();
try {
SecretCodeDAO.deleteSecretCode(email);
//loadAllEntries();
clearFields();
} catch (SQLException e) {
showAlert("Error", "Could not delete secret code.");
e.printStackTrace();
}
}
@FXML
private void handleViewAll() {
loadAllEntries();
}
private void loadAllEntries() {
try {
dataList.clear();
for (EmailSecretCode entry : SecretCodeDAO.getAllEntries()) {
dataList.add(entry);
}
} catch (SQLException e) {
showAlert("Error", "Could not load entries.");
e.printStackTrace();
}
}
private void clearFields() {
emailField.clear();
secretCodeField.clear();
}
private void showAlert(String title, String message) {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle(title);
alert.setContentText(message);
alert.show();
}
}

View File

@@ -0,0 +1,73 @@
package com.secure_mailer.backend;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class SecretCodeDAO {
private static final String DB_URL = "jdbc:h2:~/email_client_db";
public static void addSecretCode(String email, String secretCode) throws SQLException {
String sql = "INSERT INTO SecretCodes (email, secretCode) VALUES (?, ?)";
try (Connection connection = DriverManager.getConnection(DB_URL, "sa", "");
PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setString(1, email);
stmt.setString(2, secretCode);
stmt.executeUpdate();
System.out.println("Secret code added.");
}
}
public static String getSecretCode(String email) throws SQLException {
String sql = "SELECT secretCode FROM SecretCodes WHERE email = ?";
try (Connection connection = DriverManager.getConnection(DB_URL, "sa", "");
PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setString(1, email);
ResultSet rs = stmt.executeQuery();
return rs.next() ? rs.getString("secretCode") : null;
}
}
public static void updateSecretCode(String email, String newSecretCode) throws SQLException {
String sql = "UPDATE SecretCodes SET secretCode = ? WHERE email = ?";
try (Connection connection = DriverManager.getConnection(DB_URL, "sa", "");
PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setString(1, newSecretCode);
stmt.setString(2, email);
stmt.executeUpdate();
System.out.println("Secret code updated.");
}
}
public static void deleteSecretCode(String email) throws SQLException {
String sql = "DELETE FROM SecretCodes WHERE email = ?";
try (Connection connection = DriverManager.getConnection(DB_URL, "sa", "");
PreparedStatement stmt = connection.prepareStatement(sql)) {
stmt.setString(1, email);
stmt.executeUpdate();
System.out.println("Secret code deleted.");
}
}
public static List<EmailSecretCode> getAllEntries() throws SQLException {
String sql = "SELECT * FROM SecretCodes";
List<EmailSecretCode> list = new ArrayList<>();
try (Connection connection = DriverManager.getConnection(DB_URL, "sa", "");
PreparedStatement stmt = connection.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
String email = rs.getString("email");
String secretCode = rs.getString("secretCode");
list.add(new EmailSecretCode(email, secretCode));
}
}
return list;
}
}

View File

@@ -0,0 +1,260 @@
package com.secure_mailer.backend;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.sql.SQLException;
import java.io.*;
import org.apache.commons.codec.binary.Base32;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.time.Instant;
import javafx.animation.PauseTransition;
import javafx.application.Platform;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.util.Duration;
public class ValidatorClient {
private Socket skt;
private String fromEmailId;
private String toEmailId;
private String emlHash;
private String timeStamp;
private String authCode;
public ValidatorClient() {
try {
skt = new Socket(InetAddress.getByName(null), 2000);
} catch (IOException e) {
// TODO Auto-generated catch block
Platform.runLater(() -> showAlert("Error", "Failed to connet with server."));
e.printStackTrace();
}
}
public ValidatorClient(String host, int port) {
try {
skt = new Socket(host, port);
} catch (IOException e) {
// TODO Auto-generated catch block
Platform.runLater(() -> showAlert("Error", "Failed to connet with server."));
e.printStackTrace();
}
}
public void closeValidatorClient() {
try {
skt.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void sendRecord(String fromEmailId, String toEmailId,
String emlHash ) throws SQLException {
this.fromEmailId = fromEmailId;
this.toEmailId = toEmailId;
this.emlHash = emlHash;
PrintStream ps = null;
try {
ps=new PrintStream(skt.getOutputStream());
String secretKey = SecretCodeDAO.getSecretCode(toEmailId);
long timeStep = Instant.now().getEpochSecond() / 30;
this.timeStamp = Long.toString(timeStep);
this.authCode = generateTOTP(secretKey, timeStep);
String[] data = new String[] {
this.fromEmailId,
this.toEmailId,
this.timeStamp,
this.authCode,
this.emlHash
};
System.out.println(this.fromEmailId);
System.out.println(this.toEmailId);
System.out.println(this.timeStamp);
System.out.println(this.authCode);
System.out.println(this.emlHash);
String packet = formPacket(data);
//Packet ready.
packet = String.valueOf(0) + packet;
//Send the packet.
ps.println(packet);
// If successful, show the alert on the JavaFX thread
Platform.runLater(() -> showAlert("Message Sent", "Your message has been sent successfully!"));
} catch(SQLException e) {
Platform.runLater(() -> showAlert("Error", "Failed to retrieve Secret key."));
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
Platform.runLater(() -> showAlert("Error", "Failed to send the message."));
e.printStackTrace();
}
}
public boolean bringCode(String fromEmailId, String toEmailId, String emlHash) {
this.fromEmailId = fromEmailId;
this.toEmailId = toEmailId;
this.emlHash = emlHash;
PrintStream ps = null;
BufferedReader br= null;
try {
ps=new PrintStream(skt.getOutputStream());
br=new BufferedReader(new InputStreamReader(skt.getInputStream()));
String[] data = new String[] {
this.emlHash
};
String packet = formPacket(data);
//Packet ready.
packet = String.valueOf(1) + packet;
//Send the size of packet.
//ps.println(packet.length());
//Send the packet.
ps.println(packet);
//Receive packet.
String msg = br.readLine();
//Parse the packet.
int i = 0;
String num = "";
for(; i < msg.length() ; i++ ) {
if( msg.charAt(i) != ':' )
num += Character.toString(msg.charAt(i));
else
break;
}
if( num.equals("420") ) {
Platform.runLater(() -> showAlert("Error", "Email record not found on server."));
return false;
}
this.timeStamp = num;
i = i + 1;
num = "";
for(; i < msg.length() ; i++ ) {
num += Character.toString(msg.charAt(i));
}
this.authCode = num;
String secretKey = SecretCodeDAO.getSecretCode(fromEmailId);
String totp = generateTOTP( secretKey, Long.parseLong(this.timeStamp));
return (totp == this.authCode);
} catch(SQLException e) {
Platform.runLater(() -> showAlert("Error", "Failed to retrieve Secret key."));
e.printStackTrace();
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
Platform.runLater(() -> showAlert("Error", "Failed to send communicate with server for authentication."));
e.printStackTrace();
return false;
}
}
private String formPacket(String[] data) {
int dataSize = data.length;
String packet = "";
int stringSize;
for(int i = 0 ; i < dataSize ; i++ ) {
stringSize = data[i].length();
packet += String.valueOf(stringSize) + ":" + data[i];
}
return packet;
}
public String generateTOTP(String secretKey, long timeStep) {
try {
Base32 base32 = new Base32();
byte[] bytes = base32.decode(secretKey);
SecretKeySpec secretKeySpec = new SecretKeySpec(bytes, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(secretKeySpec);
// Current Unix time / 30 (TOTP time step)
//long timeStep = Instant.now().getEpochSecond() / 30;
byte[] data = new byte[8];
for (int i = 7; timeStep > 0; i--) {
data[i] = (byte) (timeStep & 0xFF);
timeStep >>= 8;
}
byte[] hash = mac.doFinal(data);
int offset = hash[hash.length - 1] & 0xF;
int otp = ((hash[offset] & 0x7F) << 24 | (hash[offset + 1] & 0xFF) << 16 |
(hash[offset + 2] & 0xFF) << 8 | (hash[offset + 3] & 0xFF)) % 1_000_000;
return String.format("%06d", otp);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void showAlert(String title, String content) {
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle(title);
alert.setHeaderText(null);
alert.setContentText(content);
alert.show();
// Create a PauseTransition for 10 seconds
PauseTransition delay = new PauseTransition(Duration.seconds(10));
delay.setOnFinished(event -> alert.close()); // Close alert after 10 seconds
delay.play(); // Start the timer
}
}

View File

@@ -0,0 +1,106 @@
package com.secure_mailer.backend.service;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Transport;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import com.secure_mailer.backend.EmailAccount;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javax.crypto.SecretKey;
import java.util.Base64;
public class EmailSendingService extends Service<Void> {
private EmailAccount emailAccount;
private String subject;
private String recipient;
private String content;
private List<File> attachments = new ArrayList<File>();
//private SecretKey sKey;
class SecretKeyToString {
public static String secretKeyToString(SecretKey secretKey) {
// Convert SecretKey to byte array and then to Base64 string
byte[] encodedKey = secretKey.getEncoded();
return Base64.getEncoder().encodeToString(encodedKey);
}
}
public EmailSendingService(EmailAccount emailAccount, String subject, String recipient, String content, List<File> list
,SecretKey sKey
) {
this.emailAccount = emailAccount;
this.subject = subject;
this.recipient = recipient;
this.content = content;
this.attachments = list;
//this.sKey = sKey;
}
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
try {
MimeMessage mimeMessage = new MimeMessage(emailAccount.getSession());
mimeMessage.setFrom(emailAccount.getAddress());
mimeMessage.addRecipients(Message.RecipientType.TO, recipient);
mimeMessage.setSubject(subject);
//Embedding Secret Key.
// MimeBodyPart customDataPart = new MimeBodyPart();
// customDataPart.setText(SecretKeyToString.secretKeyToString(sKey), "UTF-8");
// customDataPart.setHeader("Secret-Key", "<custom-data>");
Multipart multipart = new MimeMultipart();
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(content, "text/html");
multipart.addBodyPart(messageBodyPart);
//Adding Secret Key to message.
//multipart.addBodyPart(customDataPart);
mimeMessage.setContent(multipart);
if(attachments.size()>0) {
for (File file: attachments) {
MimeBodyPart mimeBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(file.getAbsolutePath());
mimeBodyPart.setDataHandler(new DataHandler(source));
mimeBodyPart.setFileName(file.getName());
multipart.addBodyPart(mimeBodyPart);
}
}
Transport transport = emailAccount.getSession().getTransport();
transport.connect(
emailAccount.getProperties().getProperty("outgoingHost"),
emailAccount.getAddress(),
emailAccount.getPassword());
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
transport.close();
} catch(MessagingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} return null;
}
};
}
}

View File

@@ -0,0 +1,102 @@
package com.secure_mailer.backend.service;
import java.util.ArrayList;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Store;
import javax.mail.event.MessageCountEvent;
import javax.mail.event.MessageCountListener;
import com.secure_mailer.frontend.FolderTreeItem;
import com.secure_mailer.frontend.IconResolver;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
public class FetchFolderService extends Service<Void>{
private ArrayList<Folder> folderList;
private FolderTreeItem foldersRoot;
private Store store;
public FetchFolderService(Store store, FolderTreeItem foldersRoot, ArrayList<Folder> folderList) {
this.store = store;
this.foldersRoot = foldersRoot;
this.folderList = folderList;
}
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
fetchFolders();
return null;
}
};
}
private void fetchFolders() throws MessagingException {
Folder[] folders = store.getDefaultFolder().list();
handleFolders(folders, foldersRoot);
}
private void handleFolders(Folder[] folders, FolderTreeItem foldersRoot) throws MessagingException {
for(Folder folder: folders) {
folderList.add(folder);
FolderTreeItem folderTreeItem = new FolderTreeItem(folder);
folderTreeItem.setGraphic(IconResolver.getIcon(folder.getName()));
foldersRoot.getChildren().add(folderTreeItem);
foldersRoot.setExpanded(true);
fetchMessagesOnFolder(folderTreeItem);
addMessageListenerToFolder(folder, folderTreeItem);
if (folder.getType() == Folder.HOLDS_FOLDERS) {
Folder[] subFolders = folder.list();
handleFolders(subFolders, folderTreeItem);
}
}
}
private void addMessageListenerToFolder(Folder folder, FolderTreeItem folderTreeItem) {
folder.addMessageCountListener(new MessageCountListener() {
@Override
public void messagesAdded(MessageCountEvent e) {
for(int i = 0; i < e.getMessages().length; i++) {
try {
Message message = folder.getMessage(folder.getMessageCount() - i);
folderTreeItem.addEmailToTop(message);
} catch (MessagingException ex) {
ex.printStackTrace();
}
}
}
@Override
public void messagesRemoved(MessageCountEvent e) {}
});
}
private void fetchMessagesOnFolder(FolderTreeItem folderTreeItem) {
Folder folder = folderTreeItem.getFolder();
Service<Void> fetchMessagesService = new Service<Void>() {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
if(folder.getType() != Folder.HOLDS_FOLDERS) {
folder.open(Folder.READ_WRITE);
int folderSize = folder.getMessageCount();
for(int i = folderSize; i > 0; i--) {
folderTreeItem.addEmail(folder.getMessage(i));
}
}
return null;
}
};
}
};
fetchMessagesService.start();
}
}

View File

@@ -0,0 +1,44 @@
package com.secure_mailer.backend.service;
import javax.mail.Authenticator;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;
import com.secure_mailer.backend.EmailAccount;
public class LoginService {
private EmailAccount emailAccount;
public LoginService(EmailAccount emailAccount) {
this.emailAccount = emailAccount;
login();
}
private void login() {
Authenticator authenticator = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(emailAccount.getAddress(), emailAccount.getPassword());
}
};
Session session = Session.getInstance(emailAccount.getProperties(), authenticator);
emailAccount.setSession(session);
try {
Store store = session.getStore("imaps");
store.connect(emailAccount.getProperties().getProperty("incomingHost"),
emailAccount.getAddress(),
emailAccount.getPassword());
emailAccount.setStore(store);
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,165 @@
package com.secure_mailer.backend.service;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.internet.MimeBodyPart;
import com.secure_mailer.frontend.EmailMessage;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
public class MessageRendererService extends Service<Object>{
private EmailMessage emailMessage;
private StringBuffer stringBuffer;
// private boolean isAuthenticated;
public MessageRendererService(StringBuffer stringBuffer) {
this.stringBuffer = stringBuffer;
// this.isAuthenticated = false;
}
public MessageRendererService(EmailMessage email) {
this.emailMessage = email;
this.stringBuffer = new StringBuffer();
// this.isAuthenticated = false;
}
@Override
protected Task<Object> createTask() {
try { loadMessage(); }
catch (Exception e) { e.printStackTrace(); }
return new Task<Object>() {
@Override
protected Object call() throws Exception { return null; }
};
}
private void loadMessage() throws MessagingException, IOException {
if (emailMessage.getMessage().isExpunged()) {this.cancel();}
stringBuffer.setLength(0);
Message message = emailMessage.getMessage();
String contentType = message.getContentType();
if(isSimpleType(contentType)){
if( emailMessage.getIsAuthenticated() )
stringBuffer.append(message.getContent().toString());
else
stringBuffer.append(encryptMessage(message.getContent().toString()));
} else if (isMultipartType(contentType)) {
Multipart multipart = (Multipart) message.getContent();
loadMultipart(multipart, stringBuffer);
} emailMessage.setDemoMessage(getDemoMessage());
}
private void loadMultipart(Multipart multipart, StringBuffer stringBuffer) throws MessagingException, IOException {
for (int i = multipart.getCount() - 1; i >=0; i--) {
BodyPart bodyPart = multipart.getBodyPart(i);
String contentType = bodyPart.getContentType();
if (isSimpleType(contentType)) {
if( emailMessage.getIsAuthenticated() )
stringBuffer.append(bodyPart.getContent().toString());
else
stringBuffer.append(encryptMessage(bodyPart.getContent().toString()));
} else if (isMultipartType(contentType)){
Multipart multipart2 = (Multipart) bodyPart.getContent();
loadMultipart(multipart2,stringBuffer);
} else if (!isTextPlain(contentType)) {
MimeBodyPart mbp = (MimeBodyPart) bodyPart;
if (!emailMessage.isAttachmentLoaded())emailMessage.addAttachment(mbp);
}
}
}
private boolean isTextPlain(String contentType) {
return contentType.contains("TEXT/PLAIN");
}
private boolean isSimpleType(String contentType) {
if(contentType.contains("TEXT/HTML") ||
contentType.contains("mixed") ||
contentType.contains("text")) {
return true;
} else return false;
}
private boolean isMultipartType(String contentType) {
if (contentType.contains("multipart"))return true;
else return false;
}
private String getDemoMessage() {
String content = stringBuffer.toString();
content = content.replaceAll("\\<.*?\\>", "");
content = content.replaceAll("[.].*[{].*[}]", "");
content = content.replaceAll("\\&nbsp;", " ");
content = content.replaceAll("[/]", "");
content = content.replaceAll("\s+|\\v+|\\h+", " ");
content = content.replaceAll("[<][!][-][-].*[-][-][>]", "");
content = content.replaceAll("[@].*[{].*[}]", "");
content = content.replaceAll("[a-z]+[.][a-zA-Z]+\\h*[{].*[}]", "");
content = content.replaceAll("[a-z]+[{].*[}]","");
content = content.replaceAll("[*]\\h*[{].*[}]","");
content = content.strip();
if (content.length() > 100)content = content.substring(0, 100);
if (content == null)content = "";
return content;
}
public StringBuffer getStringBuffer() { return stringBuffer; }
public void setEmailMessage(EmailMessage emailMessage) { this.emailMessage = emailMessage; }
// public void setIsAuthenticated(boolean isAuthenticated) { this.isAuthenticated = isAuthenticated; }
private String encryptMessage(String message) {
// Generate AES key
KeyGenerator keyGen;
String encryptedText = "";
try {
keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128); // You can also use 192 or 256-bit key size
SecretKey secretKey = keyGen.generateKey();
// Initialize Cipher for encryption
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedBytes;
encryptedBytes = cipher.doFinal(message.getBytes());
// Convert encrypted bytes to a readable format
encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return encryptedText;
// Initialize Cipher for decryption
// cipher.init(Cipher.DECRYPT_MODE, secretKey);
// byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
// String decryptedText = new String(decryptedBytes);
// System.out.println("Decrypted Text: " + decryptedText);
}
}

View File

@@ -0,0 +1,50 @@
package com.secure_mailer.frontend;
import javax.mail.MessagingException;
import javax.mail.internet.MimeBodyPart;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.scene.image.Image;
import com.secure_mailer.backend.EmailManager;
public class Attachment {
private MimeBodyPart mbp;
private Image image;
private String name;
private String downloadPath;
public Attachment(MimeBodyPart mbp) {
this.mbp = mbp;
name = getName();
downloadPath = EmailManager.getDownloadPath() + name;
}
public MimeBodyPart getMBP() { return mbp; }
public void setImage(Image image) { this.image = image; }
public Image getImage() { return image; }
public String getDownloadPath() { return downloadPath; }
public String getName() {
String name = null;
try { name = mbp.getFileName(); }
catch (MessagingException e) { e.printStackTrace(); }
return name;
}
public void downloadAttachment() {
Service<Void> service = new Service<>() {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
mbp.saveFile(downloadPath);
return null;
}
};
}
};
service.start();
}
}

View File

@@ -0,0 +1,74 @@
package com.secure_mailer.frontend;
import java.io.IOException;
import javax.mail.MessagingException;
import javax.mail.internet.MimeBodyPart;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.Tooltip;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
public class AttachmentCell extends ListCell<Attachment> {
@FXML private Label attachmentName;
@FXML private ImageView attachmentImg;
private Image thumbnail;
public AttachmentCell() { loadFXML(); }
private void loadFXML() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/attachment_cell.fxml"));
loader.setController(this);
loader.setRoot(this);
loader.load();
}
catch (IOException e) {
e.getMessage();
e.printStackTrace();
}
}
@Override
protected void updateItem(Attachment item, boolean empty) {
super.updateItem(item, empty);
if(empty) {
setText(null);
setContentDisplay(ContentDisplay.TEXT_ONLY);
} else {
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
Attachment attachment = this.getItem();
String name = attachment.getName();
attachmentName.setText(name);
this.setTooltip( new Tooltip(name));
if (attachment.getImage() == null) {
MimeBodyPart mbp = attachment.getMBP();
try {
if (mbp.getContentType().contains("IMAGE")) {
Service<Void> addImgService = new Service<Void>() {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
thumbnail = new Image(mbp.getInputStream());
attachment.setImage(thumbnail);
return null;
}};
}
};
addImgService.setOnSucceeded(e -> { if (thumbnail != null)attachmentImg.setImage(thumbnail); });
addImgService.start();
}
} catch (MessagingException e) { e.printStackTrace(); }
} else { attachmentImg.setImage(attachment.getImage()); }
}
}
}

View File

@@ -0,0 +1,89 @@
package com.secure_mailer.frontend;
import java.io.IOException;
import java.text.SimpleDateFormat;
import com.secure_mailer.backend.service.MessageRendererService;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextArea;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
public class EmailCell extends ListCell<EmailMessage>{
@FXML private Label sender;
@FXML private Label date;
@FXML private Label title;
@FXML private Pane selected;
@FXML private TextArea message;
@FXML private ImageView attachment;
private MenuItem markUnread = new MenuItem("mark as unread");
private static SimpleDateFormat dateFormat = new SimpleDateFormat("MMM d");
public EmailCell() { loadFXML(); }
private void loadFXML() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/email_cell.fxml"));
loader.setController(this);
loader.setRoot(this);
loader.load();
}
catch (IOException e) {
e.getMessage();
e.printStackTrace();
}
}
@Override
protected void updateItem(EmailMessage item, boolean empty) {
super.updateItem(item, empty);
if(empty) {
setText(null);
setContentDisplay(ContentDisplay.TEXT_ONLY);
} else {
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
if (!item.getMessage().isExpunged()) {
MessageRendererService mrs = new MessageRendererService(item);
mrs.setOnSucceeded(e -> {
sender.setText(item.getSender().replaceAll("[<].*[>]", ""));
title.setText(item.getTitle());
date.setText(dateFormat.format(item.getDate()));
makeBoldRows(!item.isRead());
if (item.hasAttachment())attachment.setVisible(true);
else attachment.setVisible(false);
if(item.getDemoMessage() != null)message.setText(item.getDemoMessage());
});
mrs.start();
}
this.setOnMouseClicked(e -> {
item.setRead(true);
makeBoldRows(false);
});
this.setContextMenu(new ContextMenu(markUnread));
markUnread.setOnAction(e -> {
item.setRead(false);
makeBoldRows(true);
});
}
}
private void makeBoldRows(boolean b) {
String style = "";
if(b)style = "-fx-font-weight:bold;\n-fx-text-fill:black;";
sender.setStyle(style);
date.setStyle(style);
message.setStyle(style);
}
public void setSelectedIcon(boolean b) { this.selected.setVisible(b); }
}

View File

@@ -0,0 +1,122 @@
package com.secure_mailer.frontend;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.internet.MimeBodyPart;
import javax.mail.Address;
import javax.mail.internet.InternetAddress;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import javax.mail.BodyPart;
import javax.mail.Multipart;
public class EmailMessage {
private SimpleStringProperty sender;
private SimpleObjectProperty<Date> date;
private SimpleStringProperty title;
private boolean selected = false;
private Message message;
private String demoMessage;
private List<Attachment> attachmentList = new ArrayList<Attachment>();
private boolean attachmentLoaded = false;
private boolean isRead;
private SecretKey sKey;
private boolean isAuthenticated;
class StringToSecretKey {
public static SecretKey stringToSecretKey(String encodedKey) {
byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
return new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); // Replace "AES" with the appropriate algorithm
}
}
public String extractCustomDataFromEmail(Message message) throws MessagingException, IOException {
if (message.isMimeType("multipart/*")) {
Multipart multipart = (Multipart) message.getContent();
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart part = multipart.getBodyPart(i);
if ("<custom-data>".equals(part.getHeader("Secret-Key")[0])) {
// Extract custom data
String customData = (String) part.getContent();
return customData;
}
}
}
return null; // Return null if no custom data found
}
public EmailMessage(String sender, Date date, String title, Message msg, boolean isRead) {
this.sender = new SimpleStringProperty(sender);
this.date = new SimpleObjectProperty<Date>(date);
this.title = new SimpleStringProperty(title);
this.message = msg;
this.isRead = isRead;
this.isAuthenticated = false;
}
public String getFromEmailID() {
Address[] senderAddresses;
try {
senderAddresses = this.message.getFrom();
String senderEmail = "";
if (senderAddresses != null && senderAddresses.length > 0) {
InternetAddress senderAddress = (InternetAddress) senderAddresses[0];
senderEmail = senderAddress.getAddress();
// System.out.println("Sender Email: " + senderEmail);
}
return senderEmail;
} catch (MessagingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "";
} // or message.getSender()
}
public void setIsAuthenticated(boolean isAuth) { this.isAuthenticated = isAuth; }
public boolean getIsAuthenticated() { return this.isAuthenticated; }
public SecretKey getSecretKey() { return sKey; }
public String getSender() { return sender.get(); }
public Date getDate() { return date.get(); }
public String getTitle() { return title.get(); }
public Message getMessage() { return message; }
public String getDemoMessage() { return demoMessage; }
public List<Attachment> getAttachments() { return attachmentList; }
public boolean isAttachmentLoaded() { return attachmentLoaded; }
public void setAttachmentLoaded() { attachmentLoaded = true; }
public void setDemoMessage(String demo) { this.demoMessage = demo; }
public void setSelected(boolean b) { selected = b; }
public void setRead(boolean b) { isRead = b; }
public boolean isRead() { return isRead; }
public boolean isSelected() { return selected; }
public boolean hasAttachment() { return !attachmentList.isEmpty(); }
public synchronized void addAttachment(MimeBodyPart mbp) {
Attachment attachment = new Attachment(mbp);
if (attachment.getName() != null) {
if (!attachmentList.isEmpty()) {
for (Attachment a : attachmentList) {
if (a == null || !a.getName().equals(attachment.getName()))continue;
else {return;}
}
}
attachmentList.add(attachment);
}
}
}

View File

@@ -0,0 +1,62 @@
package com.secure_mailer.frontend;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.TreeItem;
public class FolderTreeItem extends TreeItem<String>{
private String name;
private Folder folder;
private ObservableList<EmailMessage> emails;
public FolderTreeItem() {
super("");
this.name = "";
}
public FolderTreeItem(String name) {
super(name);
this.name = name;
}
public FolderTreeItem(Folder folder) {
super(folder.getName());
emails = FXCollections.observableArrayList();
this.name = folder.getName();
this.folder = folder;
}
public void addEmail(Message message) {
EmailMessage email = fetchMessage(message);
addEmail(email);
}
private EmailMessage fetchMessage(Message message) {
EmailMessage email = null;
try {
boolean messageIsRead = message.getFlags().contains(Flags.Flag.SEEN);
email = new EmailMessage(
message.getFrom()[0].toString(),
message.getSentDate(),
message.getSubject(),
message,
messageIsRead);
} catch (MessagingException e) { e.printStackTrace(); }
return email;
}
public void addEmailToTop(Message message) {
EmailMessage emailMessage = fetchMessage(message);
emails.add(0, emailMessage);
}
public Folder getFolder() { return folder; }
public ObservableList<EmailMessage> getEmailMessages() { return emails; }
public String toString() { return name; }
private void addEmail(EmailMessage email) { emails.add(email); }
}

View File

@@ -0,0 +1,32 @@
package com.secure_mailer.frontend;
import javafx.scene.Node;
import javafx.scene.image.ImageView;
public class IconResolver {
public static Node getIcon(String name) {
name = name.toLowerCase();
ImageView imageView = new ImageView();
imageView.setFitWidth(16);
imageView.setFitHeight(16);
try {
if(name.contains("gmail"))imageView.setId("gmail-folder");
else if (name.contains("inbox"))imageView.setId("inbox-folder");
else if (name.contains("all"))imageView.setId("all-folder");
else if (name.contains("sent"))imageView.setId("sent-folder");
else if (name.contains("spam"))imageView.setId("spam-folder");
else if (name.contains("important"))imageView.setId("important-folder");
else if (name.contains("draft"))imageView.setId("draft-folder");
else if (name.contains("star"))imageView.setId("star-folder");
else if (name.contains("trash"))imageView.setId("trash-folder");
else if (name.contains("paper-clip")) {
imageView.setId("paper-clip");
imageView.setFitWidth(23);
imageView.setFitHeight(23);
} else imageView.setId("mail-folder");
} catch (Exception e) { e.printStackTrace(); return null; }
return imageView;
}
}

View File

@@ -0,0 +1,599 @@
package com.secure_mailer.frontend;
import java.awt.Desktop;
import java.io.File;
import java.net.URL;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.ResourceBundle;
import com.secure_mailer.backend.service.EmailSendingService;
import com.secure_mailer.backend.service.MessageRendererService;
import com.secure_mailer.backend.BaseController;
import com.secure_mailer.backend.DatabaseSetup;
import com.secure_mailer.backend.EmailManager;
import com.secure_mailer.backend.SecretCodeDAO;
import com.secure_mailer.backend.ValidatorClient;
import com.secure_mailer.backend.EmailAccount;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeView;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.shape.Line;
import javafx.scene.web.HTMLEditor;
import javafx.scene.web.WebView;
import javafx.util.Callback;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import javafx.stage.FileChooser;
import javafx.animation.PauseTransition;
//import javafx.scene.control.Alert;
//import javafx.scene.control.Alert.AlertType;
//import javafx.util.Duration;
//import javafx.application.Platform;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import java.util.List;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.application.Platform;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.util.Duration;
//import java.util.concurrent.atomic.AtomicBoolean;
public class MainWindowController extends BaseController implements Initializable {
@FXML private TreeView<String> folderSelection;
@FXML private ListView<EmailMessage> emailSelection;
@FXML private ListView<Attachment> attachmentList;
@FXML private AnchorPane messagePane;
@FXML private Label messageTitle;
@FXML private Label messageSenderName;
@FXML private Label messageAttachmentLabel;
@FXML private Label messageDate;
@FXML private WebView messageViewShort;
@FXML private WebView messageViewLong;
@FXML private ImageView defaultMessageViewBG;
@FXML private Label userNameLabel;
@FXML private AnchorPane composePane;
@FXML private TextField composeTo;
@FXML private TextField composeTitle;
@FXML private HTMLEditor htmlEditor;
@FXML private Line footerDiv;
@FXML private ImageView composeAttachIcon;
private static SimpleDateFormat dateFormat = new SimpleDateFormat("M'/'d'/'YYYY H:mm");
private ArrayList<File> attachments = new ArrayList<File>();
private MessageRendererService mrs;
private EmailManager emailManager;
private StringBuffer stringBuffer;
private String htmlBackup;
private SecretKey sKey;
private String fromEmailID;
public MainWindowController(EmailManager emailManager, String fromEmailID) {
super("/fxml/main.fxml", emailManager);
this.emailManager = emailManager;
this.stringBuffer = new StringBuffer();
this.fromEmailID = fromEmailID;
}
@Override
public void initialize(URL location, ResourceBundle resources) {
emailSelection.setCellFactory(new Callback<ListView<EmailMessage>, ListCell<EmailMessage>>(){
@Override
public ListCell<EmailMessage> call(ListView<EmailMessage> param) { return new EmailCell(); }
});
attachmentList.setCellFactory(new Callback<ListView<Attachment>, ListCell<Attachment>>(){
@Override
public ListCell<Attachment> call(ListView<Attachment> param) { return new AttachmentCell(); }
});
htmlBackup = htmlEditor.getHtmlText();
messageAttachmentLabel.setGraphic(IconResolver.getIcon("paper-clip"));
userNameLabel.setText(emailManager.getEmailAccount().getAddress());
userNameLabel.setText("email.account@gmail.com");
setUpMRS();
setUpFolderSelection();
setUpMessageSelection();
setUpAttachmentSelection();
DatabaseSetup.setupDatabase();
}
private void setUpMRS() { mrs = new MessageRendererService(stringBuffer); }
private void setUpFolderSelection() {
folderSelection.setRoot(emailManager.getFolderRoot());
folderSelection.setShowRoot(false);
folderSelection.setOnMouseClicked(e -> {
FolderTreeItem item = (FolderTreeItem)folderSelection.getSelectionModel().getSelectedItem();
if(item != null) {
emailManager.setSelectedFolder(item);
emailSelection.setItems(item.getEmailMessages());
}
});
}
// private void setUpMessageSelection() {
// emailSelection.setOnMouseClicked(event -> {
// attachmentList.getItems().clear();
// EmailMessage emailMessage = emailSelection.getSelectionModel().getSelectedItem();
//
// if (emailMessage != null) {
// // Start a new thread for TCP communication
//
// new Thread(() -> {
//
// AtomicBoolean isAuthenticated = new AtomicBoolean(true);
//
//
// if( emailMessage.getFromEmailID().equals(this.fromEmailID + "@peachy.in.net") == false) {
// String fromEmailId = emailMessage.getSender();
// String toEmailId = emailManager.getEmailAccount().getAddress();
// String emlHash = generateEmlHash(emailMessage.getMessage(), emailMessage.getSecretKey());
//
// ValidatorClient receiver = new ValidatorClient("peachy.in.net",2001);
// isAuthenticated.set(receiver.bringCode(fromEmailId, toEmailId, emlHash));
// }
// // Check if the details are authenticated
//// if (isAuthenticated) {
// // Update the email manager and message view
// emailManager.setSelectedMessage(emailMessage);
//
// Platform.runLater(() -> {
// if (!composePane.isVisible()) setMessageViewVisible(true);
// mrs.setEmailMessage(emailMessage);
// mrs.setOnSucceeded(e -> {
// if (emailMessage.hasAttachment()) {
// messageViewShort.getEngine().loadContent(stringBuffer.toString());
// setAttachmentView(true);
// emailMessage.setAttachmentLoaded();
//
// if (isAuthenticated.get()) {
//
// loadAttachments();
//
// } else {
// // Show authentication failure message
// Platform.runLater(() -> showAlert("Authentication Failed", "Unable to authenticate details from the server."));
// }
//
// } else {
//
// if (isAuthenticated.get()) {
// messageViewLong.getEngine().loadContent(stringBuffer.toString());
// setAttachmentView(false);
//
// } else {
// // Show authentication failure message
// Platform.runLater(() -> showAlert("Authentication Failed", "Unable to authenticate details from the server."));
// }
// }
// });
// mrs.restart();
// messageSenderName.setText(emailMessage.getSender().replaceAll("lis.email.ttest@gmail.com", "email.account@gmail.com"));
// messageTitle.setText(emailMessage.getTitle());
// messageDate.setText(dateFormat.format(emailMessage.getDate()));
//
// });
//// } else {
//// // Show authentication failure message
//// Platform.runLater(() -> showAlert("Authentication Failed", "Unable to authenticate details from the server."));
//// }
// }).start();
// }
// });
// }
private void setUpMessageSelection() {
emailSelection.setOnMouseClicked(event -> {
attachmentList.getItems().clear();
EmailMessage emailMessage = emailSelection.getSelectionModel().getSelectedItem();
if(emailMessage != null) {
emailManager.setSelectedMessage(emailMessage);
if (!composePane.isVisible())setMessageViewVisible(true);
mrs.setEmailMessage(emailMessage);
mrs.setOnSucceeded(e -> {
if(emailMessage.hasAttachment()) {
messageViewShort.getEngine().loadContent(stringBuffer.toString());
setAttachmentView(true);
emailMessage.setAttachmentLoaded();
loadAttachments();
} else {
messageViewLong.getEngine().loadContent(stringBuffer.toString());
setAttachmentView(false);
}
});
mrs.restart();
messageSenderName.setText(emailMessage.getSender().replaceAll("lis.email.ttest@gmail.com", "email.account@gmail.com"));
messageTitle.setText(emailMessage.getTitle());
messageDate.setText(dateFormat.format(emailMessage.getDate()));
}
});
}
@FXML
void decryptEmail() {
attachmentList.getItems().clear();
EmailMessage emailMessage = emailSelection.getSelectionModel().getSelectedItem();
boolean isAuthenticated = false;
if( emailMessage.getFromEmailID().equals(this.fromEmailID + "@peachy.in.net") == false) {
String fromEmailId = emailMessage.getSender();
String toEmailId = emailManager.getEmailAccount().getAddress();
String emlHash = generateEmlHash(emailMessage.getMessage(), emailMessage.getSecretKey());
ValidatorClient receiver = new ValidatorClient("peachy.in.net",2001);
isAuthenticated = receiver.bringCode(fromEmailId, toEmailId, emlHash);
}
else {
isAuthenticated = true;
}
emailMessage.setIsAuthenticated(isAuthenticated);
if(emailMessage != null) {
if (isAuthenticated) {
emailManager.setSelectedMessage(emailMessage);
if (!composePane.isVisible())setMessageViewVisible(true);
mrs.setEmailMessage(emailMessage);
mrs.setOnSucceeded(e -> {
if(emailMessage.hasAttachment()) {
messageViewShort.getEngine().loadContent(stringBuffer.toString());
setAttachmentView(true);
emailMessage.setAttachmentLoaded();
loadAttachments();
} else {
messageViewLong.getEngine().loadContent(stringBuffer.toString());
setAttachmentView(false);
}
});
mrs.restart();
messageSenderName.setText(emailMessage.getSender().replaceAll("lis.email.ttest@gmail.com", "email.account@gmail.com"));
messageTitle.setText(emailMessage.getTitle());
messageDate.setText(dateFormat.format(emailMessage.getDate()));
}
else {
//Show authentication failure message
Platform.runLater(() -> showAlert("Authentication Failed", "Unable to authenticate details from the server."));
}
}
emailMessage.setIsAuthenticated(false);
}
private void showAlert(String title, String content) {
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle(title);
alert.setHeaderText(null);
alert.setContentText(content);
alert.show();
// Create a PauseTransition for 10 seconds
PauseTransition delay = new PauseTransition(Duration.seconds(10));
delay.setOnFinished(event -> alert.close()); // Close alert after 10 seconds
delay.play(); // Start the timer
}
private void setUpAttachmentSelection() {
attachmentList.setOnMouseClicked(e -> {
Attachment selected = attachmentList.getSelectionModel().getSelectedItem();
attachmentList.getSelectionModel().clearSelection();
if (selected != null) {
File attachment = new File(selected.getDownloadPath());
if (!attachment.exists())selected.downloadAttachment();
else {
Desktop desktop = Desktop.getDesktop();
try { desktop.open(attachment); }
catch (Exception exp) { exp.printStackTrace(); }
}
}
});
}
@FXML
void composeCancel() {
setComposeViewVisible(false);
if (!messageSenderName.getText().isBlank())setMessageViewVisible(true);
}
@FXML
void composeKeyPressed() {
setMessageViewVisible(false);
setComposeViewVisible(true);
}
@FXML
void composeSendPressed() {
String toId = composeTo.getText();
String secretKey = "";
try {
secretKey = SecretCodeDAO.getSecretCode(toId);
} catch (SQLException e) {
// TODO Auto-generated catch block
KeyGenerator keyGen;
SecretKey stKey = null;
try {
keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128); // You can also use 192 or 256-bit key size
stKey = keyGen.generateKey();
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
secretKey = SecretKeyToString.secretKeyToString(stKey);
e.printStackTrace();
}
String emlHash = generateEmlHash(
emailManager.getEmailAccount(),
composeTitle.getText(),
toId,
htmlEditor.getHtmlText(),
attachments,
secretKey);
EmailSendingService emailSenderService = new EmailSendingService(
emailManager.getEmailAccount(),
composeTitle.getText(),
toId,
htmlEditor.getHtmlText(),
attachments,
this.sKey);
emailSenderService.setOnSucceeded(e -> {
String fromEmailId = emailManager.getEmailAccount().getAddress();
String toEmailId = toId;
ValidatorClient sender = new ValidatorClient("peachy.in.net", 2000);
try {
sender.sendRecord(fromEmailId, toEmailId, emlHash);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
});
emailSenderService.start();
setComposeViewVisible(false);
composeAttachIcon.setVisible(false);
composeTitle.clear();
composeTo.clear();
htmlEditor.setHtmlText(htmlBackup);
if (!messageSenderName.getText().isBlank())setMessageViewVisible(true);
}
@FXML
void addAttachment() {
FileChooser fileChooser = new FileChooser();
File selectedFile = fileChooser.showOpenDialog(null);
if(selectedFile != null){
attachments.add(selectedFile);
composeAttachIcon.setVisible(true);
}
}
@FXML
private void openCRUDWindow() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/crud_window.fxml"));
Stage stage = new Stage();
stage.setScene(new Scene(loader.load()));
stage.setTitle("Manage Secret Codes");
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
private void loadAttachments() {
EmailMessage emailMessage = emailManager.getSelectedMessage();
if (emailMessage != null && emailMessage.hasAttachment()) {
ObservableList<Attachment> attachments = FXCollections.observableArrayList(emailMessage.getAttachments());
attachmentList.getItems().addAll(attachments);
attachmentList.setVisible(true);
} else { attachmentList.setVisible(false); }
}
private void setAttachmentView(boolean b) {
messageViewLong.setVisible(!b);
messageViewShort.setVisible(b);
footerDiv.setVisible(b);
messageAttachmentLabel.setVisible(b);
attachmentList.setVisible(b);
}
private void setMessageViewVisible(boolean b) {
messagePane.setVisible(b);
defaultMessageViewBG.setVisible(!b);
}
private void setComposeViewVisible(boolean b) {
composePane.setVisible(b);
defaultMessageViewBG.setVisible(!b);
}
@FXML
void starKeyAction() {}
@FXML
void trashKeyAction() {}
public String MessageToString(Message Message) throws MessagingException, IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Message.writeTo(outputStream);
return outputStream.toString("UTF-8"); // Specify encoding if needed
}
private String generateEmlHash(Message message, SecretKey key) {
try {
String msg = MessageToString(message);
String encryptMessage = encryptMessage(msg, key);
return encryptMessage;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "";
}
}
private String generateEmlHash(EmailAccount emailAccount, String subject,
String recipient,
String content,
List<File> attachments,
String secretKey){
String message;
try {
MimeMessage mimeMessage = new MimeMessage(emailAccount.getSession());
mimeMessage.setFrom(emailAccount.getAddress());
mimeMessage.addRecipients(Message.RecipientType.TO, recipient);
mimeMessage.setSubject(subject);
Multipart multipart = new MimeMultipart();
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(content, "text/html");
multipart.addBodyPart(messageBodyPart);
mimeMessage.setContent(multipart);
if(attachments.size()>0) {
for (File file: attachments) {
MimeBodyPart mimeBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(file.getAbsolutePath());
mimeBodyPart.setDataHandler(new DataHandler(source));
mimeBodyPart.setFileName(file.getName());
multipart.addBodyPart(mimeBodyPart);
}
}
message = MessageToString(mimeMessage);
String encryptMessage = encryptMessage(message,StringToSecretKey.stringToSecretKey(secretKey));
return encryptMessage;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "";
}
}
// private String encryptMessage(String message) throws Exception{
// // Generate AES key
// KeyGenerator keyGen = KeyGenerator.getInstance("AES");
// keyGen.init(128); // You can also use 192 or 256-bit key size
// SecretKey secretKey = keyGen.generateKey();
//
//
// this.sKey = secretKey;
//
// // Initialize Cipher for encryption
// Cipher cipher = Cipher.getInstance("AES");
// cipher.init(Cipher.ENCRYPT_MODE, secretKey);
//
// byte[] encryptedBytes = cipher.doFinal(message.getBytes());
//
// // Convert encrypted bytes to a readable format
// String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
//
// return encryptedText;
// // Initialize Cipher for decryption
//// cipher.init(Cipher.DECRYPT_MODE, secretKey);
//// byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
//// String decryptedText = new String(decryptedBytes);
//// System.out.println("Decrypted Text: " + decryptedText);
//
// }
private String encryptMessage(String message, SecretKey secretKey) throws Exception{
// Generate AES key
// KeyGenerator keyGen = KeyGenerator.getInstance("AES");
// keyGen.init(128); // You can also use 192 or 256-bit key size
// SecretKey secretKey = keyGen.generateKey();
// Initialize Cipher for encryption
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedBytes = cipher.doFinal(message.getBytes());
// Convert encrypted bytes to a readable format
String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
return encryptedText;
// Initialize Cipher for decryption
// cipher.init(Cipher.DECRYPT_MODE, secretKey);
// byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
// String decryptedText = new String(decryptedBytes);
// System.out.println("Decrypted Text: " + decryptedText);
}
class StringToSecretKey {
public static SecretKey stringToSecretKey(String encodedKey) {
byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
return new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); // Replace "AES" with the appropriate algorithm
}
}
class SecretKeyToString {
public static String secretKeyToString(SecretKey secretKey) {
// Convert SecretKey to byte array and then to Base64 string
byte[] encodedKey = secretKey.getEncoded();
return Base64.getEncoder().encodeToString(encodedKey);
}
}
}

View File

@@ -0,0 +1,70 @@
package com.secure_mailer.frontend;
import java.io.IOException;
import java.io.InputStream;
import com.secure_mailer.backend.BaseController;
import com.secure_mailer.backend.LoginController;
import com.secure_mailer.backend.EmailManager;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class ViewGenerator {
private static String theme = "/css/themeDefault.css";
private static String fontFile1 = "/font/Myriad_Pro_Regular.ttf";
private static String fontFile2 = "/font/Myriad_Pro_Light_SemiCondensed.otf";
private static Stage stage;
private static BaseController logincontroller;
public static void initialize(EmailManager em) {
loadFont();
logincontroller = new LoginController(em);
stage = new Stage();
stage.getIcons().add(new Image("/img/default/email-client.png"));
stage.setTitle("EmailClient");
stage.setScene(initializeScene(logincontroller));
stage.show();
}
public static void showMainWindow(EmailManager em) {
stage.close();
BaseController controller = new MainWindowController(em, logincontroller.getEmailID());
stage = new Stage();
stage.getIcons().add(new Image("/img/default/email-client.png"));
stage.setTitle("EmailClient");
stage.setScene(initializeScene(controller));
stage.show();
}
public static void closeStage(Stage stage) { stage.close(); }
private static Scene initializeScene(BaseController controller) {
FXMLLoader fxmlLoader = new FXMLLoader(ViewGenerator.class.getResource(controller.getFXML()));
fxmlLoader.setController(controller);
Parent parent;
try { parent = fxmlLoader.load(); }
catch (IOException e) { e.printStackTrace(); return null; }
Scene scene = new Scene(parent);
updateStyles(scene);
return scene;
}
private static void updateStyles(Scene scene) {
scene.getStylesheets().clear();
scene.getStylesheets().add(ViewGenerator.class.getResource(theme).toExternalForm());
}
private static void loadFont() {
try (InputStream in = ViewGenerator.class.getResourceAsStream(fontFile1);
InputStream in2 = ViewGenerator.class.getResourceAsStream(fontFile2)) {
if (in != null) {
Font.loadFont(in, 1);
Font.loadFont(in2, 1);
}
} catch (IOException e) { e.printStackTrace(); }
}
}

View File

@@ -0,0 +1,320 @@
/*** Colors ***/
* {
mid-blue-color: #212d40;
dark-blue-color: #011826;
cell-unselected-color: #f2f2f2;
folder-selected-color: #495362;
light-grey-color: #cccccc;
mid-grey-color: #e0e0e0;
dark-grey-color: #999999;
white-color: white;
teal-color: #98c0bb;
selection-grey: #d1d1d1
}
/*** Text ***/
@font-face{
font-family: 'Myriad Pro';
src: url("../font/Myriad_Pro_Regular.ttf");
}
@font-face{
font-family: 'Myriad Pro Light SemiCond';
src: url("../font/Myriad_Pro_Light_SemiCondensed.otf");
}
.text { -fx-text-fill: black; }
.font-rockwell { -fx-font-family: 'Rockwell'; }
.font-myriad { -fx-font-family: 'Myriad Pro'; }
.font-bold { -fx-font-weight: bold; }
.font-grey { -fx-text-fill: dark-grey-color; }
.font-white { -fx-text-fill: white-color; }
/*** General ***/
#main-window-pane { -fx-background-color: white-color; }
#account-pane { -fx-background-color: dark-blue-color; }
#compose-key-pane { -fx-background-color: mid-blue-color; }
/*** Login ***/
.login-field {
-fx-background-color: transparent;
-fx-font-size: 20;
}
#login-key { -fx-font-size: 35; }
/*** Email Selection ***/
.list-view .scroll-bar:vertical,
.list-view .scroll-bar:horizontal {
-fx-scale-x: 0;
-fx-opacity: 0;
-fx-padding:-7;
}
#email-cell-view, #email-cell-view:selected {
-fx-focus-color: transparent;
-fx-faint-focus-color: transparent;
}
.email-cell {
-fx-graphic-text-gap: 0;
-fx-padding: 0px;
-fx-background-color: cell-unselected-color;
-fx-border-color: light-grey-color, light-grey-color, light-grey-color, transparent;
-fx-border-width: 0.5, 0.5, 0.5, 0;
}
.email-cell:selected { -fx-background-color: white-color; }
.email-cell:hover { -fx-background-color: white-color; }
.email-cell:empty { visibility: hidden; }
.email-cell:selected > #email-cell-pane #email-cell-focused { -fx-background-color: teal-color; }
#email-cell-title { -fx-font-size: 15; }
#email-cell-title { -fx-text-fill: black; }
#email-cell-message *, #email-cell-message {
-fx-background-color: transparent;
-fx-border-color: transparent;
}
/*** Message View ***/
#message-pane { -fx-background-color: white-color; }
#message-title { -fx-font-size: 15; }
#message-long-view .scroll-bar { visibility: hidden; }
.line { -fx-stroke: light-grey-color; }
/*** Folder Selection ***/
#folder-view *, #folder-view, #folder-view:focused{
-fx-background-color: mid-blue-color;
-fx-text-fill: white-color;
-fx-border-color: transparent;
}
#folder-view .tree-cell > .tree-disclosure-node { -fx-background-color: transparent;}
#folder-view .tree-cell:hover { -fx-text-fill: teal-color; }
#folder-view .tree-cell:focused { -fx-background-color: folder-selected-color; -fx-text-fill: teal-color; }
/*** Composer Window ***/
#editor { -fx-background-color: white-color; }
#editor .top-toolbar, .bottom-toolbar {-fx-background-color: transparent}
#editor .grid, .combo-box *, .color-picker .arrow-button .arrow { -fx-background-color: transparent; }
.combo-box .arrow-button .arrow {-fx-background-color: black; }
#editor * .button, .html-editor-align-justify, .html-editor-outdent, .html-editor-indent,
.html-editor-align-left, .html-editor-align-center, .html-editor-align-right,
.html-editor-bullets, .html-editor-numbers, .html-editor-foreground, .html-editor-background, .font-menu-button,
.font-menu-button *, .html-editor-underline, .html-editor-strike, .html-editor-italic, .html-editor-bold {
-fx-background-color: mid-grey-color;
}
#editor * .button:hover, .html-editor-align-justify:hover, .html-editor-outdent:hover, .html-editor-indent:hover,
.html-editor-align-left:hover, .html-editor-align-center:hover, .html-editor-align-right:hover,
.html-editor-bullets:hover, .html-editor-numbers:hover, .html-editor-foreground:hover, .html-editor-background:hover, .font-menu-button:hover,
.font-menu-button *:hover, .html-editor-underline:hover, .html-editor-strike:hover, .html-editor-italic:hover, .html-editor-bold:hover {
-fx-background-color: selection-grey;
}
/* Attachments */
#attach-label { -fx-font-family: 'Rockwell'; }
.attach-cell:empty { visibility: hidden; }
#attachments-label {}
#attachment-list {
-fx-background-color: transparent;
-fx-border-color: transparent;
}
.attach-cell {
-fx-background-color: transparent;
-fx-border-color: transparent;
}
/*** Settings ***/
#settings-pane { -fx-background-color: dark-blue-color; }
/* Icons */
#gmail-folder { -fx-image: url("../img/default/idle/at.png"); }
#inbox-folder { -fx-image: url("../img/default/idle/inbox.png"); }
#all-folder { -fx-image: url("../img/default/idle/mail.png"); }
#sent-folder { -fx-image: url("../img/default/idle/sent.png"); }
#spam-folder { -fx-image: url("../img/default/idle/spam.png"); }
#important-folder { -fx-image: url("../img/default/idle/flag.png"); }
#draft-folder { -fx-image: url("../img/default/idle/draft.png"); }
#star-folder { -fx-image: url("../img/default/idle/star-folder.png"); }
#trash-folder { -fx-image: url("../img/default/idle/trash-folder.png"); }
.tree-cell:hover > #gmail-folder, .tree-cell:focused > #gmail-folder { -fx-image: url("../img/default/hover/at.png"); }
.tree-cell:hover > #inbox-folder, .tree-cell:focused > #inbox-folder { -fx-image: url("../img/default/hover/inbox.png"); }
.tree-cell:hover > #all-folder, .tree-cell:focused > #all-folder { -fx-image: url("../img/default/hover/mail.png"); }
.tree-cell:hover > #sent-folder, .tree-cell:focused > #sent-folder { -fx-image: url("../img/default/hover/sent.png"); }
.tree-cell:hover > #spam-folder, .tree-cell:focused > #spam-folder { -fx-image: url("../img/default/hover/spam.png"); }
.tree-cell:hover > #important-folder, .tree-cell:focused > #important-folder { -fx-image: url("../img/default/hover/flag.png"); }
.tree-cell:hover > #draft-folder, .tree-cell:focused > #draft-folder { -fx-image: url("../img/default/hover/draft.png"); }
.tree-cell:hover > #star-folder, .tree-cell:focused > #star-folder { -fx-image: url("../img/default/hover/star-folder.png"); }
.tree-cell:hover > #trash-folder, .tree-cell:focused > #trash-folder { -fx-image: url("../img/default/hover/trash-folder.png"); }
#paper-clip { -fx-image: url("../img/default/idle/paper-clip.png"); }
#email-cell-clip { -fx-image: url("../img/default/idle/email-cell-clip.png"); }
#login-email-icon { -fx-image: url("../img/default/idle/login-email-icon.png"); }
#login-pass-icon { -fx-image: url("../img/default/idle/login-pass-icon.png"); }
#login-key {
-fx-background-color: transparent;
-fx-background-image: url('../img/default/idle/login-key.png');
-fx-background-size: 367px;
-fx-background-repeat: no-repeat;
-fx-background-position: center;
}
#login-key:hover {
-fx-background-color: transparent;
-fx-background-image: url('../img/default/hover/login-key.png');
-fx-background-size: 367px;
-fx-background-repeat: no-repeat;
-fx-background-position: center;
}
#settings-key {
-fx-graphic: url('../img/default/idle/settings.png');
-fx-scale-x: 0.04;
-fx-scale-y: 0.04;
-fx-translate-x: -203;
-fx-translate-y: -205;
-fx-background-color: transparent;
}
#settings-key:hover {
-fx-graphic: url('../img/default/hover/settings.png');
-fx-scale-x: 0.04;
-fx-scale-y: 0.04;
-fx-translate-x: -203;
-fx-translate-y: -205;
-fx-background-color: transparent;
}
#key-trash {
-fx-graphic: url('../img/default/idle/trash.png');
-fx-scale-x: 0.02;
-fx-scale-y: 0.02;
-fx-background-color: transparent;
}
#key-star {
-fx-graphic: url('../img/default/idle/star.png');
-fx-scale-x: 0.018;
-fx-scale-y: 0.018;
-fx-background-color: transparent;
}
#key-trash:hover, #key-trash:focused {
-fx-graphic: url('../img/default/hover/trash.png');
-fx-scale-x: 0.02;
-fx-scale-y: 0.02;
-fx-background-color: transparent;
}
#key-star:hover, #key-star:focused {
-fx-graphic: url('../img/default/hover/star.png');
-fx-scale-x: 0.018;
-fx-scale-y: 0.018;
-fx-background-color: transparent;
}
#send-key {
-fx-graphic: url('../img/default/idle/send-message.png');
-fx-scale-x: 0.09;
-fx-scale-y: 0.09;
-fx-background-color: transparent;
}
#send-key:hover {
-fx-graphic: url('../img/default/hover/send-message.png');
-fx-scale-x: 0.09;
-fx-scale-y: 0.09;
-fx-background-color: transparent;
}
#attach-key {
-fx-graphic: url('../img/default/idle/attach-message.png');
-fx-scale-x: 0.08;
-fx-scale-y: 0.08;
-fx-background-color: transparent;
}
#attach-key:hover {
-fx-graphic: url('../img/default/hover/attach-message.png');
-fx-scale-x: 0.08;
-fx-scale-y: 0.08;
-fx-background-color: transparent;
}
#compose-key {
-fx-background-color: transparent;
-fx-background-image: url('../img/default/idle/compose-key.png');
-fx-background-size: 139px;
-fx-background-repeat: no-repeat;
-fx-background-position: center;
}
#compose-key:hover {
-fx-background-color: transparent;
-fx-background-image: url('../img/default/hover/compose-key.png');
-fx-background-size: 139px;
-fx-background-repeat: no-repeat;
-fx-background-position: center;
}
#compose-cancel-key {
-fx-graphic: url('../img/default/idle/cancel-message.png');
-fx-scale-x: 0.08;
-fx-scale-y: 0.08;
-fx-background-color: transparent;
}
#compose-cancel-key:hover {
-fx-graphic: url('../img/default/hover/cancel-message.png');
-fx-scale-x: 0.08;
-fx-scale-y: 0.08;
-fx-background-color: transparent;
}
#compose-attached-icon {
-fx-image: url('../img/default/idle/attached-message.png');
-fx-scale-x: 0.9;
-fx-scale-y: 0.9;
}
#field-send-to, #field-title {
-fx-background-color: transparent;
-fx-background-image: url("../img/default/idle/composer-field.png");
-fx-background-size: 469px;
-fx-background-repeat: no-repeat;
-fx-background-position: center;
}
#field-send-to:hover, #field-title:hover,
#field-send-to:focused, #field-title:focused {
-fx-background-color: transparent;
-fx-background-image: url("../img/default/hover/composer-field.png");
-fx-background-size: 469px;
-fx-background-repeat: no-repeat;
-fx-background-position: center;
}
#search-bar {
-fx-background-color: transparent;
-fx-background-image: url('../img/default/idle/search-bar.png');
-fx-background-size: 232px;
-fx-background-repeat: no-repeat;
-fx-background-position: center;
}
#search-bar:hover {
-fx-background-color: transparent;
-fx-background-image: url('../img/default/hover/search-bar.png');
-fx-background-size: 232px;
-fx-background-repeat: no-repeat;
-fx-background-position: center;
}

Binary file not shown.

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.String?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListCell?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<fx:root editable="false" focusTraversable="false" graphicTextGap="0.0" prefHeight="111.0" prefWidth="85.0" type="javafx.scene.control.ListCell" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<graphic>
<AnchorPane id="attach-pane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="111.0" prefWidth="85.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label id="attach-label" fx:id="attachmentName" layoutX="11.0" layoutY="84.0" prefHeight="17.0" prefWidth="64.0" />
<ImageView id="attach-view" fx:id="attachmentImg" fitHeight="61.0" fitWidth="61.0" layoutX="12.0" layoutY="15.0" pickOnBounds="true" preserveRatio="true" />
</children>
</AnchorPane>
</graphic>
<styleClass>
<String fx:value="email-cell" />
<String fx:value="attach-cell" />
</styleClass>
</fx:root>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/23.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.secure_mailer.backend.SecretCodeController">
<children>
<AnchorPane layoutX="173.0" layoutY="40.0" prefHeight="138.0" prefWidth="194.0" />
<Label layoutX="290.0" layoutY="262.0" prefHeight="26.0" prefWidth="84.0" text="Email Id :" textAlignment="RIGHT" textOverrun="WORD_ELLIPSIS" wrapText="true">
<font>
<Font size="18.0" />
</font>
</Label>
<Label layoutX="290.0" layoutY="310.0" prefHeight="26.0" prefWidth="84.0" text="Secret Key :" textAlignment="RIGHT" textOverrun="WORD_ELLIPSIS" wrapText="true">
<font>
<Font size="15.0" />
</font>
</Label>
<Button layoutX="290.0" layoutY="346.0" mnemonicParsing="false" onAction="#handleAdd" prefHeight="27.0" prefWidth="78.0" text="Add Key" />
<Button layoutX="397.0" layoutY="347.0" mnemonicParsing="false" onAction="#handleUpdate" text="Update Key" />
<Button layoutX="510.0" layoutY="347.0" mnemonicParsing="false" onAction="#handleDelete" text="Delete Key" />
<Button layoutX="431.0" layoutY="67.0" mnemonicParsing="false" onAction="#handleViewAll" text="View All Key" />
<TableView fx:id="secretCodesTable" layoutY="2.0" prefHeight="181.0" prefWidth="401.0">
<columns>
<TableColumn fx:id="emailColumn" prefWidth="200" text="Email" />
<TableColumn fx:id="secretCodeColumn" prefWidth="200" text="Secret Code" />
</columns>
</TableView>
<TextField fx:id="emailField" layoutX="397.0" layoutY="263.0" promptText="Email Id" />
<TextField fx:id="secretCodeField" layoutX="397.0" layoutY="311.0" promptText="Secret Key" />
</children>
</AnchorPane>

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.String?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListCell?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
<fx:root editable="false" focusTraversable="false" graphicTextGap="0.0" prefHeight="100.0" prefWidth="300.0" styleClass="email-cell" type="javafx.scene.control.ListCell" xmlns="http://javafx.com/javafx/23.0.1" xmlns:fx="http://javafx.com/fxml/1">
<graphic>
<AnchorPane id="email-cell-pane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="100.0" prefWidth="300.0" stylesheets="@../css/themeDefault.css" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<ImageView fitHeight="100.0" fitWidth="301.0" layoutX="-1.0" opacity="0.57" visible="false" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0">
<image>
<Image url="@../img/email-cell-template.png" />
</image>
</ImageView>
<Label id="email-cell-name" fx:id="sender" focusTraversable="false" layoutX="24.0" layoutY="11.0" prefHeight="17.0" prefWidth="177.0">
<styleClass>
<String fx:value="font-rockwell" />
<String fx:value="font-grey" />
</styleClass></Label>
<Label id="email-cell-date" fx:id="date" alignment="CENTER_RIGHT" focusTraversable="false" layoutX="222.0" layoutY="11.0" prefHeight="17.0" prefWidth="61.0">
<styleClass>
<String fx:value="font-rockwell" />
<String fx:value="font-grey" />
</styleClass></Label>
<Label id="email-cell-title" fx:id="title" focusTraversable="false" layoutX="24.0" layoutY="29.0" prefHeight="17.0" prefWidth="192.0">
<styleClass>
<String fx:value="font-rockwell" />
<String fx:value="font-bold" />
</styleClass></Label>
<TextArea id="email-cell-message" fx:id="message" editable="false" focusTraversable="false" layoutX="15.0" layoutY="48.0" mouseTransparent="true" prefHeight="43.0" prefWidth="219.0" wrapText="true">
<styleClass>
<String fx:value="font-rockwell" />
<String fx:value="font-grey" />
</styleClass></TextArea>
<ImageView id="email-cell-clip" fx:id="attachment" fitHeight="34.0" fitWidth="33.0" layoutX="257.0" layoutY="60.0" pickOnBounds="true" preserveRatio="true" visible="false" />
<Pane id="email-cell-focused" fx:id="selected" layoutY="-1.0" prefHeight="100.0" prefWidth="10.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="290.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</graphic>
</fx:root>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.String?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.Line?>
<AnchorPane id="login-pane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" stylesheets="@../css/themeDefault.css" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Button id="login-key" layoutX="116.0" layoutY="248.0" mnemonicParsing="false" onAction="#loginAction" prefHeight="95.0" prefWidth="367.0" styleClass="font-rockwell" text="Sign in" />
<Line endX="235.199951171875" endY="1.52587890625E-5" layoutX="301.0" layoutY="140.0" startX="-237.99996948242188" startY="1.52587890625E-5" strokeLineCap="ROUND" strokeWidth="2.0" />
<TextField fx:id="emailField" layoutX="119.0" layoutY="90.0" prefHeight="36.0" prefWidth="390.0">
<styleClass>
<String fx:value="font-rockwell" />
<String fx:value="login-field" />
</styleClass>
</TextField>
<PasswordField fx:id="passwordField" layoutX="119.0" layoutY="155.0" prefHeight="36.0" prefWidth="390.0">
<styleClass>
<String fx:value="font-rockwell" />
<String fx:value="font-bold" />
<String fx:value="login-field" />
</styleClass>
</PasswordField>
<ImageView id="login-email-icon" fitHeight="35.0" fitWidth="35.0" layoutX="69.0" layoutY="94.0" pickOnBounds="true" preserveRatio="true" />
<ImageView id="login-pass-icon" fitHeight="35.0" fitWidth="35.0" layoutX="69.0" layoutY="153.0" pickOnBounds="true" preserveRatio="true" />
</children>
</AnchorPane>

View File

@@ -0,0 +1,142 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.String?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TreeView?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Line?>
<?import javafx.scene.web.HTMLEditor?>
<?import javafx.scene.web.WebView?>
<AnchorPane id="main-window-pane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="674.0" prefWidth="1000.0" stylesheets="@../css/themeDefault.css" xmlns="http://javafx.com/javafx/23.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<ImageView fx:id="defaultMessageViewBG" fitHeight="376.0" fitWidth="376.0" layoutX="552.0" layoutY="149.0">
<image>
<Image url="@../img/EmailBackground-01.png" />
</image>
</ImageView>
<ImageView fitHeight="705.0" fitWidth="1000.0" layoutX="4.0" layoutY="-29.0" opacity="0.57" visible="false">
<image>
<Image url="@../img/EmailUIcompose.png" />
</image>
</ImageView>
<ImageView fitHeight="672.0" fitWidth="1200.0" layoutX="260.0" layoutY="287.0" visible="false" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0">
<image>
<Image url="@../img/EmailUI.png" />
</image>
</ImageView>
<AnchorPane id="message-pane" fx:id="messagePane" layoutX="492.0" layoutY="159.0" prefHeight="200.0" prefWidth="508.0" visible="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="492.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label fx:id="messageDate" alignment="TOP_RIGHT" layoutX="340.0" layoutY="14.0" prefHeight="17.0" prefWidth="139.0" AnchorPane.rightAnchor="29.0" AnchorPane.topAnchor="14.0">
<styleClass>
<String fx:value="font-rockwell" />
<String fx:value="font-grey" />
</styleClass>
</Label>
<Label id="message-title" fx:id="messageTitle" layoutX="17.0" layoutY="19.0" prefHeight="23.0" prefWidth="319.0" AnchorPane.leftAnchor="17.0" AnchorPane.topAnchor="19.0">
<styleClass>
<String fx:value="font-rockwell" />
<String fx:value="font-bold" />
</styleClass>
</Label>
<Label fx:id="messageSenderName" layoutX="17.0" layoutY="43.0" prefHeight="17.0" prefWidth="302.0" AnchorPane.leftAnchor="17.0" AnchorPane.topAnchor="43.0">
<styleClass>
<String fx:value="font-rockwell" />
<String fx:value="font-grey" />
</styleClass>
</Label>
<Button fx:id="decrypt" layoutX="230.0" layoutY="10.0" mnemonicParsing="false" prefHeight="26.0" prefWidth="78.0" text="Decrypt" onAction="#decryptEmail"/>
<Button id="key-trash" layoutX="-183.0" layoutY="-591.0" mnemonicParsing="false" onAction="#trashKeyAction" prefHeight="25.0" prefWidth="25.0" stylesheets="@../css/themeDefault.css" AnchorPane.rightAnchor="-603.0" AnchorPane.topAnchor="-591.0" />
<Button id="key-star" layoutX="-209.0" layoutY="-591.0" mnemonicParsing="false" onAction="#starKeyAction" prefHeight="25.0" prefWidth="25.0" stylesheets="@../css/themeDefault.css" AnchorPane.rightAnchor="-577.0" AnchorPane.topAnchor="-591.0" />
<Line endX="336.5999755859375" layoutX="126.0" layoutY="79.0" startX="-99.4000244140625" strokeLineCap="ROUND" strokeWidth="2.0" styleClass="line" AnchorPane.leftAnchor="26.0" AnchorPane.rightAnchor="44.0" AnchorPane.topAnchor="78.0" />
<WebView id="message-long-view" fx:id="messageViewLong" layoutX="9.0" layoutY="86.0" prefHeight="579.0" prefWidth="489.0" AnchorPane.bottomAnchor="9.0" AnchorPane.leftAnchor="9.0" AnchorPane.rightAnchor="9.0" AnchorPane.topAnchor="86.0" />
<WebView id="message-long-view" fx:id="messageViewShort" layoutX="9.0" layoutY="88.0" prefHeight="427.0" prefWidth="489.0" AnchorPane.bottomAnchor="159.0" AnchorPane.leftAnchor="9.0" AnchorPane.rightAnchor="9.0" AnchorPane.topAnchor="88.0" />
<Line fx:id="footerDiv" endX="336.5999755859375" layoutX="126.0" layoutY="548.0" startX="-99.4000244140625" strokeLineCap="ROUND" strokeWidth="2.0" styleClass="line" visible="false" AnchorPane.bottomAnchor="125.0" AnchorPane.leftAnchor="26.0" AnchorPane.rightAnchor="44.0" />
<Label id="attachments-label" fx:id="messageAttachmentLabel" layoutX="24.0" layoutY="523.0" prefHeight="17.0" prefWidth="116.0" text="ATTACHMENTS" visible="false" AnchorPane.bottomAnchor="134.0" AnchorPane.leftAnchor="24.0">
<styleClass>
<String fx:value="font-rockwell" />
<String fx:value="font-grey" />
</styleClass>
</Label>
<ListView id="attachment-list" fx:id="attachmentList" layoutY="555.0" orientation="HORIZONTAL" prefHeight="111.0" prefWidth="508.0" visible="false" AnchorPane.bottomAnchor="8.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" />
</children>
</AnchorPane>
<AnchorPane id="composer-pane" fx:id="composePane" layoutX="492.0" layoutY="159.0" prefHeight="200.0" prefWidth="508.0" visible="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="492.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<HTMLEditor id="editor" fx:id="htmlEditor" htmlText="&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body contenteditable=&quot;true&quot;&gt;&lt;/body&gt;&lt;/html&gt;" layoutY="86.0" prefHeight="518.0" prefWidth="508.0" AnchorPane.bottomAnchor="70.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="86.0" />
<TextField id="field-send-to" fx:id="composeTo" layoutX="20.0" layoutY="13.0" prefHeight="26.0" prefWidth="469.0" promptText="to:" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="13.0">
<styleClass>
<String fx:value="font-rockwell" />
<String fx:value="font-grey" />
</styleClass></TextField>
<TextField id="field-title" fx:id="composeTitle" layoutX="20.0" layoutY="50.0" prefHeight="26.0" prefWidth="469.0" promptText="title:" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="50.0">
<styleClass>
<String fx:value="font-rockwell" />
<String fx:value="font-grey" />
</styleClass></TextField>
<ImageView fitHeight="41.0" fitWidth="148.0" layoutX="340.0" layoutY="619.0" AnchorPane.bottomAnchor="14.0" AnchorPane.rightAnchor="20.0">
<image>
<Image url="@../img/default/idle/composer-tools-box.png" />
</image>
</ImageView>
<Button id="send-key" layoutX="245.00000000000006" layoutY="428.00000000000006" mnemonicParsing="false" onAction="#composeSendPressed" prefHeight="45.0" prefWidth="45.0" stylesheets="@../css/themeDefault.css" AnchorPane.bottomAnchor="-179.20000000000005" AnchorPane.rightAnchor="-170.20000000000005" />
<Button id="attach-key" layoutX="183.00000000000006" layoutY="427.00000000000006" mnemonicParsing="false" onAction="#addAttachment" prefHeight="30.0" prefWidth="30.0" stylesheets="@../css/themeDefault.css" AnchorPane.bottomAnchor="-178.20000000000005" AnchorPane.rightAnchor="-108.20000000000005" />
<Button id="compose-cancel-key" layoutX="148.00000000000006" layoutY="427.00000000000006" mnemonicParsing="false" onAction="#composeCancel" prefHeight="30.0" prefWidth="30.0" stylesheets="@../css/themeDefault.css" AnchorPane.bottomAnchor="-178.20000000000005" AnchorPane.rightAnchor="-73.20000000000005" />
<ImageView id="compose-attached-icon" fx:id="composeAttachIcon" fitHeight="45.0" fitWidth="45.0" layoutX="10.0" layoutY="614.0" pickOnBounds="true" preserveRatio="true" visible="false" AnchorPane.bottomAnchor="15.0" AnchorPane.leftAnchor="10.0" />
<Line fx:id="footerDiv1" endX="336.5999755859375" layoutX="135.0" layoutY="604.0" startX="-99.4000244140625" strokeLineCap="ROUND" strokeWidth="2.0" styleClass="line" AnchorPane.bottomAnchor="69.0" AnchorPane.rightAnchor="35.0" />
</children>
</AnchorPane>
<AnchorPane id="account-pane" layoutY="474.0" prefHeight="70.0" prefWidth="190.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0">
<children>
<Label fx:id="userNameLabel" layoutX="8.0" layoutY="14.0" prefHeight="17.0" prefWidth="165.0">
<styleClass>
<String fx:value="font-rockwell" />
<String fx:value="font-bold" />
<String fx:value="font-white" />
</styleClass>
</Label>
</children>
</AnchorPane>
<AnchorPane>
</AnchorPane>
<AnchorPane id="settings-pane" layoutX="-13.0" layoutY="-1.0" minHeight="-Infinity" minWidth="-Infinity" prefHeight="32.0" prefWidth="492.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<TextField id="search-bar" focusTraversable="false" layoutX="226.0" layoutY="3.0" prefHeight="25.0" prefWidth="232.0">
<padding>
<Insets left="20.0" />
</padding></TextField>
<Button id="settings-key" layoutX="462.0" layoutY="9.0" mnemonicParsing="false" prefHeight="390.0" prefWidth="0.0" />
<ImageView fitHeight="14.0" fitWidth="14.0" layoutX="230.0" layoutY="9.0">
<image>
<Image url="@../img/default/idle/search-icon.png" />
</image>
</ImageView>
<VBox prefHeight="200.0" prefWidth="100.0" />
</children></AnchorPane>
<TreeView id="folder-view" fx:id="folderSelection" layoutY="113.0" prefHeight="491.0" prefWidth="190.0" AnchorPane.bottomAnchor="70.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="113.0">
<styleClass>
<String fx:value="font-myriad" />
<String fx:value="font-white" />
</styleClass></TreeView>
<ListView id="email-cell-view" fx:id="emailSelection" focusTraversable="false" layoutX="190.0" prefHeight="674.0" prefWidth="302.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="190.0" AnchorPane.topAnchor="30.0" />
<Pane id="compose-key-pane" layoutY="30.0" prefHeight="84.0" prefWidth="190.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="30.0">
<children>
<Button id="compose-key" layoutX="23.0" layoutY="23.0" mnemonicParsing="false" onAction="#composeKeyPressed" prefHeight="38.0" prefWidth="139.0" text="COMPOSE">
<styleClass>
<String fx:value="font-rockwell" />
<String fx:value="font-bold" />
<String fx:value="font-white" />
</styleClass></Button>
</children>
</Pane>
<Button layoutX="62.0" layoutY="512.0" mnemonicParsing="false" onAction="#openCRUDWindow" opacity="0.72" text="Enter Key" textFill="#373d04" />
</children>
</AnchorPane>

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 835 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -0,0 +1,38 @@
package com.secure_mailer;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}
/**
* @return the suite of tests being tested
*/
public static Test suite()
{
return new TestSuite( AppTest.class );
}
/**
* Rigourous Test :-)
*/
public void testApp()
{
assertTrue( true );
}
}