aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeffas <dev@jeffas.io>2019-09-11 20:28:14 +0100
committerDrew DeVault <sir@cmpwn.com>2019-09-12 16:18:34 -0400
commite2d5c456dc27f958d79fdf740c7b0852b2af4160 (patch)
tree0e8b75b1996e142cb5b980ffe507634c5ff2fa03
parenta93b4de6f3c362d6e0db0b1f6d3f2e1c9a5cd64d (diff)
downloadaerc-e2d5c456dc27f958d79fdf740c7b0852b2af4160.tar.gz
Add signatures
This adds the ability for per-account signatures in the accounts.conf config file. The signature is added to emails in the editor at the bottom of the email. This includes when forwarding, replying to, and composing emails. There are two config options: signature-file and signature-cmd. The former allows a signature to be read from a file and the latter allows an arbitrary command to be executed to return the signature. The config options have been documented in aerc-config
-rw-r--r--commands/account/compose.go4
-rw-r--r--commands/msg/forward.go4
-rw-r--r--commands/msg/reply.go6
-rw-r--r--commands/msg/unsubscribe.go1
-rw-r--r--config/config.go2
-rw-r--r--doc/aerc-config.5.scd8
-rw-r--r--widgets/aerc.go2
-rw-r--r--widgets/compose.go66
8 files changed, 84 insertions, 9 deletions
diff --git a/commands/account/compose.go b/commands/account/compose.go
index ad48fe61..039eb923 100644
--- a/commands/account/compose.go
+++ b/commands/account/compose.go
@@ -29,7 +29,7 @@ func (Compose) Execute(aerc *widgets.Aerc, args []string) error {
return err
}
acct := aerc.SelectedAccount()
- composer := widgets.NewComposer(
+ composer := widgets.NewComposer(aerc,
aerc.Config(), acct.AccountConfig(), acct.Worker(), nil)
tab := aerc.NewTab(composer, "New email")
composer.OnHeaderChange("Subject", func(subject string) {
@@ -40,7 +40,7 @@ func (Compose) Execute(aerc *widgets.Aerc, args []string) error {
}
tab.Content.Invalidate()
})
- go composer.SetContents(strings.NewReader(body))
+ go composer.PrependContents(strings.NewReader(body))
return nil
}
diff --git a/commands/msg/forward.go b/commands/msg/forward.go
index b925a497..494072d0 100644
--- a/commands/msg/forward.go
+++ b/commands/msg/forward.go
@@ -69,7 +69,7 @@ func (forward) Execute(aerc *widgets.Aerc, args []string) error {
"To": to,
"Subject": subject,
}
- composer := widgets.NewComposer(aerc.Config(), acct.AccountConfig(),
+ composer := widgets.NewComposer(aerc, aerc.Config(), acct.AccountConfig(),
acct.Worker(), defaults)
addTab := func() {
@@ -154,7 +154,7 @@ func forwardBodyPart(store *lib.MessageStore, composer *widgets.Composer,
pipeout, pipein := io.Pipe()
scanner := bufio.NewScanner(part.Body)
- go composer.SetContents(pipeout)
+ go composer.PrependContents(pipeout)
// TODO: Let user customize the date format used here
io.WriteString(pipein, fmt.Sprintf("Forwarded message from %s on %s:\n\n",
msg.Envelope.From[0].Name,
diff --git a/commands/msg/reply.go b/commands/msg/reply.go
index 7c40e979..9ef7a3b8 100644
--- a/commands/msg/reply.go
+++ b/commands/msg/reply.go
@@ -116,8 +116,8 @@ func (reply) Execute(aerc *widgets.Aerc, args []string) error {
"In-Reply-To": msg.Envelope.MessageId,
}
- composer := widgets.NewComposer(
- aerc.Config(), acct.AccountConfig(), acct.Worker(), defaults)
+ composer := widgets.NewComposer(aerc, aerc.Config(),
+ acct.AccountConfig(), acct.Worker(), defaults)
if args[0] == "reply" {
composer.FocusTerminal()
@@ -170,7 +170,7 @@ func (reply) Execute(aerc *widgets.Aerc, args []string) error {
pipeout, pipein := io.Pipe()
scanner := bufio.NewScanner(part.Body)
- go composer.SetContents(pipeout)
+ go composer.PrependContents(pipeout)
// TODO: Let user customize the date format used here
io.WriteString(pipein, fmt.Sprintf("On %s %s wrote:\n",
msg.Envelope.Date.Format("Mon Jan 2, 2006 at 3:04 PM"),
diff --git a/commands/msg/unsubscribe.go b/commands/msg/unsubscribe.go
index f18da075..15a9411c 100644
--- a/commands/msg/unsubscribe.go
+++ b/commands/msg/unsubscribe.go
@@ -88,6 +88,7 @@ func unsubscribeMailto(aerc *widgets.Aerc, u *url.URL) error {
"Subject": u.Query().Get("subject"),
}
composer := widgets.NewComposer(
+ aerc,
aerc.Config(),
acct.AccountConfig(),
acct.Worker(),
diff --git a/config/config.go b/config/config.go
index 738fd1d8..eeaf9370 100644
--- a/config/config.go
+++ b/config/config.go
@@ -55,6 +55,8 @@ type AccountConfig struct {
Params map[string]string
Outgoing string
OutgoingCredCmd string
+ SignatureFile string
+ SignatureCmd string
}
type BindingConfig struct {
diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd
index d422e5df..91b444a5 100644
--- a/doc/aerc-config.5.scd
+++ b/doc/aerc-config.5.scd
@@ -297,6 +297,14 @@ Note that many of these configuration options are written for you, such as
Specifies an optional command that is run to get the source account's
password. See each protocol's man page for more details.
+*signature-file*
+ Specifies the file to read in order to obtain the signature to be added
+ to emails sent from this account.
+
+*signature-cmd*
+ Specifies the command to execute in *sh* in order to obtain the
+ signature to be added to emails sent from this account. If the command
+ fails then *signature-file* is used instead.
# BINDS.CONF
diff --git a/widgets/aerc.go b/widgets/aerc.go
index fe3c1e21..8671c87b 100644
--- a/widgets/aerc.go
+++ b/widgets/aerc.go
@@ -430,7 +430,7 @@ func (aerc *Aerc) Mailto(addr *url.URL) error {
defaults[header] = strings.Join(vals, ",")
}
}
- composer := NewComposer(aerc.Config(),
+ composer := NewComposer(aerc, aerc.Config(),
acct.AccountConfig(), acct.Worker(), defaults)
composer.FocusSubject()
title := "New email"
diff --git a/widgets/compose.go b/widgets/compose.go
index 0e7f09e6..22c58da5 100644
--- a/widgets/compose.go
+++ b/widgets/compose.go
@@ -2,6 +2,8 @@ package widgets
import (
"bufio"
+ "bytes"
+ "fmt"
"io"
"io/ioutil"
"mime"
@@ -17,6 +19,7 @@ import (
"github.com/emersion/go-message/mail"
"github.com/gdamore/tcell"
"github.com/mattn/go-runewidth"
+ "github.com/mitchellh/go-homedir"
"github.com/pkg/errors"
"git.sr.ht/~sircmpwn/aerc/config"
@@ -29,6 +32,7 @@ type Composer struct {
acct *config.AccountConfig
config *config.AercConfig
+ aerc *Aerc
defaults map[string]string
editor *Terminal
@@ -48,7 +52,7 @@ type Composer struct {
width int
}
-func NewComposer(conf *config.AercConfig,
+func NewComposer(aerc *Aerc, conf *config.AercConfig,
acct *config.AccountConfig, worker *types.Worker, defaults map[string]string) *Composer {
if defaults == nil {
@@ -68,6 +72,7 @@ func NewComposer(conf *config.AercConfig,
}
c := &Composer{
+ aerc: aerc,
editors: editors,
acct: acct,
config: conf,
@@ -80,6 +85,8 @@ func NewComposer(conf *config.AercConfig,
focusable: focusable,
}
+ c.AddSignature()
+
c.updateGrid()
c.ShowTerminal()
@@ -140,6 +147,63 @@ func (c *Composer) SetContents(reader io.Reader) *Composer {
return c
}
+func (c *Composer) PrependContents(reader io.Reader) {
+ buf := bytes.NewBuffer(nil)
+ c.email.Seek(0, io.SeekStart)
+ io.Copy(buf, c.email)
+ c.email.Seek(0, io.SeekStart)
+ io.Copy(c.email, reader)
+ io.Copy(c.email, buf)
+ c.email.Sync()
+}
+
+func (c *Composer) AppendContents(reader io.Reader) {
+ c.email.Seek(0, io.SeekEnd)
+ io.Copy(c.email, reader)
+ c.email.Sync()
+}
+
+func (c *Composer) AddSignature() {
+ var signature []byte
+ if c.acct.SignatureCmd != "" {
+ var err error
+ signature, err = c.readSignatureFromCmd()
+ if err != nil {
+ signature = c.readSignatureFromFile()
+ }
+ } else {
+ signature = c.readSignatureFromFile()
+ }
+ c.AppendContents(bytes.NewReader(signature))
+}
+
+func (c *Composer) readSignatureFromCmd() ([]byte, error) {
+ sigCmd := c.acct.SignatureCmd
+ cmd := exec.Command("sh", "-c", sigCmd)
+ signature, err := cmd.Output()
+ if err != nil {
+ return nil, err
+ }
+ return signature, nil
+}
+
+func (c *Composer) readSignatureFromFile() []byte {
+ sigFile := c.acct.SignatureFile
+ if sigFile == "" {
+ return nil
+ }
+ sigFile, err := homedir.Expand(sigFile)
+ if err != nil {
+ return nil
+ }
+ signature, err := ioutil.ReadFile(sigFile)
+ if err != nil {
+ c.aerc.PushError(fmt.Sprintf(" Error loading signature from file: %v", sigFile))
+ return nil
+ }
+ return signature
+}
+
func (c *Composer) FocusTerminal() *Composer {
if c.editor == nil {
return c