aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--commands/account/compose.go2
-rw-r--r--lib/templates/template.go9
-rw-r--r--widgets/compose.go189
3 files changed, 48 insertions, 152 deletions
diff --git a/commands/account/compose.go b/commands/account/compose.go
index c2144418..8115faa2 100644
--- a/commands/account/compose.go
+++ b/commands/account/compose.go
@@ -46,7 +46,7 @@ func (Compose) Execute(aerc *widgets.Aerc, args []string) error {
}
tab.Content.Invalidate()
})
- go composer.PrependContents(strings.NewReader(body))
+ go composer.AppendContents(strings.NewReader(body))
return nil
}
diff --git a/lib/templates/template.go b/lib/templates/template.go
index 9df594eb..e18328cc 100644
--- a/lib/templates/template.go
+++ b/lib/templates/template.go
@@ -3,6 +3,7 @@ package templates
import (
"bytes"
"errors"
+ "io"
"net/mail"
"os"
"os/exec"
@@ -185,7 +186,7 @@ func findTemplate(templateName string, templateDirs []string) (string, error) {
return "", errors.New("Can't find template - " + templateName)
}
-func ParseTemplateFromFile(templateName string, templateDirs []string, data interface{}) ([]byte, error) {
+func ParseTemplateFromFile(templateName string, templateDirs []string, data interface{}) (io.Reader, error) {
templateFile, err := findTemplate(templateName, templateDirs)
if err != nil {
return nil, err
@@ -196,11 +197,11 @@ func ParseTemplateFromFile(templateName string, templateDirs []string, data inte
return nil, err
}
- var outString bytes.Buffer
- if err := emailTemplate.Execute(&outString, data); err != nil {
+ var body bytes.Buffer
+ if err := emailTemplate.Execute(&body, data); err != nil {
return nil, err
}
- return outString.Bytes(), nil
+ return &body, nil
}
func ParseTemplate(templateText string, data interface{}) ([]byte, error) {
diff --git a/widgets/compose.go b/widgets/compose.go
index a97e5fed..9ceabf6c 100644
--- a/widgets/compose.go
+++ b/widgets/compose.go
@@ -15,7 +15,6 @@ import (
"strings"
"time"
- "github.com/emersion/go-message"
"github.com/emersion/go-message/mail"
"github.com/gdamore/tcell"
"github.com/mattn/go-runewidth"
@@ -99,10 +98,10 @@ func NewComposer(aerc *Aerc, conf *config.AercConfig,
completer: cmpl,
}
- c.AddSignature()
if err := c.AddTemplate(template, templateData); err != nil {
return nil, err
}
+ c.AddSignature()
c.updateGrid()
c.ShowTerminal()
@@ -172,16 +171,6 @@ func (c *Composer) SetContents(reader io.Reader) *Composer {
return c
}
-func (c *Composer) PrependContents(reader io.Reader) {
- buf := bytes.NewBuffer(nil)
- c.email.Seek(0, io.SeekStart)
- io.Copy(buf, c.email)
- c.email.Seek(0, io.SeekStart)
- io.Copy(c.email, reader)
- io.Copy(c.email, buf)
- c.email.Sync()
-}
-
func (c *Composer) AppendContents(reader io.Reader) {
c.email.Seek(0, io.SeekEnd)
io.Copy(c.email, reader)
@@ -198,67 +187,29 @@ func (c *Composer) AddTemplate(template string, data interface{}) error {
if err != nil {
return err
}
- return c.addTemplate(templateText)
-}
-func (c *Composer) AddTemplateFromString(template string, data interface{}) error {
- if template == "" {
- return nil
- }
-
- templateText, err := templates.ParseTemplate(template, data)
+ mr, err := mail.CreateReader(templateText)
if err != nil {
- return err
+ return fmt.Errorf("Template loading failed: %v", err)
}
- return c.addTemplate(templateText)
-}
-func (c *Composer) addTemplate(templateText []byte) error {
- reader, err := mail.CreateReader(bytes.NewReader(templateText))
- if err != nil {
- // encountering an error when reading the template probably
- // means the template didn't evaluate to a properly formatted
- // mail file.
- // This is fine, we still want to support simple body templates
- // that don't include headers.
- //
- // Just prepend the rendered template in that case. This
- // basically equals the previous behavior.
- c.PrependContents(bytes.NewReader(templateText))
- return nil
- }
- defer reader.Close()
-
- // populate header editors
- header := reader.Header
- mhdr := (*message.Header)(&header.Header)
- for _, editor := range c.editors {
- if mhdr.Has(editor.name) {
- editor.input.Set(mhdr.Get(editor.name))
- // remove header fields that have editors
- mhdr.Del(editor.name)
+ // add the headers contained in the template to the default headers
+ hf := mr.Header.Fields()
+ for hf.Next() {
+ var val string
+ var err error
+ if val, err = hf.Text(); err != nil {
+ val = hf.Value()
}
+ c.defaults[hf.Key()] = val
}
- part, err := reader.NextPart()
+ part, err := mr.NextPart()
if err != nil {
- return errors.Wrap(err, "reader.NextPart")
- }
- c.PrependContents(part.Body)
-
- var (
- headers string
- fds = mhdr.Fields()
- )
- for fds.Next() {
- headers += fmt.Sprintf("%s: %s\n", fds.Key(), fds.Value())
- }
- if headers != "" {
- headers += "\n"
+ return fmt.Errorf("Could not get body of template: %v", err)
}
- // prepend header fields without editors to message body
- c.PrependContents(bytes.NewReader([]byte(headers)))
+ c.AppendContents(part.Body)
return nil
}
@@ -411,114 +362,58 @@ func (c *Composer) Worker() *types.Worker {
}
func (c *Composer) PrepareHeader() (*mail.Header, []string, error) {
- // Extract headers from the email, if present
- if err := c.reloadEmail(); err != nil {
- return nil, nil, err
- }
- var (
- rcpts []string
- header mail.Header
- )
- reader, err := mail.CreateReader(c.email)
- if err == nil {
- header = reader.Header
- defer reader.Close()
- } else {
- c.email.Seek(0, io.SeekStart)
+ header := &mail.Header{}
+ for h, val := range c.defaults {
+ if val == "" {
+ continue
+ }
+ header.SetText(h, val)
}
- // Update headers
- mhdr := (*message.Header)(&header.Header)
- mhdr.SetText("Message-Id", c.msgId)
+ header.SetText("Message-Id", c.msgId)
+ header.SetDate(c.date)
headerKeys := make([]string, 0, len(c.editors))
for key := range c.editors {
headerKeys = append(headerKeys, key)
}
- // Ensure headers which require special processing are included.
- for _, key := range []string{"To", "From", "Cc", "Bcc", "Subject", "Date"} {
- if _, ok := c.editors[key]; !ok {
- headerKeys = append(headerKeys, key)
- }
- }
- for _, h := range headerKeys {
- val := ""
- editor, ok := c.editors[h]
- if ok {
- val = editor.input.String()
- } else {
- val, _ = mhdr.Text(h)
+ var rcpts []string
+ for h, editor := range c.editors {
+ val := editor.input.String()
+ if val == "" {
+ continue
}
switch h {
- case "Subject":
- if subject, _ := header.Subject(); subject == "" {
- header.SetSubject(val)
+ case "From", "To", "Cc", "Bcc": // Address headers
+ hdrRcpts, err := gomail.ParseAddressList(val)
+ if err != nil {
+ return nil, nil, errors.Wrapf(err, "ParseAddressList(%s)", val)
}
- case "Date":
- if date, err := header.Date(); err != nil || date == (time.Time{}) {
- header.SetDate(c.date)
+ edRcpts := make([]*mail.Address, len(hdrRcpts))
+ for i, addr := range hdrRcpts {
+ edRcpts[i] = (*mail.Address)(addr)
}
- case "From", "To", "Cc", "Bcc": // Address headers
- if val != "" {
- hdrRcpts, err := gomail.ParseAddressList(val)
- if err != nil {
- return nil, nil, errors.Wrapf(err, "ParseAddressList(%s)", val)
- }
- edRcpts := make([]*mail.Address, len(hdrRcpts))
- for i, addr := range hdrRcpts {
- edRcpts[i] = (*mail.Address)(addr)
- }
- header.SetAddressList(h, edRcpts)
- if h != "From" {
- for _, addr := range edRcpts {
- rcpts = append(rcpts, addr.Address)
- }
+ header.SetAddressList(h, edRcpts)
+ if h != "From" {
+ for _, addr := range edRcpts {
+ rcpts = append(rcpts, addr.Address)
}
}
default:
- // Handle user configured header editors.
- if ok && !mhdr.Header.Has(h) {
- if val := editor.input.String(); val != "" {
- mhdr.SetText(h, val)
- }
- }
- }
- }
-
- // Merge in additional headers
- txthdr := mhdr.Header
- for key, value := range c.defaults {
- if !txthdr.Has(key) && value != "" {
- mhdr.SetText(key, value)
+ header.SetText(h, val)
}
}
-
- return &header, rcpts, nil
+ return header, rcpts, nil
}
func (c *Composer) WriteMessage(header *mail.Header, writer io.Writer) error {
if err := c.reloadEmail(); err != nil {
return err
}
- var body io.Reader
- reader, err := mail.CreateReader(c.email)
- if err == nil {
- // 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 errors.Wrap(err, "reader.NextPart")
- }
- body = part.Body
- defer reader.Close()
- } else {
- c.email.Seek(0, io.SeekStart)
- body = c.email
- }
if len(c.attachments) == 0 {
// don't create a multipart email if we only have text
- return writeInlineBody(header, body, writer)
+ return writeInlineBody(header, c.email, writer)
}
// otherwise create a multipart email,
@@ -529,7 +424,7 @@ func (c *Composer) WriteMessage(header *mail.Header, writer io.Writer) error {
}
defer w.Close()
- if err := writeMultipartBody(body, w); err != nil {
+ if err := writeMultipartBody(c.email, w); err != nil {
return errors.Wrap(err, "writeMultipartBody")
}