diff options
author | Drew DeVault <sir@cmpwn.com> | 2019-05-14 13:07:48 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2019-05-14 13:07:48 -0400 |
commit | 6c36e04c1f7f7e222c71c5c8e7e7337744fe9c34 (patch) | |
tree | 52695aa088a565808275582f138cf673c0066d76 /widgets | |
parent | d5e82ecfe05065a84f1e13bee44e309b8e1559bd (diff) |
Add :send-message, prepares & writes email to /tmp
Diffstat (limited to 'widgets')
-rw-r--r-- | widgets/compose.go | 79 | ||||
-rw-r--r-- | widgets/msgviewer.go | 11 |
2 files changed, 86 insertions, 4 deletions
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) diff --git a/widgets/msgviewer.go b/widgets/msgviewer.go index ba99911..3eda27d 100644 --- a/widgets/msgviewer.go +++ b/widgets/msgviewer.go @@ -10,6 +10,7 @@ import ( "github.com/danwakefield/fnmatch" "github.com/emersion/go-imap" "github.com/emersion/go-message" + _ "github.com/emersion/go-message/charset" "github.com/emersion/go-message/mail" "github.com/gdamore/tcell" "github.com/google/shlex" @@ -109,7 +110,8 @@ func NewMessageViewer(conf *config.AercConfig, store *lib.MessageStore, pager = exec.Command(cmd[0], cmd[1:]...) for _, f := range conf.Filters { - mime := strings.ToLower(msg.BodyStructure.MIMEType) + "/" + strings.ToLower(msg.BodyStructure.MIMESubType) + mime := strings.ToLower(msg.BodyStructure.MIMEType) + + "/" + strings.ToLower(msg.BodyStructure.MIMESubType) switch f.FilterType { case config.FILTER_MIMETYPE: if fnmatch.Match(f.Filter, mime, 0) { @@ -181,11 +183,12 @@ handle_error: func (mv *MessageViewer) attemptCopy() { if mv.source != nil && mv.pager.Process != nil { - header := make(message.Header) - header.Set("Content-Transfer-Encoding", mv.msg.BodyStructure.Encoding) + header := message.Header{} + header.SetText("Content-Transfer-Encoding", + mv.msg.BodyStructure.Encoding) header.SetContentType( mv.msg.BodyStructure.MIMEType, mv.msg.BodyStructure.Params) - header.SetContentDescription(mv.msg.BodyStructure.Description) + header.SetText("Content-Description", mv.msg.BodyStructure.Description) if mv.filter != nil { stdout, _ := mv.filter.StdoutPipe() mv.filter.Start() |