plugins/base: add message URL and Content-Id helpers
This commit is contained in:
parent
c3e323161a
commit
7af7d73700
1 changed files with 54 additions and 12 deletions
|
@ -4,6 +4,7 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -105,6 +106,14 @@ func ensureMailboxSelected(conn *imapclient.Client, mboxName string) error {
|
||||||
|
|
||||||
type IMAPMessage struct {
|
type IMAPMessage struct {
|
||||||
*imap.Message
|
*imap.Message
|
||||||
|
|
||||||
|
Mailbox string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *IMAPMessage) URL() *url.URL {
|
||||||
|
return &url.URL{
|
||||||
|
Path: fmt.Sprintf("/message/%v/%v", url.PathEscape(msg.Mailbox), msg.Uid),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *IMAPMessage) TextPartName() string {
|
func (msg *IMAPMessage) TextPartName() string {
|
||||||
|
@ -144,6 +153,16 @@ func (msg *IMAPMessage) TextPartName() string {
|
||||||
return strings.Join(l, ".")
|
return strings.Join(l, ".")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newIMAPPartNode(msg *IMAPMessage, path []int, part *imap.BodyStructure) *IMAPPartNode {
|
||||||
|
filename, _ := part.Filename()
|
||||||
|
return &IMAPPartNode{
|
||||||
|
Path: path,
|
||||||
|
MIMEType: strings.ToLower(part.MIMEType + "/" + part.MIMESubType),
|
||||||
|
Filename: filename,
|
||||||
|
Message: msg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (msg *IMAPMessage) Attachments() []IMAPPartNode {
|
func (msg *IMAPMessage) Attachments() []IMAPPartNode {
|
||||||
if msg.BodyStructure == nil {
|
if msg.BodyStructure == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -155,22 +174,33 @@ func (msg *IMAPMessage) Attachments() []IMAPPartNode {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
filename, _ := part.Filename()
|
attachments = append(attachments, *newIMAPPartNode(msg, path, part))
|
||||||
attachments = append(attachments, IMAPPartNode{
|
|
||||||
Path: path,
|
|
||||||
MIMEType: strings.ToLower(part.MIMEType + "/" + part.MIMESubType),
|
|
||||||
Filename: filename,
|
|
||||||
})
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return attachments
|
return attachments
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (msg *IMAPMessage) PartByID(id string) *IMAPPartNode {
|
||||||
|
if msg.BodyStructure == nil || id == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var result *IMAPPartNode
|
||||||
|
msg.BodyStructure.Walk(func(path []int, part *imap.BodyStructure) bool {
|
||||||
|
if result == nil && part.Id == "<"+id+">" {
|
||||||
|
result = newIMAPPartNode(msg, path, part)
|
||||||
|
}
|
||||||
|
return result == nil
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
type IMAPPartNode struct {
|
type IMAPPartNode struct {
|
||||||
Path []int
|
Path []int
|
||||||
MIMEType string
|
MIMEType string
|
||||||
Filename string
|
Filename string
|
||||||
Children []IMAPPartNode
|
Children []IMAPPartNode
|
||||||
|
Message *IMAPMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node IMAPPartNode) PathString() string {
|
func (node IMAPPartNode) PathString() string {
|
||||||
|
@ -182,6 +212,17 @@ func (node IMAPPartNode) PathString() string {
|
||||||
return strings.Join(l, ".")
|
return strings.Join(l, ".")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (node IMAPPartNode) URL(raw bool) *url.URL {
|
||||||
|
u := node.Message.URL()
|
||||||
|
if raw {
|
||||||
|
u.Path += "/raw"
|
||||||
|
}
|
||||||
|
q := u.Query()
|
||||||
|
q.Set("part", node.PathString())
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
|
||||||
func (node IMAPPartNode) IsText() bool {
|
func (node IMAPPartNode) IsText() bool {
|
||||||
return strings.HasPrefix(strings.ToLower(node.MIMEType), "text/")
|
return strings.HasPrefix(strings.ToLower(node.MIMEType), "text/")
|
||||||
}
|
}
|
||||||
|
@ -194,7 +235,7 @@ func (node IMAPPartNode) String() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func imapPartTree(bs *imap.BodyStructure, path []int) *IMAPPartNode {
|
func imapPartTree(msg *IMAPMessage, bs *imap.BodyStructure, path []int) *IMAPPartNode {
|
||||||
if !strings.EqualFold(bs.MIMEType, "multipart") && len(path) == 0 {
|
if !strings.EqualFold(bs.MIMEType, "multipart") && len(path) == 0 {
|
||||||
path = []int{1}
|
path = []int{1}
|
||||||
}
|
}
|
||||||
|
@ -206,6 +247,7 @@ func imapPartTree(bs *imap.BodyStructure, path []int) *IMAPPartNode {
|
||||||
MIMEType: strings.ToLower(bs.MIMEType + "/" + bs.MIMESubType),
|
MIMEType: strings.ToLower(bs.MIMEType + "/" + bs.MIMESubType),
|
||||||
Filename: filename,
|
Filename: filename,
|
||||||
Children: make([]IMAPPartNode, len(bs.Parts)),
|
Children: make([]IMAPPartNode, len(bs.Parts)),
|
||||||
|
Message: msg,
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, part := range bs.Parts {
|
for i, part := range bs.Parts {
|
||||||
|
@ -214,7 +256,7 @@ func imapPartTree(bs *imap.BodyStructure, path []int) *IMAPPartNode {
|
||||||
partPath := append([]int(nil), path...)
|
partPath := append([]int(nil), path...)
|
||||||
partPath = append(partPath, num)
|
partPath = append(partPath, num)
|
||||||
|
|
||||||
node.Children[i] = *imapPartTree(part, partPath)
|
node.Children[i] = *imapPartTree(msg, part, partPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
return node
|
return node
|
||||||
|
@ -225,7 +267,7 @@ func (msg *IMAPMessage) PartTree() *IMAPPartNode {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return imapPartTree(msg.BodyStructure, nil)
|
return imapPartTree(msg, msg.BodyStructure, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *IMAPMessage) HasFlag(flag string) bool {
|
func (msg *IMAPMessage) HasFlag(flag string) bool {
|
||||||
|
@ -265,7 +307,7 @@ func listMessages(conn *imapclient.Client, mboxName string, page, messagesPerPag
|
||||||
|
|
||||||
msgs := make([]IMAPMessage, 0, to-from)
|
msgs := make([]IMAPMessage, 0, to-from)
|
||||||
for msg := range ch {
|
for msg := range ch {
|
||||||
msgs = append(msgs, IMAPMessage{msg})
|
msgs = append(msgs, IMAPMessage{msg, mboxName})
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := <-done; err != nil {
|
if err := <-done; err != nil {
|
||||||
|
@ -350,7 +392,7 @@ func searchMessages(conn *imapclient.Client, mboxName, query string, page, messa
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
msgs[i] = IMAPMessage{msg}
|
msgs[i] = IMAPMessage{msg, mboxName}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := <-done; err != nil {
|
if err := <-done; err != nil {
|
||||||
|
@ -416,7 +458,7 @@ func getMessagePart(conn *imapclient.Client, mboxName string, uid uint32, partPa
|
||||||
return nil, nil, fmt.Errorf("failed to create message reader: %v", err)
|
return nil, nil, fmt.Errorf("failed to create message reader: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &IMAPMessage{msg}, part, nil
|
return &IMAPMessage{msg, mboxName}, part, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func markMessageAnswered(conn *imapclient.Client, mboxName string, uid uint32) error {
|
func markMessageAnswered(conn *imapclient.Client, mboxName string, uid uint32) error {
|
||||||
|
|
Loading…
Reference in a new issue