aboutsummaryrefslogtreecommitdiff
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)
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()