final implementation
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.classpath
|
||||||
|
/.metadata/
|
||||||
|
.project
|
||||||
|
/.settings/
|
||||||
|
/target/
|
||||||
157
pom.xml
Normal 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>
|
||||||
19
src/main/java/com/secure_mailer/App.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/main/java/com/secure_mailer/backend/BaseController.java
Normal 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; }
|
||||||
|
}
|
||||||
37
src/main/java/com/secure_mailer/backend/DatabaseSetup.java
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
52
src/main/java/com/secure_mailer/backend/EmailAccount.java
Normal 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;}
|
||||||
|
}
|
||||||
36
src/main/java/com/secure_mailer/backend/EmailManager.java
Normal 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; }
|
||||||
|
|
||||||
|
}
|
||||||
30
src/main/java/com/secure_mailer/backend/EmailSecretCode.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/main/java/com/secure_mailer/backend/LoginController.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
73
src/main/java/com/secure_mailer/backend/SecretCodeDAO.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
260
src/main/java/com/secure_mailer/backend/ValidatorClient.java
Normal 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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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("\\ ", " ");
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
50
src/main/java/com/secure_mailer/frontend/Attachment.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
74
src/main/java/com/secure_mailer/frontend/AttachmentCell.java
Normal 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()); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
89
src/main/java/com/secure_mailer/frontend/EmailCell.java
Normal 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); }
|
||||||
|
}
|
||||||
122
src/main/java/com/secure_mailer/frontend/EmailMessage.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
62
src/main/java/com/secure_mailer/frontend/FolderTreeItem.java
Normal 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); }
|
||||||
|
}
|
||||||
32
src/main/java/com/secure_mailer/frontend/IconResolver.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
70
src/main/java/com/secure_mailer/frontend/ViewGenerator.java
Normal 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(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
320
src/main/resources/css/themeDefault.css
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
BIN
src/main/resources/font/Myriad_Pro_Light_SemiCondensed.otf
Normal file
BIN
src/main/resources/font/Myriad_Pro_Regular.ttf
Normal file
22
src/main/resources/fxml/attachment_cell.fxml
Normal 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>
|
||||||
37
src/main/resources/fxml/crud_window.fxml
Normal 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>
|
||||||
46
src/main/resources/fxml/email_cell.fxml
Normal 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>
|
||||||
32
src/main/resources/fxml/login.fxml
Normal 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>
|
||||||
142
src/main/resources/fxml/main.fxml
Normal 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="<html><head></head><body contenteditable="true"></body></html>" 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>
|
||||||
BIN
src/main/resources/img/EmailBackground-01.png
Normal file
|
After Width: | Height: | Size: 238 KiB |
BIN
src/main/resources/img/EmailUI.png
Normal file
|
After Width: | Height: | Size: 624 KiB |
BIN
src/main/resources/img/EmailUIcompose.png
Normal file
|
After Width: | Height: | Size: 835 KiB |
BIN
src/main/resources/img/LoginUI.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
src/main/resources/img/default/email-client.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
src/main/resources/img/default/hover/at.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
src/main/resources/img/default/hover/attach-message.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src/main/resources/img/default/hover/cancel-message.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
src/main/resources/img/default/hover/compose-key.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
src/main/resources/img/default/hover/composer-field.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/main/resources/img/default/hover/draft.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
src/main/resources/img/default/hover/flag.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/main/resources/img/default/hover/inbox.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
src/main/resources/img/default/hover/login-key.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/main/resources/img/default/hover/mail.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
src/main/resources/img/default/hover/search-bar.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src/main/resources/img/default/hover/send-message.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
src/main/resources/img/default/hover/sent.png
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
src/main/resources/img/default/hover/settings.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/main/resources/img/default/hover/spam.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
src/main/resources/img/default/hover/star-folder.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
src/main/resources/img/default/hover/star.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
src/main/resources/img/default/hover/trash-folder.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
src/main/resources/img/default/hover/trash.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
src/main/resources/img/default/idle/at.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
src/main/resources/img/default/idle/attach-message.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src/main/resources/img/default/idle/attached-message.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
src/main/resources/img/default/idle/cancel-message.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
src/main/resources/img/default/idle/compose-key.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
src/main/resources/img/default/idle/composer-field.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/main/resources/img/default/idle/composer-tools-box.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
src/main/resources/img/default/idle/draft.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
src/main/resources/img/default/idle/email-cell-clip.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
src/main/resources/img/default/idle/flag.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/main/resources/img/default/idle/inbox.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
src/main/resources/img/default/idle/login-email-icon.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
src/main/resources/img/default/idle/login-key.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/main/resources/img/default/idle/login-pass-icon.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
src/main/resources/img/default/idle/mail.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
src/main/resources/img/default/idle/paper-clip.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
src/main/resources/img/default/idle/search-bar.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src/main/resources/img/default/idle/search-icon.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
src/main/resources/img/default/idle/send-message.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
src/main/resources/img/default/idle/sent.png
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
src/main/resources/img/default/idle/settings.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src/main/resources/img/default/idle/spam.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
src/main/resources/img/default/idle/star-folder.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
src/main/resources/img/default/idle/star.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
src/main/resources/img/default/idle/trash-folder.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
src/main/resources/img/default/idle/trash.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
src/main/resources/img/email-cell-template.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
38
src/test/java/com/secure_mailer/AppTest.java
Normal 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 );
|
||||||
|
}
|
||||||
|
}
|
||||||