This is the v1 version, had the v2 before.
This commit is contained in:
243
backend/memory/mailbox.go
Normal file
243
backend/memory/mailbox.go
Normal file
@@ -0,0 +1,243 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"github.com/emersion/go-imap"
|
||||
"github.com/emersion/go-imap/backend"
|
||||
"github.com/emersion/go-imap/backend/backendutil"
|
||||
)
|
||||
|
||||
var Delimiter = "/"
|
||||
|
||||
type Mailbox struct {
|
||||
Subscribed bool
|
||||
Messages []*Message
|
||||
|
||||
name string
|
||||
user *User
|
||||
}
|
||||
|
||||
func (mbox *Mailbox) Name() string {
|
||||
return mbox.name
|
||||
}
|
||||
|
||||
func (mbox *Mailbox) Info() (*imap.MailboxInfo, error) {
|
||||
info := &imap.MailboxInfo{
|
||||
Delimiter: Delimiter,
|
||||
Name: mbox.name,
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func (mbox *Mailbox) uidNext() uint32 {
|
||||
var uid uint32
|
||||
for _, msg := range mbox.Messages {
|
||||
if msg.Uid > uid {
|
||||
uid = msg.Uid
|
||||
}
|
||||
}
|
||||
uid++
|
||||
return uid
|
||||
}
|
||||
|
||||
func (mbox *Mailbox) flags() []string {
|
||||
flagsMap := make(map[string]bool)
|
||||
for _, msg := range mbox.Messages {
|
||||
for _, f := range msg.Flags {
|
||||
if !flagsMap[f] {
|
||||
flagsMap[f] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var flags []string
|
||||
for f := range flagsMap {
|
||||
flags = append(flags, f)
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
func (mbox *Mailbox) unseenSeqNum() uint32 {
|
||||
for i, msg := range mbox.Messages {
|
||||
seqNum := uint32(i + 1)
|
||||
|
||||
seen := false
|
||||
for _, flag := range msg.Flags {
|
||||
if flag == imap.SeenFlag {
|
||||
seen = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !seen {
|
||||
return seqNum
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (mbox *Mailbox) Status(items []imap.StatusItem) (*imap.MailboxStatus, error) {
|
||||
status := imap.NewMailboxStatus(mbox.name, items)
|
||||
status.Flags = mbox.flags()
|
||||
status.PermanentFlags = []string{"\\*"}
|
||||
status.UnseenSeqNum = mbox.unseenSeqNum()
|
||||
|
||||
for _, name := range items {
|
||||
switch name {
|
||||
case imap.StatusMessages:
|
||||
status.Messages = uint32(len(mbox.Messages))
|
||||
case imap.StatusUidNext:
|
||||
status.UidNext = mbox.uidNext()
|
||||
case imap.StatusUidValidity:
|
||||
status.UidValidity = 1
|
||||
case imap.StatusRecent:
|
||||
status.Recent = 0 // TODO
|
||||
case imap.StatusUnseen:
|
||||
status.Unseen = 0 // TODO
|
||||
}
|
||||
}
|
||||
|
||||
return status, nil
|
||||
}
|
||||
|
||||
func (mbox *Mailbox) SetSubscribed(subscribed bool) error {
|
||||
mbox.Subscribed = subscribed
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mbox *Mailbox) Check() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mbox *Mailbox) ListMessages(uid bool, seqSet *imap.SeqSet, items []imap.FetchItem, ch chan<- *imap.Message) error {
|
||||
defer close(ch)
|
||||
|
||||
for i, msg := range mbox.Messages {
|
||||
seqNum := uint32(i + 1)
|
||||
|
||||
var id uint32
|
||||
if uid {
|
||||
id = msg.Uid
|
||||
} else {
|
||||
id = seqNum
|
||||
}
|
||||
if !seqSet.Contains(id) {
|
||||
continue
|
||||
}
|
||||
|
||||
m, err := msg.Fetch(seqNum, items)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
ch <- m
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mbox *Mailbox) SearchMessages(uid bool, criteria *imap.SearchCriteria) ([]uint32, error) {
|
||||
var ids []uint32
|
||||
for i, msg := range mbox.Messages {
|
||||
seqNum := uint32(i + 1)
|
||||
|
||||
ok, err := msg.Match(seqNum, criteria)
|
||||
if err != nil || !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
var id uint32
|
||||
if uid {
|
||||
id = msg.Uid
|
||||
} else {
|
||||
id = seqNum
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
func (mbox *Mailbox) CreateMessage(flags []string, date time.Time, body imap.Literal) error {
|
||||
if date.IsZero() {
|
||||
date = time.Now()
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadAll(body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mbox.Messages = append(mbox.Messages, &Message{
|
||||
Uid: mbox.uidNext(),
|
||||
Date: date,
|
||||
Size: uint32(len(b)),
|
||||
Flags: flags,
|
||||
Body: b,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mbox *Mailbox) UpdateMessagesFlags(uid bool, seqset *imap.SeqSet, op imap.FlagsOp, flags []string) error {
|
||||
for i, msg := range mbox.Messages {
|
||||
var id uint32
|
||||
if uid {
|
||||
id = msg.Uid
|
||||
} else {
|
||||
id = uint32(i + 1)
|
||||
}
|
||||
if !seqset.Contains(id) {
|
||||
continue
|
||||
}
|
||||
|
||||
msg.Flags = backendutil.UpdateFlags(msg.Flags, op, flags)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mbox *Mailbox) CopyMessages(uid bool, seqset *imap.SeqSet, destName string) error {
|
||||
dest, ok := mbox.user.mailboxes[destName]
|
||||
if !ok {
|
||||
return backend.ErrNoSuchMailbox
|
||||
}
|
||||
|
||||
for i, msg := range mbox.Messages {
|
||||
var id uint32
|
||||
if uid {
|
||||
id = msg.Uid
|
||||
} else {
|
||||
id = uint32(i + 1)
|
||||
}
|
||||
if !seqset.Contains(id) {
|
||||
continue
|
||||
}
|
||||
|
||||
msgCopy := *msg
|
||||
msgCopy.Uid = dest.uidNext()
|
||||
dest.Messages = append(dest.Messages, &msgCopy)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mbox *Mailbox) Expunge() error {
|
||||
for i := len(mbox.Messages) - 1; i >= 0; i-- {
|
||||
msg := mbox.Messages[i]
|
||||
|
||||
deleted := false
|
||||
for _, flag := range msg.Flags {
|
||||
if flag == imap.DeletedFlag {
|
||||
deleted = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if deleted {
|
||||
mbox.Messages = append(mbox.Messages[:i], mbox.Messages[i+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user