prism/service/proton/email.go
2026-02-02 14:52:07 -08:00

112 lines
2.3 KiB
Go

package proton
import (
"fmt"
"prism/service/notification"
"github.com/emersion/go-imap"
)
func (m *Monitor) handleNewMessages() error {
criteria := imap.NewSearchCriteria()
criteria.WithoutFlags = []string{m.cfg.IMAPSeenFlag}
uids, err := m.client.UidSearch(criteria)
if err != nil {
return fmt.Errorf("search failed: %w", err)
}
if len(uids) == 0 {
return nil
}
seqSet := new(imap.SeqSet)
seqSet.AddNum(uids...)
messages := make(chan *imap.Message, 10)
done := make(chan error, 1)
go func() {
done <- m.client.UidFetch(seqSet, []imap.FetchItem{imap.FetchEnvelope, imap.FetchUid}, messages)
}()
for msg := range messages {
if err := m.processMessage(msg); err != nil {
m.logger.Error("Failed to process message", "error", err)
}
}
if err := <-done; err != nil {
return fmt.Errorf("fetch failed: %w", err)
}
return nil
}
func (m *Monitor) processMessage(msg *imap.Message) error {
if msg.Envelope == nil {
return nil
}
if msg.Envelope.Date.Before(m.monitorStartTime) {
m.logger.Debug("Skipping old email", "date", msg.Envelope.Date, "subject", msg.Envelope.Subject)
return nil
}
var from string
if len(msg.Envelope.From) > 0 {
addr := msg.Envelope.From[0]
if addr.PersonalName != "" {
from = addr.PersonalName
} else {
from = addr.Address()
}
} else {
from = "Unknown sender"
}
subject := msg.Envelope.Subject
if subject == "" {
subject = "No subject"
}
endpoint := m.cfg.EndpointPrefixProton + m.cfg.ProtonPrismTopic
notif := notification.Notification{
Title: from,
Message: subject,
Actions: []notification.Action{
{
ID: "mark-read",
Endpoint: "/api/proton-mail/mark-read",
Method: "POST",
Data: map[string]interface{}{
"uid": msg.Uid,
},
},
},
}
if err := m.dispatcher.Send(endpoint, notif); err != nil {
m.logger.Error("Failed to send notification", "endpoint", endpoint, "error", err)
return err
}
m.logger.Info("Processed Proton Mail notification", "from", from, "subject", subject)
return nil
}
func (m *Monitor) MarkAsRead(uid uint32) error {
if m.client == nil {
return fmt.Errorf("not connected")
}
seqSet := new(imap.SeqSet)
seqSet.AddNum(uid)
item := imap.FormatFlagsOp(imap.AddFlags, true)
flags := []interface{}{m.cfg.IMAPSeenFlag}
return m.client.UidStore(seqSet, item, flags, nil)
}