about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJelle Besseling <jelle@pingiun.com>2019-08-18 11:33:15 +0200
committerDrew DeVault <sir@cmpwn.com>2019-08-20 10:05:51 +0900
commit1f5293931adf591fcbeaa9a272d717240da9213a (patch)
tree4b14e64f11fd283341607842ea8acd3ca4ccaf94
parent36c6030e81b229414bb42bf7fc37d091c6497ddf (diff)
downloadaerc-1f5293931adf591fcbeaa9a272d717240da9213a.tar.gz
Add forwarding as attachment feature
This allows a single message to be forward as attachment with the
:forward -a command
-rw-r--r--commands/msg/forward.go65
-rw-r--r--doc/aerc.1.scd4
-rw-r--r--widgets/compose.go9
3 files changed, 73 insertions, 5 deletions
diff --git a/commands/msg/forward.go b/commands/msg/forward.go
index ca29096..7f23a0a 100644
--- a/commands/msg/forward.go
+++ b/commands/msg/forward.go
@@ -4,10 +4,16 @@ import (
 	"bufio"
 	"errors"
 	"fmt"
+	"git.sr.ht/~sircmpwn/aerc/lib"
+	"git.sr.ht/~sircmpwn/aerc/models"
 	"git.sr.ht/~sircmpwn/aerc/widgets"
+	"git.sr.ht/~sircmpwn/getopt"
 	"github.com/emersion/go-message"
 	"github.com/emersion/go-message/mail"
 	"io"
+	"io/ioutil"
+	"os"
+	"path"
 	"strings"
 )
 
@@ -26,9 +32,21 @@ func (_ forward) Complete(aerc *widgets.Aerc, args []string) []string {
 }
 
 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 := ""
 	if len(args) != 1 {
-		to = strings.Join(args[1:], ", ")
+		to = strings.Join(args[optind:], ", ")
 	}
 
 	widget := aerc.SelectedTab().(widgets.ProvidesMessage)
@@ -48,7 +66,7 @@ func (_ forward) Execute(aerc *widgets.Aerc, args []string) error {
 
 	subject := "Fwd: " + msg.Envelope.Subject
 	defaults := map[string]string{
-		"To": to,
+		"To":      to,
 		"Subject": subject,
 	}
 	composer := widgets.NewComposer(aerc.Config(), acct.AccountConfig(),
@@ -56,7 +74,7 @@ func (_ forward) Execute(aerc *widgets.Aerc, args []string) error {
 
 	addTab := func() {
 		tab := aerc.NewTab(composer, subject)
-		if len(args) == 1 {
+		if to == "" {
 			composer.FocusRecipient()
 		} else {
 			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: add attachments!
 	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()
 		addTab()
 	})
-	return nil
 }
diff --git a/doc/aerc.1.scd b/doc/aerc.1.scd
index e172f89..4aa777c 100644
--- a/doc/aerc.1.scd
+++ b/doc/aerc.1.scd
@@ -90,9 +90,11 @@ message list, the message in the message viewer, etc).
 *delete*
 	Deletes the selected message.
 
-*forward* [address...]
+*forward* [-A] [address...]
 	Opens the composer to forward the selected message to another recipient.
 
+	*-A*: Forward the message as an RFC 8022 attachment.
+
 *move* <target>
 	Moves the selected message to the target folder.
 
diff --git a/widgets/compose.go b/widgets/compose.go
index b4ae078..a49a947 100644
--- a/widgets/compose.go
+++ b/widgets/compose.go
@@ -42,6 +42,8 @@ type Composer struct {
 	layout    HeaderLayout
 	focusable []ui.DrawableInteractive
 	focused   int
+
+	onClose []func(ti *Composer)
 }
 
 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) {
 	c.grid.Draw(ctx)
 }
@@ -184,6 +190,9 @@ func (c *Composer) OnInvalidate(fn func(d ui.Drawable)) {
 }
 
 func (c *Composer) Close() {
+	for _, onClose := range c.onClose {
+		onClose(c)
+	}
 	if c.email != nil {
 		path := c.email.Name()
 		c.email.Close()