imap: misc fixes
This commit is contained in:
parent
fc7e906d1b
commit
7d67375d85
|
@ -30,7 +30,7 @@ func (mbox *Mailbox) bucket(tx *bolt.Tx) (*bolt.Bucket, error) {
|
|||
if b == nil {
|
||||
return nil, errors.New("cannot find mailboxes bucket")
|
||||
}
|
||||
b = tx.Bucket([]byte(mbox.name))
|
||||
b = b.Bucket([]byte(mbox.name))
|
||||
if b == nil {
|
||||
return nil, errors.New("cannot find mailbox bucket")
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ func (u *User) sync(messages []*protonmail.Message) error {
|
|||
for _, msg := range messages {
|
||||
k := []byte(msg.ID)
|
||||
v, err := json.Marshal(msg)
|
||||
if err != nil{
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := b.Put(k, v); err != nil {
|
||||
|
@ -72,6 +72,7 @@ func (u *User) Message(apiID string) (*protonmail.Message, error) {
|
|||
return ErrNotFound
|
||||
}
|
||||
|
||||
msg = &protonmail.Message{}
|
||||
return json.Unmarshal(v, msg)
|
||||
})
|
||||
return msg, err
|
||||
|
|
|
@ -2,7 +2,9 @@ package imap
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/emersion/go-imap"
|
||||
|
@ -21,6 +23,9 @@ type mailbox struct {
|
|||
u *user
|
||||
db *database.Mailbox
|
||||
|
||||
initialized bool
|
||||
initializedLock sync.Mutex
|
||||
|
||||
total, unread int
|
||||
}
|
||||
|
||||
|
@ -73,6 +78,8 @@ func (mbox *mailbox) Check() error {
|
|||
}
|
||||
|
||||
func (mbox *mailbox) sync() error {
|
||||
log.Printf("Synchronizing mailbox %v...", mbox.name)
|
||||
|
||||
filter := &protonmail.MessageFilter{
|
||||
PageSize: 150,
|
||||
Label: mbox.label,
|
||||
|
@ -101,6 +108,25 @@ func (mbox *mailbox) sync() error {
|
|||
filter.Page++
|
||||
}
|
||||
|
||||
log.Printf("Synchronizing mailbox %v: done.", mbox.name)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mbox *mailbox) init() error {
|
||||
mbox.initializedLock.Lock()
|
||||
defer mbox.initializedLock.Unlock()
|
||||
|
||||
if mbox.initialized {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: sync only the first time
|
||||
if err := mbox.sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mbox.initialized = true
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -165,6 +191,10 @@ func (mbox *mailbox) fetchMessage(isUid bool, id uint32, items []imap.FetchItem)
|
|||
func (mbox *mailbox) ListMessages(uid bool, seqSet *imap.SeqSet, items []imap.FetchItem, ch chan<- *imap.Message) error {
|
||||
defer close(ch)
|
||||
|
||||
if err := mbox.init(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, seq := range seqSet.Set {
|
||||
start := seq.Start
|
||||
if start == 0 {
|
||||
|
@ -203,6 +233,10 @@ func matchString(s, substr string) bool {
|
|||
}
|
||||
|
||||
func (mbox *mailbox) SearchMessages(isUID bool, c *imap.SearchCriteria) ([]uint32, error) {
|
||||
if err := mbox.init(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: c.Not, c.Or
|
||||
if c.Not != nil || c.Or != nil {
|
||||
return nil, errors.New("search queries with NOT or OR clauses or not yet implemented")
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -146,9 +147,6 @@ func (mbox *mailbox) fetchBodyStructure(msg *protonmail.Message, extended bool)
|
|||
}
|
||||
|
||||
func (mbox *mailbox) inlineBody(msg *protonmail.Message) (io.Reader, error) {
|
||||
h := mail.NewTextHeader()
|
||||
h.SetContentType(msg.MIMEType, nil)
|
||||
|
||||
md, err := msg.Read(mbox.u.privateKeys, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -175,13 +173,19 @@ func (mbox *mailbox) attachmentBody(att *protonmail.Attachment) (io.Reader, erro
|
|||
|
||||
func inlineHeader(msg *protonmail.Message) message.Header {
|
||||
h := mail.NewTextHeader()
|
||||
if msg.MIMEType != "" {
|
||||
h.SetContentType(msg.MIMEType, nil)
|
||||
} else {
|
||||
log.Println("Sending an inline header without its proper MIME type")
|
||||
}
|
||||
h.Set("Content-Transfer-Encoding", "quoted-printable")
|
||||
return h.Header
|
||||
}
|
||||
|
||||
func attachmentHeader(att *protonmail.Attachment) message.Header {
|
||||
h := mail.NewAttachmentHeader()
|
||||
h.SetContentType(att.MIMEType, nil)
|
||||
h.Set("Content-Transfer-Encoding", "base64")
|
||||
h.SetFilename(att.Name)
|
||||
if att.ContentID != "" {
|
||||
h.Set("Content-Id", att.ContentID)
|
||||
|
@ -206,15 +210,22 @@ func mailAddressList(addresses []*protonmail.MessageAddress) []*mail.Address {
|
|||
|
||||
func messageHeader(msg *protonmail.Message) message.Header {
|
||||
h := mail.NewHeader()
|
||||
h.SetContentType("multipart/mixed", nil)
|
||||
h.SetDate(time.Unix(msg.Time, 0))
|
||||
h.SetSubject(msg.Subject)
|
||||
h.SetAddressList("From", []*mail.Address{mailAddress(msg.Sender)})
|
||||
if msg.ReplyTo != nil {
|
||||
h.SetAddressList("Reply-To", []*mail.Address{mailAddress(msg.ReplyTo)})
|
||||
}
|
||||
if len(msg.ToList) > 0 {
|
||||
h.SetAddressList("To", mailAddressList(msg.ToList))
|
||||
}
|
||||
if len(msg.CCList) > 0 {
|
||||
h.SetAddressList("Cc", mailAddressList(msg.CCList))
|
||||
}
|
||||
if len(msg.BCCList) > 0 {
|
||||
h.SetAddressList("Bcc", mailAddressList(msg.BCCList))
|
||||
}
|
||||
// TODO: In-Reply-To
|
||||
h.Set("Message-Id", messageID(msg))
|
||||
return h.Header
|
||||
|
@ -280,13 +291,16 @@ func (mbox *mailbox) fetchBodySection(msg *protonmail.Message, section *imap.Bod
|
|||
var h message.Header
|
||||
var getBody func() (io.Reader, error)
|
||||
if part := section.Path[0]; part == 1 {
|
||||
h = inlineHeader(msg)
|
||||
getBody = func() (io.Reader, error) {
|
||||
// TODO: only fetch the message if the body is needed
|
||||
// For now we fetch it in all cases because the MIME type is not included
|
||||
// in the cached message, and inlineHeader needs it
|
||||
msg, err := mbox.u.c.GetMessage(msg.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
h = inlineHeader(msg)
|
||||
getBody = func() (io.Reader, error) {
|
||||
return mbox.inlineBody(msg)
|
||||
}
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue