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) {