From 6c36e04c1f7f7e222c71c5c8e7e7337744fe9c34 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 14 May 2019 13:07:48 -0400 Subject: Add :send-message, prepares & writes email to /tmp --- widgets/compose.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) (limited to 'widgets/compose.go') diff --git a/widgets/compose.go b/widgets/compose.go index 5b7a1ba..318bfc4 100644 --- a/widgets/compose.go +++ b/widgets/compose.go @@ -1,10 +1,15 @@ package widgets import ( + "io" "io/ioutil" + gomail "net/mail" "os" "os/exec" + "time" + "github.com/emersion/go-message" + "github.com/emersion/go-message/mail" "github.com/gdamore/tcell" "github.com/mattn/go-runewidth" @@ -79,6 +84,9 @@ func NewComposer(conf *config.AccountConfig) *Composer { focused: 1, focusable: []ui.DrawableInteractive{from, to, subject, term}, } + c.headers.to = to + c.headers.from = from + c.headers.subject = subject term.OnClose = c.termClosed @@ -107,6 +115,77 @@ func (c *Composer) Focus(focus bool) { c.focusable[c.focused].Focus(focus) } +func (c *Composer) Config() *config.AccountConfig { + return c.config +} + +// Writes the email to the given writer, and returns a list of recipients +func (c *Composer) Message(writeto io.Writer) ([]string, error) { + // Extract headers from the email, if present + c.email.Seek(0, os.SEEK_SET) + var ( + rcpts []string + header mail.Header + body io.Reader + ) + reader, err := mail.CreateReader(c.email) + if err == nil { + header = reader.Header + // TODO: Do we want to let users write a full blown multipart email + // into the editor? If so this needs to change + part, err := reader.NextPart() + if err != nil { + return nil, err + } + body = part.Body + defer reader.Close() + } else { + c.email.Seek(0, os.SEEK_SET) + body = c.email + } + // Update headers + // TODO: Custom header fields + mhdr := (*message.Header)(&header.Header) + mhdr.SetContentType("text/plain", map[string]string{"charset": "UTF-8"}) + if subject, _ := header.Subject(); subject == "" { + header.SetSubject(c.headers.subject.input.String()) + } + if date, err := header.Date(); err != nil && date != (time.Time{}) { + header.SetDate(time.Now()) + } + if from, _ := mhdr.Text("From"); from == "" { + mhdr.SetText("From", c.headers.from.input.String()) + } + if to := c.headers.to.input.String(); to != "" { + // Dammit Simon, this branch is 3x as long as it ought to be because + // your types aren't compatible enough with each other + to_rcpts, err := gomail.ParseAddressList(to) + if err != nil { + return nil, err + } + ed_rcpts, err := header.AddressList("To") + if err != nil { + return nil, err + } + for _, addr := range to_rcpts { + ed_rcpts = append(ed_rcpts, (*mail.Address)(addr)) + } + header.SetAddressList("To", ed_rcpts) + for _, addr := range ed_rcpts { + rcpts = append(rcpts, addr.Address) + } + } + // TODO: Add cc, bcc to rcpts + // TODO: attachments + writer, err := mail.CreateSingleInlineWriter(writeto, header) + if err != nil { + return nil, err + } + defer writer.Close() + io.Copy(writer, body) + return rcpts, nil +} + func (c *Composer) termClosed(err error) { // TODO: do we care about that error (note: yes, we do) c.grid.RemoveChild(c.editor) -- cgit v1.2.3