Forked the emersion/go-imap v1 project.
This commit is contained in:
140
imapserver/imapmemserver/session.go
Normal file
140
imapserver/imapmemserver/session.go
Normal file
@@ -0,0 +1,140 @@
|
||||
package imapmemserver
|
||||
|
||||
import (
|
||||
"github.com/emersion/go-imap/v2"
|
||||
"github.com/emersion/go-imap/v2/imapserver"
|
||||
)
|
||||
|
||||
type (
|
||||
user = User
|
||||
mailbox = MailboxView
|
||||
)
|
||||
|
||||
// UserSession represents a session tied to a specific user.
|
||||
//
|
||||
// UserSession implements imapserver.Session. Typically, a UserSession pointer
|
||||
// is embedded into a larger struct which overrides Login.
|
||||
type UserSession struct {
|
||||
*user // immutable
|
||||
*mailbox // may be nil
|
||||
}
|
||||
|
||||
var _ imapserver.SessionIMAP4rev2 = (*UserSession)(nil)
|
||||
|
||||
// NewUserSession creates a new user session.
|
||||
func NewUserSession(user *User) *UserSession {
|
||||
return &UserSession{user: user}
|
||||
}
|
||||
|
||||
func (sess *UserSession) Close() error {
|
||||
if sess != nil && sess.mailbox != nil {
|
||||
sess.mailbox.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sess *UserSession) Select(name string, options *imap.SelectOptions) (*imap.SelectData, error) {
|
||||
mbox, err := sess.user.mailbox(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mbox.mutex.Lock()
|
||||
defer mbox.mutex.Unlock()
|
||||
sess.mailbox = mbox.NewView()
|
||||
return mbox.selectDataLocked(), nil
|
||||
}
|
||||
|
||||
func (sess *UserSession) Unselect() error {
|
||||
sess.mailbox.Close()
|
||||
sess.mailbox = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sess *UserSession) Copy(numSet imap.NumSet, destName string) (*imap.CopyData, error) {
|
||||
dest, err := sess.user.mailbox(destName)
|
||||
if err != nil {
|
||||
return nil, &imap.Error{
|
||||
Type: imap.StatusResponseTypeNo,
|
||||
Code: imap.ResponseCodeTryCreate,
|
||||
Text: "No such mailbox",
|
||||
}
|
||||
} else if sess.mailbox != nil && dest == sess.mailbox.Mailbox {
|
||||
return nil, &imap.Error{
|
||||
Type: imap.StatusResponseTypeNo,
|
||||
Text: "Source and destination mailboxes are identical",
|
||||
}
|
||||
}
|
||||
|
||||
var sourceUIDs, destUIDs imap.UIDSet
|
||||
sess.mailbox.forEach(numSet, func(seqNum uint32, msg *message) {
|
||||
appendData := dest.copyMsg(msg)
|
||||
sourceUIDs.AddNum(msg.uid)
|
||||
destUIDs.AddNum(appendData.UID)
|
||||
})
|
||||
|
||||
return &imap.CopyData{
|
||||
UIDValidity: dest.uidValidity,
|
||||
SourceUIDs: sourceUIDs,
|
||||
DestUIDs: destUIDs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (sess *UserSession) Move(w *imapserver.MoveWriter, numSet imap.NumSet, destName string) error {
|
||||
dest, err := sess.user.mailbox(destName)
|
||||
if err != nil {
|
||||
return &imap.Error{
|
||||
Type: imap.StatusResponseTypeNo,
|
||||
Code: imap.ResponseCodeTryCreate,
|
||||
Text: "No such mailbox",
|
||||
}
|
||||
} else if sess.mailbox != nil && dest == sess.mailbox.Mailbox {
|
||||
return &imap.Error{
|
||||
Type: imap.StatusResponseTypeNo,
|
||||
Text: "Source and destination mailboxes are identical",
|
||||
}
|
||||
}
|
||||
|
||||
sess.mailbox.mutex.Lock()
|
||||
defer sess.mailbox.mutex.Unlock()
|
||||
|
||||
var sourceUIDs, destUIDs imap.UIDSet
|
||||
expunged := make(map[*message]struct{})
|
||||
sess.mailbox.forEachLocked(numSet, func(seqNum uint32, msg *message) {
|
||||
appendData := dest.copyMsg(msg)
|
||||
sourceUIDs.AddNum(msg.uid)
|
||||
destUIDs.AddNum(appendData.UID)
|
||||
expunged[msg] = struct{}{}
|
||||
})
|
||||
seqNums := sess.mailbox.expungeLocked(expunged)
|
||||
|
||||
err = w.WriteCopyData(&imap.CopyData{
|
||||
UIDValidity: dest.uidValidity,
|
||||
SourceUIDs: sourceUIDs,
|
||||
DestUIDs: destUIDs,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, seqNum := range seqNums {
|
||||
if err := w.WriteExpunge(sess.mailbox.tracker.EncodeSeqNum(seqNum)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sess *UserSession) Poll(w *imapserver.UpdateWriter, allowExpunge bool) error {
|
||||
if sess.mailbox == nil {
|
||||
return nil
|
||||
}
|
||||
return sess.mailbox.Poll(w, allowExpunge)
|
||||
}
|
||||
|
||||
func (sess *UserSession) Idle(w *imapserver.UpdateWriter, stop <-chan struct{}) error {
|
||||
if sess.mailbox == nil {
|
||||
return nil // TODO
|
||||
}
|
||||
return sess.mailbox.Idle(w, stop)
|
||||
}
|
||||
Reference in New Issue
Block a user