c610c3cd9d
Before, we were using several IMAP-specific concepts to represent information being displayed in the UI. Factor these structures out of the IMAP package to make it easier for other backends to provide the required information.
143 lines
3.7 KiB
Go
143 lines
3.7 KiB
Go
package imap
|
|
|
|
import (
|
|
"bufio"
|
|
|
|
"github.com/emersion/go-imap"
|
|
"github.com/emersion/go-message"
|
|
"github.com/emersion/go-message/mail"
|
|
"github.com/emersion/go-message/textproto"
|
|
|
|
"git.sr.ht/~sircmpwn/aerc/models"
|
|
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
|
)
|
|
|
|
func (imapw *IMAPWorker) handleFetchMessageHeaders(
|
|
msg *types.FetchMessageHeaders) {
|
|
|
|
imapw.worker.Logger.Printf("Fetching message headers")
|
|
section := &imap.BodySectionName{
|
|
BodyPartName: imap.BodyPartName{
|
|
Specifier: imap.HeaderSpecifier,
|
|
},
|
|
Peek: true,
|
|
}
|
|
|
|
items := []imap.FetchItem{
|
|
imap.FetchBodyStructure,
|
|
imap.FetchEnvelope,
|
|
imap.FetchInternalDate,
|
|
imap.FetchFlags,
|
|
imap.FetchUid,
|
|
section.FetchItem(),
|
|
}
|
|
imapw.handleFetchMessages(msg, msg.Uids, items, section)
|
|
}
|
|
|
|
func (imapw *IMAPWorker) handleFetchMessageBodyPart(
|
|
msg *types.FetchMessageBodyPart) {
|
|
|
|
imapw.worker.Logger.Printf("Fetching message part")
|
|
section := &imap.BodySectionName{}
|
|
section.Path = msg.Part
|
|
items := []imap.FetchItem{
|
|
imap.FetchFlags,
|
|
imap.FetchUid,
|
|
section.FetchItem(),
|
|
}
|
|
imapw.handleFetchMessages(msg, []uint32{msg.Uid}, items, section)
|
|
}
|
|
|
|
func (imapw *IMAPWorker) handleFetchFullMessages(
|
|
msg *types.FetchFullMessages) {
|
|
|
|
imapw.worker.Logger.Printf("Fetching full messages")
|
|
section := &imap.BodySectionName{}
|
|
items := []imap.FetchItem{
|
|
imap.FetchFlags,
|
|
imap.FetchUid,
|
|
section.FetchItem(),
|
|
}
|
|
imapw.handleFetchMessages(msg, msg.Uids, items, section)
|
|
}
|
|
|
|
func (imapw *IMAPWorker) handleFetchMessages(
|
|
msg types.WorkerMessage, uids []uint32, items []imap.FetchItem,
|
|
section *imap.BodySectionName) {
|
|
|
|
messages := make(chan *imap.Message)
|
|
done := make(chan interface{})
|
|
|
|
go func() {
|
|
for _msg := range messages {
|
|
imapw.seqMap[_msg.SeqNum-1] = _msg.Uid
|
|
switch msg.(type) {
|
|
case *types.FetchMessageHeaders:
|
|
reader := _msg.GetBody(section)
|
|
textprotoHeader, err := textproto.ReadHeader(bufio.NewReader(reader))
|
|
var header *mail.Header
|
|
if err == nil {
|
|
header = &mail.Header{message.Header{textprotoHeader}}
|
|
}
|
|
imapw.worker.PostMessage(&types.MessageInfo{
|
|
Message: types.RespondTo(msg),
|
|
Info: &models.MessageInfo{
|
|
BodyStructure: translateBodyStructure(_msg.BodyStructure),
|
|
Envelope: translateEnvelope(_msg.Envelope),
|
|
Flags: translateFlags(_msg.Flags),
|
|
InternalDate: _msg.InternalDate,
|
|
RFC822Headers: header,
|
|
Uid: _msg.Uid,
|
|
},
|
|
}, nil)
|
|
case *types.FetchFullMessages:
|
|
reader := _msg.GetBody(section)
|
|
imapw.worker.PostMessage(&types.FullMessage{
|
|
Message: types.RespondTo(msg),
|
|
Content: &models.FullMessage{
|
|
Reader: reader,
|
|
Uid: _msg.Uid,
|
|
},
|
|
}, nil)
|
|
// Update flags (to mark message as read)
|
|
imapw.worker.PostMessage(&types.MessageInfo{
|
|
Message: types.RespondTo(msg),
|
|
Info: &models.MessageInfo{
|
|
Flags: translateFlags(_msg.Flags),
|
|
Uid: _msg.Uid,
|
|
},
|
|
}, nil)
|
|
case *types.FetchMessageBodyPart:
|
|
reader := _msg.GetBody(section)
|
|
imapw.worker.PostMessage(&types.MessageBodyPart{
|
|
Message: types.RespondTo(msg),
|
|
Part: &models.MessageBodyPart{
|
|
Reader: reader,
|
|
Uid: _msg.Uid,
|
|
},
|
|
}, nil)
|
|
// Update flags (to mark message as read)
|
|
imapw.worker.PostMessage(&types.MessageInfo{
|
|
Message: types.RespondTo(msg),
|
|
Info: &models.MessageInfo{
|
|
Flags: translateFlags(_msg.Flags),
|
|
Uid: _msg.Uid,
|
|
},
|
|
}, nil)
|
|
}
|
|
}
|
|
done <- nil
|
|
}()
|
|
|
|
set := toSeqSet(uids)
|
|
if err := imapw.client.UidFetch(set, items, messages); err != nil {
|
|
imapw.worker.PostMessage(&types.Error{
|
|
Message: types.RespondTo(msg),
|
|
Error: err,
|
|
}, nil)
|
|
} else {
|
|
<-done
|
|
imapw.worker.PostMessage(
|
|
&types.Done{types.RespondTo(msg)}, nil)
|
|
}
|
|
}
|