From ccc77f980e9fa959c2c931932c4613d3116a2082 Mon Sep 17 00:00:00 2001 From: Knut Ahlers Date: Sat, 27 Jun 2020 15:48:20 +0200 Subject: [PATCH] Add get_attachment command Signed-off-by: Knut Ahlers --- commands.go | 32 +++++++++++++++++++++++++++----- handler.go | 27 +-------------------------- transport.go | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 31 deletions(-) create mode 100644 transport.go diff --git a/commands.go b/commands.go index 64196a9..8780f97 100644 --- a/commands.go +++ b/commands.go @@ -6,11 +6,13 @@ import ( "github.com/emersion/go-imap" "github.com/emersion/go-imap/client" + "github.com/jhillyerd/enmime" "github.com/pkg/errors" + log "github.com/sirupsen/logrus" ) type command interface { - Execute(*client.Client, *imap.Message, io.Writer) error + Execute(*client.Client, *imap.Message, *enmime.Envelope, io.Writer) error } type commandTypeWrap struct { @@ -31,6 +33,9 @@ func (c commandTypeWrap) rewrap(data []byte) (command, error) { case "del_flags": out = new(commandDelFlags) + case "get_attachment": + out = new(commandGetAttachment) + case "set_flags": out = new(commandSetFlags) @@ -46,7 +51,7 @@ type commandMove struct { ToMailbox string `json:"to_mailbox"` } -func (c commandMove) Execute(client *client.Client, msg *imap.Message, stdin io.Writer) error { +func (c commandMove) Execute(client *client.Client, msg *imap.Message, mail *enmime.Envelope, stdin io.Writer) error { s := &imap.SeqSet{} s.AddNum(msg.Uid) @@ -64,7 +69,7 @@ type commandAddFlags struct { Flags []string `json:"flags"` } -func (c commandAddFlags) Execute(client *client.Client, msg *imap.Message, stdin io.Writer) error { +func (c commandAddFlags) Execute(client *client.Client, msg *imap.Message, mail *enmime.Envelope, stdin io.Writer) error { var ( flags []interface{} s = &imap.SeqSet{} @@ -85,7 +90,7 @@ type commandDelFlags struct { Flags []string `json:"flags"` } -func (c commandDelFlags) Execute(client *client.Client, msg *imap.Message, stdin io.Writer) error { +func (c commandDelFlags) Execute(client *client.Client, msg *imap.Message, mail *enmime.Envelope, stdin io.Writer) error { var ( flags []interface{} s = &imap.SeqSet{} @@ -102,11 +107,28 @@ func (c commandDelFlags) Execute(client *client.Client, msg *imap.Message, stdin ) } +type commandGetAttachment struct { + Filename string `json:"filename"` +} + +func (c commandGetAttachment) Execute(client *client.Client, msg *imap.Message, mail *enmime.Envelope, stdin io.Writer) error { + a := attachmentFromMail(mail, c.Filename) + if a == nil { + log.WithFields(log.Fields{ + "uid": msg.Uid, + "filename": c.Filename, + }).Error("Requested attachment not found") + return errors.New("Attachment not found") + } + + return errors.Wrap(json.NewEncoder(stdin).Encode(a), "Unable to encode attachment to JSON") +} + type commandSetFlags struct { Flags []string `json:"flags"` } -func (c commandSetFlags) Execute(client *client.Client, msg *imap.Message, stdin io.Writer) error { +func (c commandSetFlags) Execute(client *client.Client, msg *imap.Message, mail *enmime.Envelope, stdin io.Writer) error { var ( flags []interface{} s = &imap.SeqSet{} diff --git a/handler.go b/handler.go index 9db801f..ad0d79c 100644 --- a/handler.go +++ b/handler.go @@ -15,31 +15,6 @@ import ( log "github.com/sirupsen/logrus" ) -type mailTransport struct { - Attachments []string `json:"attachments"` - Headers map[string]string `json:"headers"` - HTML string `json:"html"` - Text string `json:"text"` -} - -func mailToTransport(msg *enmime.Envelope) *mailTransport { - var out = &mailTransport{ - Headers: map[string]string{}, - HTML: msg.HTML, - Text: msg.Text, - } - - for _, a := range msg.Attachments { - out.Attachments = append(out.Attachments, a.FileName) - } - - for _, hn := range msg.GetHeaderKeys() { - out.Headers[hn] = msg.GetHeader(hn) - } - - return out -} - type mailHandler struct { Match []matcher `yaml:"match"` Command []string `yaml:"command"` @@ -89,7 +64,7 @@ func (m mailHandler) Process(imapClient *client.Client, msg *imap.Message, envel continue } - if err = c.Execute(imapClient, msg, stdin); err != nil { + if err = c.Execute(imapClient, msg, envelope, stdin); err != nil { log.WithError(err).Error("Unable to execute command") continue } diff --git a/transport.go b/transport.go new file mode 100644 index 0000000..5d6706e --- /dev/null +++ b/transport.go @@ -0,0 +1,52 @@ +package main + +import ( + "encoding/base64" + + "github.com/jhillyerd/enmime" +) + +type attachmentTransport struct { + FileName string + Content string + ContentType string +} + +func attachmentFromMail(msg *enmime.Envelope, filename string) *attachmentTransport { + for _, a := range msg.Attachments { + if a.FileName == filename { + return &attachmentTransport{ + Content: base64.StdEncoding.EncodeToString(a.Content), + ContentType: a.ContentType, + FileName: a.FileName, + } + } + } + + return nil +} + +type mailTransport struct { + Attachments []string `json:"attachments"` + Headers map[string]string `json:"headers"` + HTML string `json:"html"` + Text string `json:"text"` +} + +func mailToTransport(msg *enmime.Envelope) *mailTransport { + var out = &mailTransport{ + Headers: map[string]string{}, + HTML: msg.HTML, + Text: msg.Text, + } + + for _, a := range msg.Attachments { + out.Attachments = append(out.Attachments, a.FileName) + } + + for _, hn := range msg.GetHeaderKeys() { + out.Headers[hn] = msg.GetHeader(hn) + } + + return out +}