about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2019-05-25 11:56:56 -0400
committerDrew DeVault <sir@cmpwn.com>2019-05-25 11:56:56 -0400
commitcef784bf520470315e93835e9c2828d69de0d5c9 (patch)
tree1fd81d5ddcd630b4d2da5e733a85f864cc2bd0b1
parentc4c8648cc716d40f5f6558b5f2bf375d8f9a36d9 (diff)
downloadaerc-cef784bf520470315e93835e9c2828d69de0d5c9.tar.gz
Fix special characters in address.PersonalName
-rw-r--r--commands/account/reply.go40
-rw-r--r--commands/compose/send.go22
-rw-r--r--go.mod1
-rw-r--r--go.sum2
-rw-r--r--widgets/compose.go15
5 files changed, 47 insertions, 33 deletions
diff --git a/commands/account/reply.go b/commands/account/reply.go
index cd07ec9..579d671 100644
--- a/commands/account/reply.go
+++ b/commands/account/reply.go
@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"io"
 	gomail "net/mail"
+	"regexp"
 	"strings"
 
 	"git.sr.ht/~sircmpwn/getopt"
@@ -21,6 +22,25 @@ func init() {
 	register("reply", Reply)
 }
 
+var (
+	atom *regexp.Regexp = regexp.MustCompile("^[a-z0-9!#$%7'*+-/=?^_`{}|~ ]+$")
+)
+
+func formatAddress(addr *imap.Address) string {
+	if addr.PersonalName != "" {
+		if atom.MatchString(addr.PersonalName) {
+			return fmt.Sprintf("%s <%s@%s>",
+				addr.PersonalName, addr.MailboxName, addr.HostName)
+		} else {
+			return fmt.Sprintf("\"%s\" <%s@%s>",
+				strings.ReplaceAll(addr.PersonalName, "\"", "'"),
+				addr.MailboxName, addr.HostName)
+		}
+	} else {
+		return fmt.Sprintf("<%s@%s>", addr.MailboxName, addr.HostName)
+	}
+}
+
 func Reply(aerc *widgets.Aerc, args []string) error {
 	opts, optind, err := getopt.Getopts(args[1:], "aq")
 	if err != nil {
@@ -70,26 +90,14 @@ func Reply(aerc *widgets.Aerc, args []string) error {
 	}
 	if replyAll {
 		for _, addr := range msg.Envelope.Cc {
-			if addr.PersonalName != "" {
-				cc = append(cc, fmt.Sprintf("%s <%s@%s>",
-					addr.PersonalName, addr.MailboxName, addr.HostName))
-			} else {
-				cc = append(cc, fmt.Sprintf("<%s@%s>",
-					addr.MailboxName, addr.HostName))
-			}
+			cc = append(cc, formatAddress(addr))
 		}
 		for _, addr := range msg.Envelope.To {
 			address := fmt.Sprintf("%s@%s", addr.MailboxName, addr.HostName)
 			if address == us.Address {
 				continue
 			}
-			if addr.PersonalName != "" {
-				to = append(to, fmt.Sprintf("%s <%s@%s>",
-					addr.PersonalName, addr.MailboxName, addr.HostName))
-			} else {
-				to = append(to, fmt.Sprintf("<%s@%s>",
-					addr.MailboxName, addr.HostName))
-			}
+			to = append(to, formatAddress(addr))
 		}
 	}
 
@@ -103,8 +111,8 @@ func Reply(aerc *widgets.Aerc, args []string) error {
 	composer := widgets.NewComposer(
 		aerc.Config(), acct.AccountConfig(), acct.Worker()).
 		Defaults(map[string]string{
-			"To":          strings.Join(to, ","),
-			"Cc":          strings.Join(cc, ","),
+			"To":          strings.Join(to, ", "),
+			"Cc":          strings.Join(cc, ", "),
 			"Subject":     subject,
 			"In-Reply-To": msg.Envelope.MessageId,
 		}).
diff --git a/commands/compose/send.go b/commands/compose/send.go
index 2c2e294..7956aee 100644
--- a/commands/compose/send.go
+++ b/commands/compose/send.go
@@ -2,7 +2,6 @@ package compose
 
 import (
 	"crypto/tls"
-	"errors"
 	"fmt"
 	"io"
 	"net/mail"
@@ -14,6 +13,7 @@ import (
 	"github.com/emersion/go-smtp"
 	"github.com/gdamore/tcell"
 	"github.com/miolini/datacounter"
+	"github.com/pkg/errors"
 
 	"git.sr.ht/~sircmpwn/aerc/widgets"
 	"git.sr.ht/~sircmpwn/aerc/worker/types"
@@ -37,7 +37,7 @@ func SendMessage(aerc *widgets.Aerc, args []string) error {
 
 	uri, err := url.Parse(config.Outgoing)
 	if err != nil {
-		return err
+		return errors.Wrap(err, "url.Parse(outgoing)")
 	}
 	var (
 		scheme string
@@ -55,7 +55,7 @@ func SendMessage(aerc *widgets.Aerc, args []string) error {
 
 	header, rcpts, err := composer.PrepareHeader()
 	if err != nil {
-		return err
+		return errors.Wrap(err, "PrepareHeader")
 	}
 
 	if config.From == "" {
@@ -63,7 +63,7 @@ func SendMessage(aerc *widgets.Aerc, args []string) error {
 	}
 	from, err := mail.ParseAddress(config.From)
 	if err != nil {
-		return err
+		return errors.Wrap(err, "ParseAddress(config.From)")
 	}
 
 	var (
@@ -101,7 +101,7 @@ func SendMessage(aerc *widgets.Aerc, args []string) error {
 			}
 			conn, err = smtp.Dial(host)
 			if err != nil {
-				return 0, err
+				return 0, errors.Wrap(err, "smtp.Dial")
 			}
 			defer conn.Close()
 			if sup, _ := conn.Extension("STARTTLS"); sup {
@@ -114,7 +114,7 @@ func SendMessage(aerc *widgets.Aerc, args []string) error {
 				if err = conn.StartTLS(&tls.Config{
 					ServerName: serverName,
 				}); err != nil {
-					return 0, err
+					return 0, errors.Wrap(err, "StartTLS")
 				}
 			} else {
 				if starttls {
@@ -136,7 +136,7 @@ func SendMessage(aerc *widgets.Aerc, args []string) error {
 				ServerName: serverName,
 			})
 			if err != nil {
-				return 0, err
+				return 0, errors.Wrap(err, "smtp.DialTLS")
 			}
 			defer conn.Close()
 		}
@@ -144,21 +144,21 @@ func SendMessage(aerc *widgets.Aerc, args []string) error {
 		// TODO: sendmail
 		if saslClient != nil {
 			if err = conn.Auth(saslClient); err != nil {
-				return 0, err
+				return 0, errors.Wrap(err, "conn.Auth")
 			}
 		}
 		// TODO: the user could conceivably want to use a different From and sender
 		if err = conn.Mail(from.Address); err != nil {
-			return 0, err
+			return 0, errors.Wrap(err, "conn.Mail")
 		}
 		for _, rcpt := range rcpts {
 			if err = conn.Rcpt(rcpt); err != nil {
-				return 0, err
+				return 0, errors.Wrap(err, "conn.Rcpt")
 			}
 		}
 		wc, err := conn.Data()
 		if err != nil {
-			return 0, err
+			return 0, errors.Wrap(err, "conn.Data")
 		}
 		defer wc.Close()
 		ctr := datacounter.NewWriterCounter(wc)
diff --git a/go.mod b/go.mod
index 5ad0f83..f08eb90 100644
--- a/go.mod
+++ b/go.mod
@@ -21,6 +21,7 @@ require (
 	github.com/mattn/go-runewidth v0.0.2
 	github.com/miolini/datacounter v0.0.0-20171104152933-fd4e42a1d5e0
 	github.com/mitchellh/go-homedir v1.1.0
+	github.com/pkg/errors v0.8.1
 	github.com/riywo/loginshell v0.0.0-20181227004642-c2f4167b2303
 	github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a // indirect
 	github.com/stretchr/testify v1.3.0
diff --git a/go.sum b/go.sum
index 457f76e..e444137 100644
--- a/go.sum
+++ b/go.sum
@@ -51,6 +51,8 @@ github.com/miolini/datacounter v0.0.0-20171104152933-fd4e42a1d5e0 h1:clkDYGefEWU
 github.com/miolini/datacounter v0.0.0-20171104152933-fd4e42a1d5e0/go.mod h1:P6fDJzlxN+cWYR09KbE9/ta+Y6JofX9tAUhJpWkWPaM=
 github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/riywo/loginshell v0.0.0-20181227004642-c2f4167b2303 h1:iVSzuQeMQqR6xo15tY215nUTBmrgpTq0Qwaw+YEil24=
diff --git a/widgets/compose.go b/widgets/compose.go
index 96ee7e7..9de7f97 100644
--- a/widgets/compose.go
+++ b/widgets/compose.go
@@ -12,6 +12,7 @@ import (
 	"github.com/emersion/go-message/mail"
 	"github.com/gdamore/tcell"
 	"github.com/mattn/go-runewidth"
+	"github.com/pkg/errors"
 
 	"git.sr.ht/~sircmpwn/aerc/config"
 	"git.sr.ht/~sircmpwn/aerc/lib"
@@ -232,11 +233,11 @@ func (c *Composer) PrepareHeader() (*mail.Header, []string, error) {
 		// your types aren't compatible enough with each other
 		to_rcpts, err := gomail.ParseAddressList(to)
 		if err != nil {
-			return nil, nil, err
+			return nil, nil, errors.Wrapf(err, "ParseAddressList(%s)", to)
 		}
 		ed_rcpts, err := header.AddressList("To")
 		if err != nil {
-			return nil, nil, err
+			return nil, nil, errors.Wrap(err, "AddressList(To)")
 		}
 		for _, addr := range to_rcpts {
 			ed_rcpts = append(ed_rcpts, (*mail.Address)(addr))
@@ -266,7 +267,7 @@ func (c *Composer) WriteMessage(header *mail.Header, writer io.Writer) error {
 		// into the editor? If so this needs to change
 		part, err := reader.NextPart()
 		if err != nil {
-			return err
+			return errors.Wrap(err, "reader.NextPart")
 		}
 		body = part.Body
 		defer reader.Close()
@@ -277,11 +278,13 @@ func (c *Composer) WriteMessage(header *mail.Header, writer io.Writer) error {
 	// TODO: attachments
 	w, err := mail.CreateSingleInlineWriter(writer, *header)
 	if err != nil {
-		return err
+		return errors.Wrap(err, "CreateSingleInlineWriter")
 	}
 	defer w.Close()
-	_, err = io.Copy(w, body)
-	return err
+	if _, err := io.Copy(w, body); err != nil {
+		return errors.Wrap(err, "io.Copy")
+	}
+	return nil
 }
 
 func (c *Composer) termClosed(err error) {