Add forwarding as attachment feature
This allows a single message to be forward as attachment with the :forward -a command
This commit is contained in:
parent
36c6030e81
commit
1f5293931a
3 changed files with 73 additions and 5 deletions
|
@ -4,10 +4,16 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"git.sr.ht/~sircmpwn/aerc/lib"
|
||||||
|
"git.sr.ht/~sircmpwn/aerc/models"
|
||||||
"git.sr.ht/~sircmpwn/aerc/widgets"
|
"git.sr.ht/~sircmpwn/aerc/widgets"
|
||||||
|
"git.sr.ht/~sircmpwn/getopt"
|
||||||
"github.com/emersion/go-message"
|
"github.com/emersion/go-message"
|
||||||
"github.com/emersion/go-message/mail"
|
"github.com/emersion/go-message/mail"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -26,9 +32,21 @@ func (_ forward) Complete(aerc *widgets.Aerc, args []string) []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_ forward) Execute(aerc *widgets.Aerc, args []string) error {
|
func (_ forward) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
|
opts, optind, err := getopt.Getopts(args, "A")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
attach := false
|
||||||
|
for _, opt := range opts {
|
||||||
|
switch opt.Option {
|
||||||
|
case 'A':
|
||||||
|
attach = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
to := ""
|
to := ""
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
to = strings.Join(args[1:], ", ")
|
to = strings.Join(args[optind:], ", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
widget := aerc.SelectedTab().(widgets.ProvidesMessage)
|
widget := aerc.SelectedTab().(widgets.ProvidesMessage)
|
||||||
|
@ -56,7 +74,7 @@ func (_ forward) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
|
|
||||||
addTab := func() {
|
addTab := func() {
|
||||||
tab := aerc.NewTab(composer, subject)
|
tab := aerc.NewTab(composer, subject)
|
||||||
if len(args) == 1 {
|
if to == "" {
|
||||||
composer.FocusRecipient()
|
composer.FocusRecipient()
|
||||||
} else {
|
} else {
|
||||||
composer.FocusTerminal()
|
composer.FocusTerminal()
|
||||||
|
@ -71,6 +89,46 @@ func (_ forward) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if attach {
|
||||||
|
forwardAttach(store, composer, msg, addTab)
|
||||||
|
} else {
|
||||||
|
forwardBodyPart(store, composer, msg, addTab)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func forwardAttach(store *lib.MessageStore, composer *widgets.Composer,
|
||||||
|
msg *models.MessageInfo, addTab func()) {
|
||||||
|
|
||||||
|
store.FetchFull([]uint32{msg.Uid}, func(reader io.Reader) {
|
||||||
|
tmpDir, err := ioutil.TempDir("", "aerc-tmp-attachment")
|
||||||
|
if err != nil {
|
||||||
|
// TODO: Do something with the error
|
||||||
|
addTab()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tmpFileName := path.Join(tmpDir,
|
||||||
|
strings.ReplaceAll(fmt.Sprintf("%s.eml", msg.Envelope.Subject), "/", "-"))
|
||||||
|
tmpFile, err := os.Create(tmpFileName)
|
||||||
|
if err != nil {
|
||||||
|
println(err)
|
||||||
|
// TODO: Do something with the error
|
||||||
|
addTab()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer tmpFile.Close()
|
||||||
|
io.Copy(tmpFile, reader)
|
||||||
|
composer.AddAttachment(tmpFileName)
|
||||||
|
composer.OnClose(func(composer *widgets.Composer) {
|
||||||
|
os.RemoveAll(tmpDir)
|
||||||
|
})
|
||||||
|
addTab()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func forwardBodyPart(store *lib.MessageStore, composer *widgets.Composer,
|
||||||
|
msg *models.MessageInfo, addTab func()) {
|
||||||
// TODO: something more intelligent than fetching the 1st part
|
// TODO: something more intelligent than fetching the 1st part
|
||||||
// TODO: add attachments!
|
// TODO: add attachments!
|
||||||
store.FetchBodyPart(msg.Uid, []int{1}, func(reader io.Reader) {
|
store.FetchBodyPart(msg.Uid, []int{1}, func(reader io.Reader) {
|
||||||
|
@ -108,5 +166,4 @@ func (_ forward) Execute(aerc *widgets.Aerc, args []string) error {
|
||||||
pipeout.Close()
|
pipeout.Close()
|
||||||
addTab()
|
addTab()
|
||||||
})
|
})
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,9 +90,11 @@ message list, the message in the message viewer, etc).
|
||||||
*delete*
|
*delete*
|
||||||
Deletes the selected message.
|
Deletes the selected message.
|
||||||
|
|
||||||
*forward* [address...]
|
*forward* [-A] [address...]
|
||||||
Opens the composer to forward the selected message to another recipient.
|
Opens the composer to forward the selected message to another recipient.
|
||||||
|
|
||||||
|
*-A*: Forward the message as an RFC 8022 attachment.
|
||||||
|
|
||||||
*move* <target>
|
*move* <target>
|
||||||
Moves the selected message to the target folder.
|
Moves the selected message to the target folder.
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,8 @@ type Composer struct {
|
||||||
layout HeaderLayout
|
layout HeaderLayout
|
||||||
focusable []ui.DrawableInteractive
|
focusable []ui.DrawableInteractive
|
||||||
focused int
|
focused int
|
||||||
|
|
||||||
|
onClose []func(ti *Composer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewComposer(conf *config.AercConfig,
|
func NewComposer(conf *config.AercConfig,
|
||||||
|
@ -169,6 +171,10 @@ func (c *Composer) OnHeaderChange(header string, fn func(subject string)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Composer) OnClose(fn func(composer *Composer)) {
|
||||||
|
c.onClose = append(c.onClose, fn)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Composer) Draw(ctx *ui.Context) {
|
func (c *Composer) Draw(ctx *ui.Context) {
|
||||||
c.grid.Draw(ctx)
|
c.grid.Draw(ctx)
|
||||||
}
|
}
|
||||||
|
@ -184,6 +190,9 @@ func (c *Composer) OnInvalidate(fn func(d ui.Drawable)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Composer) Close() {
|
func (c *Composer) Close() {
|
||||||
|
for _, onClose := range c.onClose {
|
||||||
|
onClose(c)
|
||||||
|
}
|
||||||
if c.email != nil {
|
if c.email != nil {
|
||||||
path := c.email.Name()
|
path := c.email.Name()
|
||||||
c.email.Close()
|
c.email.Close()
|
||||||
|
|
Loading…
Reference in a new issue