Files
crockery/internal/store/message.go

110 lines
2.2 KiB
Go

package store
import (
"fmt"
"io"
"log"
"net/mail"
"path/filepath"
"strings"
)
type Message struct {
Maildir Maildir // maildir.name
UID uint64
SeqNum uint64
Key string
Data io.ReadCloser
hdrCache mail.Header
}
// TODO: the cache is probably fine
func (m *Message) Header() (mail.Header, error) {
if m.hdrCache != nil {
return m.hdrCache, nil
}
hdr, err := m.Maildir.Header(m.Key)
if err != nil {
return nil, err
}
m.hdrCache = hdr
return hdr, nil
}
func (m *Message) Len() uint64 {
return 0 // FIXME
}
func (m *Message) HeaderString() (string, error) {
var sb strings.Builder
hdr, err := m.Header()
if err != nil {
return "", err
}
for k, vs := range hdr {
for _, v := range vs {
fmt.Fprintf(&sb, "%s: %s\r\n", k, v)
}
}
return sb.String(), nil // FIXME
}
type MessageInterface interface {
CreateMessage(Message) error
}
// DeliverMessage takes the given message and delivers it to the correct maildir
// It does not call Close() on message.Data
func (c *concrete) CreateMessage(message Message) error {
// TODO: recover from panics, assure Abort() is called for them
maildir := message.Maildir
delivery, err := maildir.filesystem.NewDelivery()
if err != nil {
return err
}
if _, err := io.Copy(delivery, message.Data); err != nil {
delivery.Abort()
return err
}
if err := delivery.Close(); err != nil {
delivery.Abort()
return err
}
// FIXME: this moves files in the maildir before the dovecot-uidlist is
// updated. Not ideal.
// FIXME: we're not
keys, err := maildir.filesystem.Unseen()
if err != nil {
log.Printf("Failed moving messages from new/ to cur/: %v", err)
}
var filenames []string
for _, key := range keys {
filename, err := maildir.filesystem.Filename(key)
if err != nil {
log.Printf("Failed getting filename for unseen message %q: %v", key, err)
continue
}
filenames = append(filenames, filepath.Base(filename))
}
// Don't bubble the error up here as delivery has succeeded, IMAP just
// doesn't know it has. We don't want the client to attempt redelivery.
//
// FIXME: this is IMAP stuff that needs moving
if err := maildir.uids.Append(filenames...); err != nil {
log.Printf("Allocating UIDs for unseen messages failed: %v", err)
}
return nil
}