Initial commit
This commit is contained in:
72
vendor/github.com/emersion/go-imap/responses/authenticate.go
generated
vendored
Normal file
72
vendor/github.com/emersion/go-imap/responses/authenticate.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
package responses
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
|
||||
"github.com/emersion/go-imap"
|
||||
"github.com/emersion/go-sasl"
|
||||
)
|
||||
|
||||
// An AUTHENTICATE response.
|
||||
type Authenticate struct {
|
||||
Mechanism sasl.Client
|
||||
InitialResponse []byte
|
||||
Writer *imap.Writer
|
||||
}
|
||||
|
||||
func (r *Authenticate) HandleFrom(hdlr imap.RespHandler) (err error) {
|
||||
w := r.Writer
|
||||
|
||||
// Cancel auth if an error occurs
|
||||
defer (func() {
|
||||
if err != nil {
|
||||
w.Write([]byte("*\r\n"))
|
||||
w.Flush()
|
||||
}
|
||||
})()
|
||||
|
||||
for h := range hdlr {
|
||||
cont, ok := h.Resp.(*imap.ContinuationResp)
|
||||
if !ok {
|
||||
h.Reject()
|
||||
continue
|
||||
}
|
||||
h.Accept()
|
||||
|
||||
// Empty challenge, send initial response as stated in RFC 2222 section 5.1
|
||||
if cont.Info == "" && r.InitialResponse != nil {
|
||||
encoded := base64.StdEncoding.EncodeToString(r.InitialResponse)
|
||||
if _, err = w.Write([]byte(encoded + "\r\n")); err != nil {
|
||||
return
|
||||
}
|
||||
if err = w.Flush(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
r.InitialResponse = nil
|
||||
continue
|
||||
}
|
||||
|
||||
var challenge []byte
|
||||
challenge, err = base64.StdEncoding.DecodeString(cont.Info)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var res []byte
|
||||
res, err = r.Mechanism.Next(challenge)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
encoded := base64.StdEncoding.EncodeToString(res)
|
||||
if _, err = w.Write([]byte(encoded + "\r\n")); err != nil {
|
||||
return
|
||||
}
|
||||
if err = w.Flush(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
39
vendor/github.com/emersion/go-imap/responses/capability.go
generated
vendored
Normal file
39
vendor/github.com/emersion/go-imap/responses/capability.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
package responses
|
||||
|
||||
import (
|
||||
"github.com/emersion/go-imap"
|
||||
)
|
||||
|
||||
// A CAPABILITY response.
|
||||
// See RFC 3501 section 7.2.1
|
||||
type Capability struct {
|
||||
Caps []string
|
||||
}
|
||||
|
||||
func (r *Capability) HandleFrom(hdlr imap.RespHandler) (err error) {
|
||||
for h := range hdlr {
|
||||
caps, ok := h.AcceptNamedResp(imap.Capability)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
r.Caps = make([]string, len(caps))
|
||||
for i, c := range caps {
|
||||
r.Caps[i], _ = c.(string)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Capability) WriteTo(w *imap.Writer) error {
|
||||
fields := []interface{}{imap.Capability}
|
||||
for _, cap := range r.Caps {
|
||||
fields = append(fields, cap)
|
||||
}
|
||||
|
||||
res := &imap.Resp{Fields: fields}
|
||||
return res.WriteTo(w)
|
||||
}
|
45
vendor/github.com/emersion/go-imap/responses/expunge.go
generated
vendored
Normal file
45
vendor/github.com/emersion/go-imap/responses/expunge.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
package responses
|
||||
|
||||
import (
|
||||
"github.com/emersion/go-imap"
|
||||
)
|
||||
|
||||
// An EXPUNGE response.
|
||||
// See RFC 3501 section 7.4.1
|
||||
type Expunge struct {
|
||||
SeqNums chan uint32
|
||||
}
|
||||
|
||||
func (r *Expunge) HandleFrom(hdlr imap.RespHandler) error {
|
||||
defer close(r.SeqNums)
|
||||
|
||||
for h := range hdlr {
|
||||
res, ok := h.Resp.(*imap.Resp)
|
||||
if !ok || len(res.Fields) < 3 {
|
||||
h.Reject()
|
||||
continue
|
||||
}
|
||||
if name, ok := res.Fields[1].(string); !ok || name != imap.Expunge {
|
||||
h.Reject()
|
||||
continue
|
||||
}
|
||||
h.Accept()
|
||||
|
||||
seqNum, _ := imap.ParseNumber(res.Fields[0])
|
||||
r.SeqNums <- seqNum
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Expunge) WriteTo(w *imap.Writer) error {
|
||||
for seqNum := range r.SeqNums {
|
||||
res := imap.NewUntaggedResp([]interface{}{seqNum, imap.Expunge})
|
||||
|
||||
if err := res.WriteTo(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
55
vendor/github.com/emersion/go-imap/responses/fetch.go
generated
vendored
Normal file
55
vendor/github.com/emersion/go-imap/responses/fetch.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
package responses
|
||||
|
||||
import (
|
||||
"github.com/emersion/go-imap"
|
||||
)
|
||||
|
||||
// A FETCH response.
|
||||
// See RFC 3501 section 7.4.2
|
||||
type Fetch struct {
|
||||
Messages chan *imap.Message
|
||||
}
|
||||
|
||||
func (r *Fetch) HandleFrom(hdlr imap.RespHandler) error {
|
||||
defer close(r.Messages)
|
||||
|
||||
for h := range hdlr {
|
||||
res, ok := h.Resp.(*imap.Resp)
|
||||
if !ok || len(res.Fields) < 3 {
|
||||
h.Reject()
|
||||
continue
|
||||
}
|
||||
if name, ok := res.Fields[1].(string); !ok || name != imap.Fetch {
|
||||
h.Reject()
|
||||
continue
|
||||
}
|
||||
h.Accept()
|
||||
|
||||
seqNum, _ := imap.ParseNumber(res.Fields[0])
|
||||
fields, _ := res.Fields[2].([]interface{})
|
||||
|
||||
msg := &imap.Message{
|
||||
SeqNum: seqNum,
|
||||
}
|
||||
|
||||
if err := msg.Parse(fields); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Messages <- msg
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Fetch) WriteTo(w *imap.Writer) error {
|
||||
for msg := range r.Messages {
|
||||
res := imap.NewUntaggedResp([]interface{}{msg.SeqNum, imap.Fetch, msg.Format()})
|
||||
|
||||
if err := res.WriteTo(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
59
vendor/github.com/emersion/go-imap/responses/list.go
generated
vendored
Normal file
59
vendor/github.com/emersion/go-imap/responses/list.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
package responses
|
||||
|
||||
import (
|
||||
"github.com/emersion/go-imap"
|
||||
)
|
||||
|
||||
// A LIST response.
|
||||
// If Subscribed is set to true, LSUB will be used instead.
|
||||
// See RFC 3501 section 7.2.2
|
||||
type List struct {
|
||||
Mailboxes chan *imap.MailboxInfo
|
||||
Subscribed bool
|
||||
}
|
||||
|
||||
func (r *List) Name() string {
|
||||
if r.Subscribed {
|
||||
return imap.Lsub
|
||||
} else {
|
||||
return imap.List
|
||||
}
|
||||
}
|
||||
|
||||
func (r *List) HandleFrom(hdlr imap.RespHandler) error {
|
||||
defer close(r.Mailboxes)
|
||||
|
||||
name := r.Name()
|
||||
|
||||
for h := range hdlr {
|
||||
fields, ok := h.AcceptNamedResp(name)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
mbox := &imap.MailboxInfo{}
|
||||
if err := mbox.Parse(fields); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Mailboxes <- mbox
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *List) WriteTo(w *imap.Writer) error {
|
||||
name := r.Name()
|
||||
|
||||
for mbox := range r.Mailboxes {
|
||||
fields := []interface{}{name}
|
||||
fields = append(fields, mbox.Format()...)
|
||||
|
||||
res := imap.NewUntaggedResp(fields)
|
||||
if err := res.WriteTo(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
2
vendor/github.com/emersion/go-imap/responses/responses.go
generated
vendored
Normal file
2
vendor/github.com/emersion/go-imap/responses/responses.go
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// IMAP responses defined in RFC 3501.
|
||||
package responses
|
37
vendor/github.com/emersion/go-imap/responses/search.go
generated
vendored
Normal file
37
vendor/github.com/emersion/go-imap/responses/search.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
package responses
|
||||
|
||||
import (
|
||||
"github.com/emersion/go-imap"
|
||||
)
|
||||
|
||||
// A SEARCH response.
|
||||
// See RFC 3501 section 7.2.5
|
||||
type Search struct {
|
||||
Ids []uint32
|
||||
}
|
||||
|
||||
func (r *Search) HandleFrom(hdlr imap.RespHandler) (err error) {
|
||||
for h := range hdlr {
|
||||
fields, ok := h.AcceptNamedResp(imap.Search)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, f := range fields {
|
||||
id, _ := imap.ParseNumber(f)
|
||||
r.Ids = append(r.Ids, id)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Search) WriteTo(w *imap.Writer) (err error) {
|
||||
fields := []interface{}{imap.Search}
|
||||
for _, id := range r.Ids {
|
||||
fields = append(fields, id)
|
||||
}
|
||||
|
||||
res := imap.NewUntaggedResp(fields)
|
||||
return res.WriteTo(w)
|
||||
}
|
145
vendor/github.com/emersion/go-imap/responses/select.go
generated
vendored
Normal file
145
vendor/github.com/emersion/go-imap/responses/select.go
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
package responses
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/emersion/go-imap"
|
||||
)
|
||||
|
||||
// A SELECT response.
|
||||
type Select struct {
|
||||
Mailbox *imap.MailboxStatus
|
||||
}
|
||||
|
||||
func (r *Select) HandleFrom(hdlr imap.RespHandler) (err error) {
|
||||
if r.Mailbox == nil {
|
||||
r.Mailbox = &imap.MailboxStatus{}
|
||||
}
|
||||
mbox := r.Mailbox
|
||||
|
||||
mbox.Items = make(map[string]interface{})
|
||||
for h := range hdlr {
|
||||
switch res := h.Resp.(type) {
|
||||
case *imap.Resp:
|
||||
fields, ok := h.AcceptNamedResp(imap.MailboxFlags)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
flags, _ := fields[0].([]interface{})
|
||||
mbox.Flags, _ = imap.ParseStringList(flags)
|
||||
mbox.ItemsLocker.Lock()
|
||||
mbox.Items[imap.MailboxFlags] = nil
|
||||
mbox.ItemsLocker.Unlock()
|
||||
case *imap.StatusResp:
|
||||
if len(res.Arguments) < 1 {
|
||||
h.Accepts <- false
|
||||
break
|
||||
}
|
||||
|
||||
accepted := true
|
||||
switch res.Code {
|
||||
case imap.MailboxUnseen:
|
||||
mbox.Unseen, _ = imap.ParseNumber(res.Arguments[0])
|
||||
mbox.ItemsLocker.Lock()
|
||||
mbox.Items[imap.MailboxUnseen] = nil
|
||||
mbox.ItemsLocker.Unlock()
|
||||
case imap.MailboxPermanentFlags:
|
||||
flags, _ := res.Arguments[0].([]interface{})
|
||||
mbox.PermanentFlags, _ = imap.ParseStringList(flags)
|
||||
mbox.ItemsLocker.Lock()
|
||||
mbox.Items[imap.MailboxPermanentFlags] = nil
|
||||
mbox.ItemsLocker.Unlock()
|
||||
case imap.MailboxUidNext:
|
||||
mbox.UidNext, _ = imap.ParseNumber(res.Arguments[0])
|
||||
mbox.ItemsLocker.Lock()
|
||||
mbox.Items[imap.MailboxUidNext] = nil
|
||||
mbox.ItemsLocker.Unlock()
|
||||
case imap.MailboxUidValidity:
|
||||
mbox.UidValidity, _ = imap.ParseNumber(res.Arguments[0])
|
||||
mbox.ItemsLocker.Lock()
|
||||
mbox.Items[imap.MailboxUidValidity] = nil
|
||||
mbox.ItemsLocker.Unlock()
|
||||
default:
|
||||
accepted = false
|
||||
}
|
||||
h.Accepts <- accepted
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Select) WriteTo(w *imap.Writer) (err error) {
|
||||
status := r.Mailbox
|
||||
|
||||
for k := range r.Mailbox.Items {
|
||||
switch k {
|
||||
case imap.MailboxFlags:
|
||||
flags := make([]interface{}, len(status.Flags))
|
||||
for i, f := range status.Flags {
|
||||
flags[i] = f
|
||||
}
|
||||
res := imap.NewUntaggedResp([]interface{}{"FLAGS", flags})
|
||||
if err = res.WriteTo(w); err != nil {
|
||||
return
|
||||
}
|
||||
case imap.MailboxPermanentFlags:
|
||||
flags := make([]interface{}, len(status.PermanentFlags))
|
||||
for i, f := range status.PermanentFlags {
|
||||
flags[i] = f
|
||||
}
|
||||
statusRes := &imap.StatusResp{
|
||||
Type: imap.StatusOk,
|
||||
Code: imap.CodePermanentFlags,
|
||||
Arguments: []interface{}{flags},
|
||||
Info: "Flags permitted.",
|
||||
}
|
||||
if err = statusRes.WriteTo(w); err != nil {
|
||||
return
|
||||
}
|
||||
case imap.MailboxMessages:
|
||||
res := imap.NewUntaggedResp([]interface{}{status.Messages, "EXISTS"})
|
||||
if err = res.WriteTo(w); err != nil {
|
||||
return
|
||||
}
|
||||
case imap.MailboxRecent:
|
||||
res := imap.NewUntaggedResp([]interface{}{status.Recent, "RECENT"})
|
||||
if err = res.WriteTo(w); err != nil {
|
||||
return
|
||||
}
|
||||
case imap.MailboxUnseen:
|
||||
statusRes := &imap.StatusResp{
|
||||
Type: imap.StatusOk,
|
||||
Code: imap.CodeUnseen,
|
||||
Arguments: []interface{}{status.Unseen},
|
||||
Info: fmt.Sprintf("Message %d is first unseen", status.Unseen),
|
||||
}
|
||||
if err = statusRes.WriteTo(w); err != nil {
|
||||
return
|
||||
}
|
||||
case imap.MailboxUidNext:
|
||||
statusRes := &imap.StatusResp{
|
||||
Type: imap.StatusOk,
|
||||
Code: imap.CodeUidNext,
|
||||
Arguments: []interface{}{status.UidNext},
|
||||
Info: "Predicted next UID",
|
||||
}
|
||||
if err = statusRes.WriteTo(w); err != nil {
|
||||
return
|
||||
}
|
||||
case imap.MailboxUidValidity:
|
||||
statusRes := &imap.StatusResp{
|
||||
Type: imap.StatusOk,
|
||||
Code: imap.CodeUidValidity,
|
||||
Arguments: []interface{}{status.UidValidity},
|
||||
Info: "UIDs valid",
|
||||
}
|
||||
if err = statusRes.WriteTo(w); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
63
vendor/github.com/emersion/go-imap/responses/status.go
generated
vendored
Normal file
63
vendor/github.com/emersion/go-imap/responses/status.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
package responses
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/emersion/go-imap"
|
||||
"github.com/emersion/go-imap/utf7"
|
||||
)
|
||||
|
||||
// A STATUS response.
|
||||
// See RFC 3501 section 7.2.4
|
||||
type Status struct {
|
||||
Mailbox *imap.MailboxStatus
|
||||
}
|
||||
|
||||
func (r *Status) HandleFrom(hdlr imap.RespHandler) error {
|
||||
if r.Mailbox == nil {
|
||||
r.Mailbox = &imap.MailboxStatus{}
|
||||
}
|
||||
mbox := r.Mailbox
|
||||
mbox.Items = nil
|
||||
|
||||
for h := range hdlr {
|
||||
fields, ok := h.AcceptNamedResp(imap.Status)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if len(fields) < 2 {
|
||||
return errors.New("STATUS response expects two fields")
|
||||
}
|
||||
|
||||
name, ok := fields[0].(string)
|
||||
if !ok {
|
||||
return errors.New("STATUS response expects a string as first argument")
|
||||
}
|
||||
mbox.Name, _ = utf7.Decoder.String(name)
|
||||
mbox.Name = imap.CanonicalMailboxName(mbox.Name)
|
||||
|
||||
var items []interface{}
|
||||
if items, ok = fields[1].([]interface{}); !ok {
|
||||
return errors.New("STATUS response expects a list as second argument")
|
||||
}
|
||||
|
||||
if err := mbox.Parse(items); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Status) WriteTo(w *imap.Writer) error {
|
||||
mbox := r.Mailbox
|
||||
|
||||
fields := []interface{}{imap.Status, mbox.Name, mbox.Format()}
|
||||
|
||||
res := imap.NewUntaggedResp(fields)
|
||||
if err := res.WriteTo(w); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user