@@ -5,6 +5,7 @@ import (
"fmt"
"io"
"io/ioutil"
+ "log"
"mime"
"strings"
"time"
@@ -146,13 +147,28 @@ func FetchEmails(cfg *config.Config, limit, offset uint32) ([]Email, error) {
done <- c.Fetch(seqset, fetchItems, messages)
}()
- var emails []Email
+ // Collect messages from the channel into a slice
+ var msgs []*imap.Message
for msg := range messages {
- if msg == nil {
+ msgs = append(msgs, msg)
+ }
+
+ // Wait for the fetch to complete and check for errors
+ if err := <-done; err != nil {
+ return nil, err
+ }
+
+ var emails []Email
+ for _, msg := range msgs {
+ if msg == nil || msg.Envelope == nil {
continue
}
- fromAddrs := msg.Envelope.From[0].Address()
+ var fromAddr string
+ if len(msg.Envelope.From) > 0 {
+ fromAddr = msg.Envelope.From[0].Address()
+ }
+
var toAddrList []string
for _, addr := range msg.Envelope.To {
toAddrList = append(toAddrList, addr.Address())
@@ -160,17 +176,13 @@ func FetchEmails(cfg *config.Config, limit, offset uint32) ([]Email, error) {
emails = append(emails, Email{
UID: msg.Uid,
- From: fromAddrs,
+ From: fromAddr,
To: toAddrList,
Subject: decodeHeader(msg.Envelope.Subject),
Date: msg.Envelope.Date,
})
}
- if err := <-done; err != nil {
- return nil, err
- }
-
// Reverse the order to show newest first
for i, j := 0, len(emails)-1; i < j; i, j = i+1, j-1 {
emails[i], emails[j] = emails[j], emails[i]
@@ -179,8 +191,6 @@ func FetchEmails(cfg *config.Config, limit, offset uint32) ([]Email, error) {
return emails, nil
}
-
-// New function to fetch the body for a single email
func FetchEmailBody(cfg *config.Config, uid uint32) (string, []Attachment, error) {
c, err := connect(cfg)
if err != nil {
@@ -199,12 +209,23 @@ func FetchEmailBody(cfg *config.Config, uid uint32) (string, []Attachment, error
done := make(chan error, 1)
fetchItems := []imap.FetchItem{imap.FetchItem("BODY[]")}
go func() {
- done <- c.Fetch(seqset, fetchItems, messages)
+ done <- c.UidFetch(seqset, fetchItems, messages)
}()
- msg := <-messages
- if msg == nil {
- return "", nil, fmt.Errorf("could not fetch email body")
+ // Wait for the fetch operation to complete first.
+ if err := <-done; err != nil {
+ return "", nil, err
+ }
+
+ // Now that the fetch is complete, check for a message.
+ var msg *imap.Message
+ select {
+ case msg = <-messages:
+ if msg == nil {
+ return "", nil, fmt.Errorf("fetched a nil message")
+ }
+ default:
+ return "", nil, fmt.Errorf("no message found with UID %d", uid)
}
bodyLiteral := msg.GetBody(&imap.BodySectionName{})
@@ -224,7 +245,8 @@ func FetchEmailBody(cfg *config.Config, uid uint32) (string, []Attachment, error
if err == io.EOF {
break
} else if err != nil {
- return "", nil, fmt.Errorf("error getting next part: %v", err)
+ log.Printf("Error getting next part: %v", err)
+ break
}
cdHeader := p.Header.Get("Content-Disposition")
@@ -256,14 +278,9 @@ func FetchEmailBody(cfg *config.Config, uid uint32) (string, []Attachment, error
}
}
- if err := <-done; err != nil {
- return "", nil, err
- }
-
return body, attachments, nil
}
-
func moveEmail(cfg *config.Config, uid uint32, destMailbox string) error {
c, err := connect(cfg)
if err != nil {
@@ -314,4 +331,4 @@ func ArchiveEmail(cfg *config.Config, uid uint32) error {
archiveMailbox = "Archive"
}
return moveEmail(cfg, uid, archiveMailbox)
-}
+}
@@ -152,6 +152,21 @@ func (m *mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, m.current.Init()
case tui.ViewEmailMsg:
+ // Show a status message while fetching the email body
+ m.current = tui.NewStatus("Fetching email content...")
+ // Pass the index directly to the command
+ return m, tea.Batch(m.current.Init(), fetchEmailBodyCmd(m.config, m.emails[msg.Index], msg.Index))
+
+ case tui.EmailBodyFetchedMsg:
+ if msg.Err != nil {
+ log.Printf("could not fetch email body: %v", msg.Err)
+ m.current = m.inbox
+ return m, nil
+ }
+ // Use the index from the message to update the correct email
+ m.emails[msg.Index].Body = msg.Body
+ m.emails[msg.Index].Attachments = msg.Attachments
+
emailView := tui.NewEmailView(m.emails[msg.Index], m.width, m.height)
m.current = emailView
return m, m.current.Init()
@@ -248,6 +263,23 @@ func (m *mainModel) View() string {
return m.current.View()
}
+func fetchEmailBodyCmd(cfg *config.Config, email fetcher.Email, index int) tea.Cmd {
+ return func() tea.Msg {
+ body, attachments, err := fetcher.FetchEmailBody(cfg, email.UID)
+ if err != nil {
+ return tui.EmailBodyFetchedMsg{Index: index, Err: err}
+ }
+
+ // Return the fetched data along with the original index
+ return tui.EmailBodyFetchedMsg{
+ Index: index,
+ Body: body,
+ Attachments: attachments,
+ }
+ }
+}
+
+
func markdownToHTML(md []byte) []byte {
var buf bytes.Buffer
p := goldmark.New(goldmark.WithRendererOptions(html.WithUnsafe()))