diff options
| author | Drew DeVault <sir@cmpwn.com> | 2019-05-16 12:15:34 -0400 | 
|---|---|---|
| committer | Drew DeVault <sir@cmpwn.com> | 2019-05-16 12:15:34 -0400 | 
| commit | 475b697bdfd7a5821282174f14f8d904e47aff4d (patch) | |
| tree | 7febf2e25cede5809f1d40c934d379315e06bd64 | |
| parent | 2b3e123cb86f9b4c5853e31d9e76c2b0d083f90a (diff) | |
Implement (basic form) of :reply
| -rw-r--r-- | commands/account/reply.go | 83 | ||||
| -rw-r--r-- | go.mod | 1 | ||||
| -rw-r--r-- | go.sum | 2 | ||||
| -rw-r--r-- | lib/msgid.go | 34 | ||||
| -rw-r--r-- | widgets/account.go | 12 | ||||
| -rw-r--r-- | widgets/compose.go | 14 | 
6 files changed, 139 insertions, 7 deletions
diff --git a/commands/account/reply.go b/commands/account/reply.go new file mode 100644 index 0000000..d0d65a5 --- /dev/null +++ b/commands/account/reply.go @@ -0,0 +1,83 @@ +package account + +import ( +	"errors" +	"fmt" +	"strings" + +	"github.com/emersion/go-imap" + +	"git.sr.ht/~sircmpwn/aerc2/widgets" +) + +func init() { +	register("reply", Reply) +} + +func Reply(aerc *widgets.Aerc, args []string) error { +	if len(args) != 1 { +		return errors.New("Usage: reply [-aq]") +	} +	// TODO: Reply all (w/ getopt) + +	acct := aerc.SelectedAccount() +	msg := acct.Messages().Selected() +	acct.Logger().Println("Replying to email " + msg.Envelope.MessageId) + +	var ( +		to     []string +		cc     []string +		toList []*imap.Address +	) +	if len(msg.Envelope.ReplyTo) != 0 { +		toList = msg.Envelope.ReplyTo +	} else { +		toList = msg.Envelope.From +	} +	for _, addr := range toList { +		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)) +		} +	} +	// TODO: Only if reply all +	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)) +		} +	} + +	subject := "Re: " + msg.Envelope.Subject + +	composer := widgets.NewComposer( +		aerc.Config(), acct.AccountConfig(), acct.Worker()). +		Defaults(map[string]string{ +			"To": strings.Join(to, ","), +			"Cc": strings.Join(cc, ","), +			"Subject": subject, +			"In-Reply-To": msg.Envelope.MessageId, +		}). +		FocusTerminal() + +	tab := aerc.NewTab(composer, subject) + +	composer.OnSubjectChange(func(subject string) { +		if subject == "" { +			tab.Name = "New email" +		} else { +			tab.Name = subject +		} +		tab.Content.Invalidate() +	}) + +	return nil +} + + @@ -15,6 +15,7 @@ require (  	github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf  	github.com/kyoh86/xdg v0.0.0-20171127140545-8db68a8ea76a  	github.com/lucasb-eyer/go-colorful v0.0.0-20180531031333-d9cec903b20c // indirect +	github.com/martinlindhe/base36 v0.0.0-20190418230009-7c6542dfbb41  	github.com/mattn/go-isatty v0.0.3  	github.com/mattn/go-runewidth v0.0.2  	github.com/miolini/datacounter v0.0.0-20171104152933-fd4e42a1d5e0 @@ -40,6 +40,8 @@ github.com/kyoh86/xdg v0.0.0-20171127140545-8db68a8ea76a h1:vLFQnHOnCnmlySdpHAKF  github.com/kyoh86/xdg v0.0.0-20171127140545-8db68a8ea76a/go.mod h1:Z5mDqe0fxyxn3W2yTxsBAOQqIrXADQIh02wrTnaRM38=  github.com/lucasb-eyer/go-colorful v0.0.0-20180531031333-d9cec903b20c h1:b11Y3yxg40v2/9KUz76a4mSC1DMlgnPGAt+4pJSgmyU=  github.com/lucasb-eyer/go-colorful v0.0.0-20180531031333-d9cec903b20c/go.mod h1:NXg0ArsFk0Y01623LgUqoqcouGDB+PwCCQlrwrG6xJ4= +github.com/martinlindhe/base36 v0.0.0-20190418230009-7c6542dfbb41 h1:CVsnY46BCLkX9XOhALJ/S7yb9ayc4eqjXSXO3tyB66A= +github.com/martinlindhe/base36 v0.0.0-20190418230009-7c6542dfbb41/go.mod h1:+AtEs8xrBpCeYgSLoY/aJ6Wf37jtBuR0s35750M27+8=  github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=  github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=  github.com/mattn/go-pointer v0.0.0-20180825124634-49522c3f3791 h1:PfHMsLQJwoc0ccjK0sam6J0wQo4s8mOuAo2yQGw+T2U= diff --git a/lib/msgid.go b/lib/msgid.go new file mode 100644 index 0000000..8282d1d --- /dev/null +++ b/lib/msgid.go @@ -0,0 +1,34 @@ +package lib + +// TODO: Remove this pending merge into github.com/emersion/go-message + +import ( +	"bytes" +	"encoding/binary" +	"fmt" +	"math/rand" +	"os" +	"time" + +	"github.com/martinlindhe/base36" +) + +// Generates an RFC 2822-complaint Message-Id based on the informational draft +// "Recommendations for generating Message IDs", for lack of a better +// authoritative source. +func GenerateMessageId() string { +	var ( +		now   bytes.Buffer +		nonce bytes.Buffer +	) +	binary.Write(&now, binary.BigEndian, time.Now().UnixNano()) +	binary.Write(&nonce, binary.BigEndian, rand.Uint64()) +	hostname, err := os.Hostname() +	if err != nil { +		hostname = "localhost" +	} +	return fmt.Sprintf("<%s.%s@%s>", +		base36.EncodeBytes(now.Bytes()), +		base36.EncodeBytes(nonce.Bytes()), +		hostname) +} diff --git a/widgets/account.go b/widgets/account.go index c252e38..ab32f5d 100644 --- a/widgets/account.go +++ b/widgets/account.go @@ -84,6 +84,14 @@ func (acct *AccountView) AccountConfig() *config.AccountConfig {  	return acct.acct  } +func (acct *AccountView) Worker() *types.Worker { +	return acct.worker +} + +func (acct *AccountView) Logger() *log.Logger { +	return acct.logger +} +  func (acct *AccountView) Name() string {  	return acct.acct.Name  } @@ -110,10 +118,6 @@ func (acct *AccountView) Focus(focus bool) {  	// TODO: Unfocus children I guess  } -func (acct *AccountView) Worker() *types.Worker { -	return acct.worker -} -  func (acct *AccountView) connected(msg types.WorkerMessage) {  	switch msg := msg.(type) {  	case *types.Done: diff --git a/widgets/compose.go b/widgets/compose.go index 2359cad..02a9d0c 100644 --- a/widgets/compose.go +++ b/widgets/compose.go @@ -14,6 +14,7 @@ import (  	"github.com/mattn/go-runewidth"  	"git.sr.ht/~sircmpwn/aerc2/config" +	"git.sr.ht/~sircmpwn/aerc2/lib"  	"git.sr.ht/~sircmpwn/aerc2/lib/ui"  	"git.sr.ht/~sircmpwn/aerc2/worker/types"  ) @@ -123,6 +124,13 @@ func (c *Composer) Defaults(defaults map[string]string) *Composer {  	return c  } +func (c *Composer) FocusTerminal() *Composer { +	c.focusable[c.focused].Focus(false) +	c.focused = 3 +	c.focusable[c.focused].Focus(true) +	return c +} +  func (c *Composer) OnSubjectChange(fn func(subject string)) {  	c.headers.subject.OnChange(func() {  		fn(c.headers.subject.input.String()) @@ -197,9 +205,9 @@ func (c *Composer) PrepareHeader() (*mail.Header, []string, error) {  		c.email.Seek(0, os.SEEK_SET)  	}  	// Update headers -	// TODO: Custom header fields  	mhdr := (*message.Header)(&header.Header)  	mhdr.SetContentType("text/plain", map[string]string{"charset": "UTF-8"}) +	mhdr.SetText("Message-Id", lib.GenerateMessageId())  	if subject, _ := header.Subject(); subject == "" {  		header.SetSubject(c.headers.subject.input.String())  	} @@ -228,14 +236,14 @@ func (c *Composer) PrepareHeader() (*mail.Header, []string, error) {  			rcpts = append(rcpts, addr.Address)  		}  	} +	// TODO: Add cc, bcc to rcpts  	// Merge in additional headers  	txthdr := mhdr.Header  	for key, value := range c.defaults { -		if !txthdr.Has(key) { +		if !txthdr.Has(key) && value != "" {  			mhdr.SetText(key, value)  		}  	} -	// TODO: Add cc, bcc to rcpts  	return &header, rcpts, nil  }  | 
