aboutsummaryrefslogtreecommitdiff
path: root/widgets
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2019-05-14 13:07:48 -0400
committerDrew DeVault <sir@cmpwn.com>2019-05-14 13:07:48 -0400
commit6c36e04c1f7f7e222c71c5c8e7e7337744fe9c34 (patch)
tree52695aa088a565808275582f138cf673c0066d76 /widgets
parentd5e82ecfe05065a84f1e13bee44e309b8e1559bd (diff)
Add :send-message, prepares & writes email to /tmp
Diffstat (limited to 'widgets')
-rw-r--r--widgets/compose.go79
-rw-r--r--widgets/msgviewer.go11
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()