feat: aso add label for ai processed

This commit is contained in:
2025-11-12 14:05:03 +01:00
parent 56c9f764fc
commit 6de059dca7
3 changed files with 243 additions and 2 deletions

View File

@@ -18,6 +18,9 @@ import (
"github.com/sirupsen/logrus"
)
// Custom IMAP flag to mark emails as AI-processed
const AIProcessedFlag = "$AIProcessed"
type IMAPClient struct {
client *client.Client
config config.IMAPConfig
@@ -137,9 +140,9 @@ func (ic *IMAPClient) FetchUnprocessedEmails() ([]Email, error) {
return nil, nil
}
// Get all messages in the inbox that haven't been seen yet
// Get all messages in the inbox that haven't been seen yet and haven't been AI-processed
criteria := imap.NewSearchCriteria()
criteria.WithoutFlags = []string{"\\Seen"}
criteria.WithoutFlags = []string{"\\Seen", AIProcessedFlag}
uids, err := ic.client.Search(criteria)
if err != nil {
@@ -738,6 +741,67 @@ func (ic *IMAPClient) MarkAsProcessed(email Email) (err error) {
return nil
}
// MarkAsAIProcessed marks an email with a custom flag to indicate AI has processed it
// This prevents reprocessing the same email if subsequent operations (SaveDraft, MarkAsProcessed) fail
func (ic *IMAPClient) MarkAsAIProcessed(email Email) (err error) {
defer func() {
if r := recover(); r != nil {
logger.WithFields(logrus.Fields{
"panic": r,
"emailSubject": email.Subject,
}).Error("Panic occurred in MarkAsAIProcessed")
err = fmt.Errorf("panic in MarkAsAIProcessed: %v", r)
}
}()
if err := ic.ensureConnection(); err != nil {
return fmt.Errorf("failed to ensure IMAP connection: %v", err)
}
// Select source mailbox
_, err = ic.client.Select(ic.config.MailboxIn, false)
if err != nil {
return fmt.Errorf("failed to select source mailbox: %v", err)
}
// Find the email by Message-Id
criteria := imap.NewSearchCriteria()
criteria.Header.Set("Message-Id", email.ID)
uids, err := ic.client.Search(criteria)
if err != nil {
return fmt.Errorf("search failed: %v", err)
}
if len(uids) == 0 {
return fmt.Errorf("email not found")
}
// Mark with AI-processed flag
seqSet := new(imap.SeqSet)
seqSet.AddNum(uids...)
item := imap.FormatFlagsOp(imap.AddFlags, true)
flags := []interface{}{AIProcessedFlag}
if err := ic.client.Store(seqSet, item, flags, nil); err != nil {
// If custom flags are not supported, fall back to marking as \Seen
logger.WithFields(logrus.Fields{
"error": err,
"subject": email.Subject,
}).Warn("Failed to set custom AI-processed flag, falling back to \\Seen flag")
flags = []interface{}{imap.SeenFlag}
if err := ic.client.Store(seqSet, item, flags, nil); err != nil {
return fmt.Errorf("failed to mark message with fallback flag: %v", err)
}
logger.WithField("subject", email.Subject).Info("Marked email as \\Seen (custom flag not supported)")
return nil
}
logger.WithField("subject", email.Subject).Debug("Successfully marked email with AI-processed flag")
return nil
}
func (ic *IMAPClient) Close() error {
if ic.client != nil {
ic.client.Logout()