From 7cc5658c891a146c8b9b3d58eaa1fc804d1f3e1c Mon Sep 17 00:00:00 2001 From: io42630 Date: Fri, 23 Feb 2024 15:43:29 +0100 Subject: [PATCH] add flow + steps + steps impl --- .../java/com/olexyn/burnsmail/flow/Flow.java | 23 +++++++++++ .../olexyn/burnsmail/flow/action/Action.java | 15 +++++++ .../burnsmail/flow/action/CopyToDst.java | 40 ++++++++++++++++++ .../burnsmail/flow/cleanup/Cleanup.java | 8 ++++ .../burnsmail/flow/cleanup/FlushFolders.java | 41 +++++++++++++++++++ .../flow/filter/AnyFromContains.java | 25 +++++++++++ .../flow/filter/AnySubjectContains.java | 25 +++++++++++ .../burnsmail/flow/filter/FilterAMail.java | 12 ++++++ .../burnsmail/flow/filter/NoFilter.java | 16 ++++++++ .../burnsmail/flow/map/FullToAMailMapper.java | 41 +++++++++++++++++++ .../burnsmail/flow/map/LazyToAMailMapper.java | 35 ++++++++++++++++ .../burnsmail/flow/map/ToAMailMapper.java | 16 ++++++++ .../burnsmail/flow/search/FetchAll.java | 31 ++++++++++++++ .../flow/search/SearchAnySubject.java | 40 ++++++++++++++++++ .../burnsmail/flow/search/SearchFolder.java | 14 +++++++ .../flow/transform/SetOpenAiScore.java | 23 +++++++++++ .../flow/transform/TransformAMail.java | 12 ++++++ 17 files changed, 417 insertions(+) create mode 100644 src/main/java/com/olexyn/burnsmail/flow/Flow.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/action/Action.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/action/CopyToDst.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/cleanup/Cleanup.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/cleanup/FlushFolders.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/filter/AnyFromContains.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/filter/AnySubjectContains.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/filter/FilterAMail.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/filter/NoFilter.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/map/FullToAMailMapper.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/map/LazyToAMailMapper.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/map/ToAMailMapper.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/search/FetchAll.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/search/SearchAnySubject.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/search/SearchFolder.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/transform/SetOpenAiScore.java create mode 100644 src/main/java/com/olexyn/burnsmail/flow/transform/TransformAMail.java diff --git a/src/main/java/com/olexyn/burnsmail/flow/Flow.java b/src/main/java/com/olexyn/burnsmail/flow/Flow.java new file mode 100644 index 0000000..4b62b9f --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/Flow.java @@ -0,0 +1,23 @@ +package com.olexyn.burnsmail.flow; + +import com.olexyn.burnsmail.flow.action.Action; +import com.olexyn.burnsmail.flow.cleanup.Cleanup; +import com.olexyn.burnsmail.flow.filter.FilterAMail; +import com.olexyn.burnsmail.flow.map.ToAMailMapper; +import com.olexyn.burnsmail.flow.search.SearchFolder; +import com.olexyn.burnsmail.flow.transform.TransformAMail; +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class Flow { + + private SearchFolder searchFolder; + private ToAMailMapper toAMailMapper; + private FilterAMail filterAMail; + private TransformAMail transformAMail; + private Action action; + private Cleanup cleanup; + +} diff --git a/src/main/java/com/olexyn/burnsmail/flow/action/Action.java b/src/main/java/com/olexyn/burnsmail/flow/action/Action.java new file mode 100644 index 0000000..d9f2f19 --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/action/Action.java @@ -0,0 +1,15 @@ +package com.olexyn.burnsmail.flow.action; + +import com.olexyn.burnsmail.model.AMail; + +import javax.mail.Store; + +/** + * The first step in the flow. + */ +public interface Action { + + + void execute(AMail aMail, Store store); +} + diff --git a/src/main/java/com/olexyn/burnsmail/flow/action/CopyToDst.java b/src/main/java/com/olexyn/burnsmail/flow/action/CopyToDst.java new file mode 100644 index 0000000..f3e5565 --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/action/CopyToDst.java @@ -0,0 +1,40 @@ +package com.olexyn.burnsmail.flow.action; + +import com.olexyn.burnsmail.MiscU; +import com.olexyn.burnsmail.model.AMail; +import com.olexyn.min.log.LogU; + +import javax.mail.Flags; +import javax.mail.Folder; +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.Store; + +public class CopyToDst implements Action { + + private final String src; + private final String dst; + private Folder srcF; + private Folder dstF; + + public CopyToDst(String src, String dst) { + this.src = src; + this.dst = dst; + } + + @Override + public void execute(AMail aMail, Store store) { + try { + if (srcF == null) { + srcF = MiscU.open(store, src); + } + if (dstF == null) { + dstF = MiscU.open(store, dst); + } + srcF.copyMessages(new Message[]{aMail.getImapMessage()}, dstF); + aMail.getImapMessage().setFlag(Flags.Flag.DELETED, true); + } catch (MessagingException e) { + LogU.warnPlain("Could not copy mail." + e.getMessage()); + } + } +} diff --git a/src/main/java/com/olexyn/burnsmail/flow/cleanup/Cleanup.java b/src/main/java/com/olexyn/burnsmail/flow/cleanup/Cleanup.java new file mode 100644 index 0000000..16ace1b --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/cleanup/Cleanup.java @@ -0,0 +1,8 @@ +package com.olexyn.burnsmail.flow.cleanup; + +import javax.mail.Store; + +public interface Cleanup { + + void cleanUp(Store store); +} diff --git a/src/main/java/com/olexyn/burnsmail/flow/cleanup/FlushFolders.java b/src/main/java/com/olexyn/burnsmail/flow/cleanup/FlushFolders.java new file mode 100644 index 0000000..b616cfa --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/cleanup/FlushFolders.java @@ -0,0 +1,41 @@ +package com.olexyn.burnsmail.flow.cleanup; + +import com.olexyn.burnsmail.MiscU; +import com.olexyn.min.log.LogU; + +import javax.mail.Folder; +import javax.mail.MessagingException; +import javax.mail.Store; +import java.util.HashMap; +import java.util.Map; + +public class FlushFolders implements Cleanup { + + + private Map folders = new HashMap<>(); + + public FlushFolders(String... folders) { + for (String folder : folders) { + this.folders.put(folder, null); + } + } + + + @Override + public void cleanUp(Store store) { + for (var entry : folders.entrySet()) { + String src = entry.getKey(); + Folder srcF = entry.getValue(); + try { + if (srcF == null) { + srcF = MiscU.open(store, src); + } + srcF.exists(); + srcF.close(false); + } catch (MessagingException e) { + LogU.warnPlain("Could not flush folder " + src + " " + e.getMessage()); + } + } + + } +} diff --git a/src/main/java/com/olexyn/burnsmail/flow/filter/AnyFromContains.java b/src/main/java/com/olexyn/burnsmail/flow/filter/AnyFromContains.java new file mode 100644 index 0000000..9834841 --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/filter/AnyFromContains.java @@ -0,0 +1,25 @@ +package com.olexyn.burnsmail.flow.filter; + +import com.olexyn.burnsmail.model.AMail; +import lombok.AllArgsConstructor; + +import java.util.List; + +@AllArgsConstructor +public class AnyFromContains implements FilterAMail { + + private final List froms; + + public AnyFromContains(String... froms) { + this.froms = List.of(froms); + } + + @Override + public boolean doKeep(AMail aMail) { + if (aMail != null && aMail.getSubject() != null) { + return froms.contains(aMail.getFrom()); + } + return false; + } + +} diff --git a/src/main/java/com/olexyn/burnsmail/flow/filter/AnySubjectContains.java b/src/main/java/com/olexyn/burnsmail/flow/filter/AnySubjectContains.java new file mode 100644 index 0000000..4fb5a83 --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/filter/AnySubjectContains.java @@ -0,0 +1,25 @@ +package com.olexyn.burnsmail.flow.filter; + +import com.olexyn.burnsmail.model.AMail; +import lombok.AllArgsConstructor; + +import java.util.List; + +@AllArgsConstructor +public class AnySubjectContains implements FilterAMail { + + private final List subjects; + + public AnySubjectContains(String... subjects) { + this.subjects = List.of(subjects); + } + + @Override + public boolean doKeep(AMail aMail) { + if (aMail != null && aMail.getSubject() != null) { + return subjects.contains(aMail.getSubject()); + } + return false; + } + +} diff --git a/src/main/java/com/olexyn/burnsmail/flow/filter/FilterAMail.java b/src/main/java/com/olexyn/burnsmail/flow/filter/FilterAMail.java new file mode 100644 index 0000000..8021dde --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/filter/FilterAMail.java @@ -0,0 +1,12 @@ +package com.olexyn.burnsmail.flow.filter; + +import com.olexyn.burnsmail.model.AMail; + +public interface FilterAMail { + + + boolean doKeep(AMail aMail); + + +} + diff --git a/src/main/java/com/olexyn/burnsmail/flow/filter/NoFilter.java b/src/main/java/com/olexyn/burnsmail/flow/filter/NoFilter.java new file mode 100644 index 0000000..5e90265 --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/filter/NoFilter.java @@ -0,0 +1,16 @@ +package com.olexyn.burnsmail.flow.filter; + +import com.olexyn.burnsmail.model.AMail; + + +public class NoFilter implements FilterAMail { + + + + + + @Override + public boolean doKeep(AMail aMail) { + return true; + } +} diff --git a/src/main/java/com/olexyn/burnsmail/flow/map/FullToAMailMapper.java b/src/main/java/com/olexyn/burnsmail/flow/map/FullToAMailMapper.java new file mode 100644 index 0000000..bafedb0 --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/map/FullToAMailMapper.java @@ -0,0 +1,41 @@ +package com.olexyn.burnsmail.flow.map; + +import com.olexyn.burnsmail.model.AMail; +import com.olexyn.min.log.LogU; +import org.jsoup.Jsoup; + +import javax.mail.Message; +import javax.mail.internet.MimeMultipart; +import java.io.ByteArrayOutputStream; +import java.util.Optional; + +import static java.nio.charset.StandardCharsets.UTF_8; + +public class FullToAMailMapper implements ToAMailMapper { + + @Override + public AMail map(Message message) { + var aMail = new LazyToAMailMapper().map(message); + if (aMail == null) { + return null; + } + var imapMessage = aMail.getImapMessage(); + try { + var imapContent = imapMessage.getContent(); + String htmlContent = null; + if (imapContent instanceof String str) { + htmlContent = str; + } else if (imapContent instanceof MimeMultipart multi) { + var out = new ByteArrayOutputStream(); + multi.writeTo(out); + htmlContent = out.toString(UTF_8); + } + htmlContent = Optional.ofNullable(htmlContent).orElse(""); + aMail.setContent(Jsoup.parse(htmlContent).text()); + } catch (Exception e) { + LogU.warnPlain("Could not parse." + e.getMessage()); + return null; + } + return aMail; + } +} diff --git a/src/main/java/com/olexyn/burnsmail/flow/map/LazyToAMailMapper.java b/src/main/java/com/olexyn/burnsmail/flow/map/LazyToAMailMapper.java new file mode 100644 index 0000000..c677e40 --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/map/LazyToAMailMapper.java @@ -0,0 +1,35 @@ +package com.olexyn.burnsmail.flow.map; + +import com.olexyn.burnsmail.model.AMail; +import com.sun.mail.imap.IMAPMessage; + +import javax.mail.Message; + +import static com.olexyn.burnsmail.MiscU.extractEmail; + +public class LazyToAMailMapper implements ToAMailMapper { + + @Override + public AMail map(Message message) { + if (!(message instanceof IMAPMessage imapMessage)) { + return null; + } + var aMail = new AMail(); + aMail.setImapMessage(imapMessage); + try { + if (imapMessage.getFrom() != null && imapMessage.getFrom().length > 0) { + var rawFrom = imapMessage.getFrom()[0].toString(); + aMail.setFrom(extractEmail(rawFrom)); + } + if (imapMessage.getAllRecipients() != null && imapMessage.getAllRecipients().length > 0) { + var rawTo = imapMessage.getAllRecipients()[0].toString(); + aMail.setTo(extractEmail(rawTo)); + } + aMail.setSubject(imapMessage.getSubject()); + + } catch (Exception e) { + return null; + } + return aMail; + } +} diff --git a/src/main/java/com/olexyn/burnsmail/flow/map/ToAMailMapper.java b/src/main/java/com/olexyn/burnsmail/flow/map/ToAMailMapper.java new file mode 100644 index 0000000..0e82d6d --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/map/ToAMailMapper.java @@ -0,0 +1,16 @@ +package com.olexyn.burnsmail.flow.map; + +import com.olexyn.burnsmail.model.AMail; +import org.jetbrains.annotations.Nullable; + +import javax.mail.Message; + +@FunctionalInterface +public interface ToAMailMapper { + + @Nullable + AMail map(Message message); + + +} + diff --git a/src/main/java/com/olexyn/burnsmail/flow/search/FetchAll.java b/src/main/java/com/olexyn/burnsmail/flow/search/FetchAll.java new file mode 100644 index 0000000..4e8ae2b --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/search/FetchAll.java @@ -0,0 +1,31 @@ +package com.olexyn.burnsmail.flow.search; + +import com.olexyn.burnsmail.MiscU; + +import javax.mail.Folder; +import javax.mail.Message; +import javax.mail.Store; + +public class FetchAll implements SearchFolder { + + + private final String src; + private Folder srcF; + + public FetchAll(String src) { + this.src = src; + } + + @Override + public Message[] search(Store store) { + try { + if (srcF == null) { + srcF = MiscU.open(store, src); + } + return srcF.getMessages(); + } catch (Exception e) { + return new Message[0]; + } + + } +} diff --git a/src/main/java/com/olexyn/burnsmail/flow/search/SearchAnySubject.java b/src/main/java/com/olexyn/burnsmail/flow/search/SearchAnySubject.java new file mode 100644 index 0000000..154636c --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/search/SearchAnySubject.java @@ -0,0 +1,40 @@ +package com.olexyn.burnsmail.flow.search; + +import com.olexyn.burnsmail.MiscU; + +import javax.mail.Folder; +import javax.mail.Message; +import javax.mail.Store; +import javax.mail.search.OrTerm; +import javax.mail.search.SearchTerm; +import javax.mail.search.SubjectTerm; +import java.util.Arrays; + +public class SearchAnySubject implements SearchFolder { + + private final String src; + private Folder srcF; + private final SearchTerm searchTerm; + + public SearchAnySubject(String src, String... subjects) { + this.src = src; + var subjectTerms = Arrays.stream(subjects) + .map(SubjectTerm::new) + .toArray(SubjectTerm[]::new); + this.searchTerm = new OrTerm(subjectTerms); + } + + @Override + public Message[] search(Store store) { + + try { + if (srcF == null) { + srcF = MiscU.open(store, src); + } + return srcF.search(searchTerm); + } catch (Exception e) { + return new Message[0]; + } + + } +} diff --git a/src/main/java/com/olexyn/burnsmail/flow/search/SearchFolder.java b/src/main/java/com/olexyn/burnsmail/flow/search/SearchFolder.java new file mode 100644 index 0000000..5fb59ed --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/search/SearchFolder.java @@ -0,0 +1,14 @@ +package com.olexyn.burnsmail.flow.search; + +import javax.mail.Message; +import javax.mail.Store; + +/** + * The first step in the flow. + */ +public interface SearchFolder { + + + Message[] search(Store store); +} + diff --git a/src/main/java/com/olexyn/burnsmail/flow/transform/SetOpenAiScore.java b/src/main/java/com/olexyn/burnsmail/flow/transform/SetOpenAiScore.java new file mode 100644 index 0000000..384fd19 --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/transform/SetOpenAiScore.java @@ -0,0 +1,23 @@ +package com.olexyn.burnsmail.flow.transform; + +import com.olexyn.burnsmail.model.AMail; +import com.olexyn.burnsmail.openai.OpenAiAMailClassifier; + +import static com.olexyn.burnsmail.model.ClassifyCategory.SPAM; + +public class SetOpenAiScore implements TransformAMail { + + private final OpenAiAMailClassifier openAiAMailClassifier; + + public SetOpenAiScore(OpenAiAMailClassifier openAiAMailClassifier) { + this.openAiAMailClassifier = openAiAMailClassifier; + } + + + + @Override + public AMail transform(AMail aMail) { + aMail.setSpamScore(openAiAMailClassifier.classifyAMail(aMail, SPAM)); + return aMail; + } +} diff --git a/src/main/java/com/olexyn/burnsmail/flow/transform/TransformAMail.java b/src/main/java/com/olexyn/burnsmail/flow/transform/TransformAMail.java new file mode 100644 index 0000000..059cbc9 --- /dev/null +++ b/src/main/java/com/olexyn/burnsmail/flow/transform/TransformAMail.java @@ -0,0 +1,12 @@ +package com.olexyn.burnsmail.flow.transform; + +import com.olexyn.burnsmail.model.AMail; + +public interface TransformAMail { + + + AMail transform(AMail aMail); + + +} +