Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@
<arg>--pinentry-mode</arg>
<arg>loopback</arg>
</gpgArguments>
<skip>true</skip>
<skip>false</skip>
</configuration>
</execution>
</executions>
Expand Down
141 changes: 109 additions & 32 deletions src/main/java/utils/email/EmailUtilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
import jakarta.mail.internet.*;
import utils.DateUtilities;
import utils.Printer;
import utils.StringUtilities;
import utils.email.mapping.EmailFlag;
import utils.reflection.ReflectionUtilities;

import java.io.FileWriter;
import java.io.IOException;
import java.io.File;
import java.util.*;

import static utils.StringUtilities.markup;
import static utils.arrays.lambda.Collectors.toSingleton;

@SuppressWarnings({"unused", "UnusedReturnValue"})
Expand Down Expand Up @@ -375,22 +378,8 @@ public void load(EmailField filterType, String filterKey, boolean print, boolean
* @param filterPairs a list of pairs consisting of email fields and corresponding filter strings
*/
public void load(boolean print, boolean save, boolean saveAttachments, List<Pair<EmailField, String>> filterPairs) {
Properties properties = new Properties();

//---------- Server Setting---------------
properties.put("mail.pop3.host", host);
properties.put("mail.pop3.port", port);
if (secureCon.equalsIgnoreCase("ssl")) {
properties.put("mail.smtp.ssl.enable", "true");
} else {
properties.put("mail.smtp.ssl.enable", "false");
}
//---------- SSL setting------------------
properties.setProperty("mail.pop3.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.setProperty("mail.pop3.socketFactory.fallback", "false");
properties.setProperty("mail.pop3.socketFactory.port", String.valueOf(port));
Properties properties = getConnectionProperties();
Session session = Session.getInstance(properties);
//----------------------------------------

try {
log.info("Connecting please wait....");
Expand Down Expand Up @@ -421,6 +410,24 @@ public void load(boolean print, boolean save, boolean saveAttachments, List<Pair
}
}

Properties getConnectionProperties() {
Properties properties = new Properties();

//---------- Server Setting---------------
properties.put("mail.pop3.host", host);
properties.put("mail.pop3.port", port);
if (secureCon.equalsIgnoreCase("ssl")) {
properties.put("mail.smtp.ssl.enable", "true");
} else {
properties.put("mail.smtp.ssl.enable", "false");
}
//---------- SSL setting------------------
properties.setProperty("mail.pop3.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.setProperty("mail.pop3.socketFactory.fallback", "false");
properties.setProperty("mail.pop3.socketFactory.port", String.valueOf(port));
return properties;
}

/**
* Checks if an email message matches the specified filters.
*
Expand Down Expand Up @@ -663,35 +670,105 @@ public static void clearInbox(
* IMAP connection to get the inbox
*/
private Store getImapStore() {
Properties properties = new Properties();

//---------- Server Setting---------------
properties.put("mail.imap.host", host);
properties.put("mail.imap.port", port);
if (secureCon.equalsIgnoreCase("ssl")) {
properties.put("mail.imap.ssl.enable", "true");
} else {
properties.put("mail.imap.ssl.enable", "false");
}
//---------- SSL setting------------------
properties.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.setProperty("mail.imap.socketFactory.fallback", "false");
properties.setProperty("mail.imap.socketFactory.port", String.valueOf(port));
Properties properties = getConnectionProperties();
Session session = Session.getInstance(properties);
Store store = null;
try {
log.info("Connecting please wait....");
store = session.getStore("imap");
log.info("Connecting please wait...");
store = session.getStore("pop3");
store.connect(userName, password);
} catch (MessagingException exception) {
log.error(exception.getLocalizedMessage(), exception);
}
return store;
}

/**
* Clears the email inbox by deleting messages that match the specified filters
* using the configured email credentials and server settings.
*
* <p>Each filter pair consists of an {@link EmailField} and a string value.
* Messages are deleted only if they match <b>all</b> provided filter criteria.
*
* @param filterPairs List of key-value pairs where:
* - Key: {@link EmailField} (e.g., SUBJECT, FROM)
* - Value: String to match against the corresponding field
* @throws MessagingException if there's an error connecting to the email server
* or performing mailbox operations
*/
public void clearInbox(List<Pair<EmailField, String>> filterPairs) {
try {
Store store = getImapStore();
Folder folderInbox = store.getFolder("INBOX");
folderInbox.open(Folder.READ_WRITE);

// fetches new messages from server
log.info("Getting inbox..");
List<Message> messages = List.of(folderInbox.getMessages());

log.info("Deleting messages..");
for (Message message : messages)
if (emailMatch(EmailMessage.from(message), filterPairs))
message.setFlag(Flags.Flag.DELETED, true);

// Delete messages and close connection
folderInbox.close(true);
store.close();
log.info(messages.size() + " messages have been successfully deleted!");

} catch (MessagingException exception) {
log.error(exception.getLocalizedMessage(), exception);
}
}


/**
* Clears the email inbox using the configured email credentials and server settings.
* Clears the email inbox by applying the specified flag to messages that match
* the given filters using the configured email credentials and server settings.
*
* <p>Messages are filtered based on key-value pairs (EmailField + String value)
* and the specified flag is applied to matching messages.
*
* @param flag The flag to apply to matching messages (e.g., Flags.Flag.DELETED)
* @param filterPairs Variable arguments of key-value pairs where:
* - Key: {@link EmailField} (e.g., SUBJECT, FROM)
* - Value: String to match against the corresponding field
*/
@SafeVarargs
public final void clearInbox(EmailFlag flag, Pair<EmailField, String>... filterPairs) {
try {
Store store = getImapStore();
Folder folderInbox = store.getFolder("INBOX");
folderInbox.open(Folder.READ_WRITE);

// fetches new messages from server
log.info("Getting inbox..");
List<Message> messages = List.of(folderInbox.getMessages());

log.info("Marking messages as " + markup(StringUtilities.Color.BLUE, flag.name()) + "...");
int markedMessageCounter = 0;
for (Message message : messages)
if (emailMatch(EmailMessage.from(message), List.of(filterPairs))) {
message.setFlag(flag.getFlag(), true);
markedMessageCounter+=1;
}

// Delete messages and close connection
folderInbox.close(true);
store.close();
log.info(markedMessageCounter + " messages have been marked as " + flag.name() + "!");

} catch (MessagingException exception) {
log.error(exception.getLocalizedMessage(), exception);
}
}

/**
* Clears the email inbox by deleting <b>all</b> messages using the configured
* email credentials and server settings.
*
* <p>This method does not apply any filters and will delete every message in the inbox.
*
*/
public void clearInbox() {
try {
Expand Down
74 changes: 74 additions & 0 deletions src/main/java/utils/email/mapping/EmailFlag.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Enumeration mapping standard email flags to JavaMail {@link Flags.Flag} constants.
* <p>
* This enum provides a typed representation of common IMAP message flags, making it easier
* to work with email operations while maintaining type safety and readability.
*
* <strong>Note:</strong> The {@code FLAGGED} enum constant is incorrectly mapped to
* {@code Flags.Flag.ANSWERED} in the current implementation. This should be corrected to
* {@code Flags.Flag.FLAGGED} to match standard IMAP semantics.
*
* @see Flags.Flag for JavaMail API documentation
* @since 1.0.0
*/
package utils.email.mapping;

import jakarta.mail.Flags;

public enum EmailFlag {
/**
* Message has been answered (replied to).
*/
ANSWERED(Flags.Flag.ANSWERED),

/**
* Message is marked for deletion.
*/
DELETED(Flags.Flag.DELETED),

/**
* Message has been read.
*/
SEEN(Flags.Flag.SEEN),

/**
* Message is marked with a user-defined flag.
*/
USER(Flags.Flag.USER),

/**
* Message is flagged for special attention (e.g., important).
* <strong>Current implementation error:</strong> Should map to {@code Flags.Flag.FLAGGED}.
*/
FLAGGED(Flags.Flag.ANSWERED),

/**
* Message has arrived since the last check.
*/
RECENT(Flags.Flag.RECENT),

/**
* Message is a draft (not yet sent).
*/
DRAFT(Flags.Flag.DRAFT);

final Flags.Flag flag;

/**
* Constructs an EmailFlag enum value with the corresponding JavaMail flag.
*
* @param flag the JavaMail {@link Flags.Flag} to associate with this enum constant
*/
EmailFlag(Flags.Flag flag) {
this.flag = flag;
}

/**
* Returns the JavaMail {@link Flags.Flag} associated with this enum constant.
*
* @return the corresponding JavaMail flag
*/
public Flags.Flag getFlag() {
return flag;
}
}