~sircmpwn/aerc

Mailing list for aerc development.

7 3

[PATCH] Add signatures

Details
Message ID
<20190907213340.872-1-dev@jeffas.io>
DKIM signature
missing
Download raw message
Patch: +44 -3
This adds the ability for a per-account signature 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 is a config option and this has parsing associated when set. This
ensures newlines and some other escape sequences work as expected.

The option is also documented in the man page.
---
 commands/account/compose.go |  2 +-
 commands/msg/forward.go     |  2 +-
 commands/msg/reply.go       |  2 +-
 config/config.go            | 15 +++++++++++++++
 doc/aerc-config.5.scd       |  3 +++
 widgets/compose.go          | 23 +++++++++++++++++++++++
 6 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/commands/account/compose.go b/commands/account/compose.go
index ad48fe6..c8358a7 100644
--- a/commands/account/compose.go
+++ b/commands/account/compose.go
@@ -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 b925a49..c443213 100644
--- a/commands/msg/forward.go
+++ b/commands/msg/forward.go
@@ -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 34d03d5..ade4bdc 100644
--- a/commands/msg/reply.go
+++ b/commands/msg/reply.go
@@ -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/config/config.go b/config/config.go
index 06caec1..f555dd6 100644
--- a/config/config.go
+++ b/config/config.go
@@ -54,6 +54,7 @@ type AccountConfig struct {
 	Params          map[string]string
 	Outgoing        string
 	OutgoingCredCmd string
+	Signature       string
 }

 type BindingConfig struct {
@@ -180,6 +181,20 @@ func loadAccountConfig(path string) ([]AccountConfig, error) {
 		}
 		account.Outgoing = outgoing

+		if account.Signature != "" {
+			type conversion struct {
+				o string
+				n string
+			}
+			conversions := []conversion{
+				conversion{o: "\\n", n: "\n"},
+				conversion{o: "\\r", n: "\r"},
+				conversion{o: "\\t", n: "\t"}}
+			for _, conversion := range conversions {
+				account.Signature = strings.ReplaceAll(account.Signature, conversion.o, conversion.n)
+			}
+		}
+
 		accounts = append(accounts, account)
 	}
 	return accounts, nil
diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd
index 9257bde..51c5c2f 100644
--- a/doc/aerc-config.5.scd
+++ b/doc/aerc-config.5.scd
@@ -281,6 +281,9 @@ 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*
+	Specifies the signature to be added to emails sent from this account.
+

 # BINDS.CONF

diff --git a/widgets/compose.go b/widgets/compose.go
index bd4301a..fa9e544 100644
--- a/widgets/compose.go
+++ b/widgets/compose.go
@@ -2,6 +2,7 @@ package widgets

 import (
 	"bufio"
+	"bytes"
 	"io"
 	"io/ioutil"
 	"mime"
@@ -78,6 +79,8 @@ func NewComposer(conf *config.AercConfig,
 		focusable: focusable,
 	}

+	c.AddSignature()
+
 	c.updateGrid()
 	c.ShowTerminal()

@@ -138,6 +141,26 @@ 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() {
+	c.AppendContents(strings.NewReader(c.acct.Signature))
+}
+
 func (c *Composer) FocusTerminal() *Composer {
 	if c.editor == nil {
 		return c
--
2.23.0
Details
Message ID
<BWXB3XF7UGDV.YOYCD1B8F028@homura>
In-Reply-To
<20190907213340.872-1-dev@jeffas.io> (view parent)
DKIM signature
pass
Download raw message
I would rather use a signature file than a literal string in the config.
Alex
Details
Message ID
<BWXCXCMA4YSE.1COR7WYWABW2K@alex-pc>
In-Reply-To
<BWXB3XF7UGDV.YOYCD1B8F028@homura> (view parent)
DKIM signature
pass
Download raw message
I'd love if this feature could not only read from a file, but also allow
dynamic signatures via a callable script, and potentially allow for
different signature "files" for different accounts, or to different
users.  I have something like this in Mutt.

I understand this wouldn't be a simple patch though, but using a file
would lend a few more options at least.
Details
Message ID
<BWXD3X5LAUR3.2HL433BXIX64I@xps-15>
In-Reply-To
<BWXCXCMA4YSE.1COR7WYWABW2K@alex-pc> (view parent)
DKIM signature
missing
Download raw message
> I'd love if this feature could not only read from a file, but also allow
> dynamic signatures via a callable script

This would be cool.

It could be a 'signature' field in the accounts config which is checked
to be a file. If it is a file then we read it and use it as a static
signature. If it isn't a file, try to execute it as a command and
collect the output for the signature. Non-zero exit code from the
command ignores the output.

How does this sound?

> and potentially allow for different signature "files" for different
> accounts, or to different users.

Yes, the current config option is in 'accounts.conf' so is per
user-account.

> I understand this wouldn't be a simple patch though, but using a file
> would lend a few more options at least.

This doesn't sound too bad to do. I'm having a look now.
Details
Message ID
<BWXD4JTC2QPO.2NP5Y1TLZLEI@homura>
In-Reply-To
<BWXD3X5LAUR3.2HL433BXIX64I@xps-15> (view parent)
DKIM signature
pass
Download raw message
On Wed Sep 11, 2019 at 6:51 PM Jeffas wrote:
> It could be a 'signature' field in the accounts config which is checked
> to be a file. If it is a file then we read it and use it as a static
> signature. If it isn't a file, try to execute it as a command and
> collect the output for the signature. Non-zero exit code from the
> command ignores the output.
> 
> How does this sound?

I would prefer a separate "signature-cmd" config option.
Details
Message ID
<BWXD6H5FV9Y2.17IO9NNA5YVKY@xps-15>
In-Reply-To
<BWXD4JTC2QPO.2NP5Y1TLZLEI@homura> (view parent)
DKIM signature
missing
Download raw message
On Wed Sep 11, 2019 at 1:52 PM Drew DeVault wrote:
> I would prefer a separate "signature-cmd" config option.

That was also on my mind. What should happen if both are specified?
Details
Message ID
<BWXD79IYXIGW.Z1K9NWOT0U0G@homura>
In-Reply-To
<BWXD6H5FV9Y2.17IO9NNA5YVKY@xps-15> (view parent)
DKIM signature
pass
Download raw message
Error during config load? Or perhaps use the non-cmd version as a
fallback for if the command exits with a nonzero status.
Details
Message ID
<BWXDAXA914Y6.3K8EVSTR7VBSD@xps-15>
In-Reply-To
<BWXD79IYXIGW.Z1K9NWOT0U0G@homura> (view parent)
DKIM signature
missing
Download raw message
I like the idea of using the file as the fallback for the command.