aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
authorKoni Marti <koni.marti@gmail.com>2022-05-24 07:36:06 +0200
committerRobin Jarry <robin@jarry.cc>2022-05-31 14:32:08 +0200
commit6f5c6e148f08266e92875e813105997317bc212b (patch)
tree000628e3e15da1077189d5cbd27ce4cb39e99deb /widgets
parent527f602f36a001858cc95427899210984e4e71b9 (diff)
downloadaerc-6f5c6e148f08266e92875e813105997317bc212b.tar.gz
compose: append text parts
Append text parts to emails in the composer as multipart/alternative. Display the mime-type of the parts in the review window. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
Diffstat (limited to 'widgets')
-rw-r--r--widgets/compose.go71
1 files changed, 58 insertions, 13 deletions
diff --git a/widgets/compose.go b/widgets/compose.go
index 6a342d41..49a8eff2 100644
--- a/widgets/compose.go
+++ b/widgets/compose.go
@@ -30,6 +30,12 @@ import (
"git.sr.ht/~rjarry/aerc/worker/types"
)
+type Part struct {
+ MimeType string
+ Params map[string]string
+ Body io.Reader
+}
+
type Composer struct {
editors map[string]*headerEditor // indexes in lower case (from / cc / bcc)
header *mail.Header
@@ -61,6 +67,8 @@ type Composer struct {
onClose []func(ti *Composer)
width int
+
+ textParts []*Part
}
func NewComposer(aerc *Aerc, acct *AccountView, conf *config.AercConfig,
@@ -297,6 +305,14 @@ func (c *Composer) AppendContents(reader io.Reader) {
c.email.Sync()
}
+func (c *Composer) AppendPart(mimetype string, params map[string]string, body io.Reader) error {
+ if !strings.HasPrefix(mimetype, "text") {
+ return fmt.Errorf("can only append text mimetypes")
+ }
+ c.textParts = append(c.textParts, &Part{MimeType: mimetype, Params: params, Body: body})
+ return nil
+}
+
func (c *Composer) AddTemplate(template string, data interface{}) error {
if template == "" {
return nil
@@ -592,7 +608,7 @@ func (c *Composer) WriteMessage(header *mail.Header, writer io.Writer) error {
}
func writeMsgImpl(c *Composer, header *mail.Header, writer io.Writer) error {
- if len(c.attachments) == 0 && !c.attachKey {
+ if len(c.attachments) == 0 && !c.attachKey && len(c.textParts) == 0 {
// no attachements
return writeInlineBody(header, c.email, writer)
} else {
@@ -601,7 +617,14 @@ func writeMsgImpl(c *Composer, header *mail.Header, writer io.Writer) error {
if err != nil {
return errors.Wrap(err, "CreateWriter")
}
- if err := writeMultipartBody(c.email, w); err != nil {
+ parts := []*Part{
+ &Part{
+ MimeType: "text/plain",
+ Params: map[string]string{"Charset": "UTF-8"},
+ Body: c.email,
+ },
+ }
+ if err := writeMultipartBody(append(parts, c.textParts...), w); err != nil {
return errors.Wrap(err, "writeMultipartBody")
}
for _, a := range c.attachments {
@@ -634,24 +657,26 @@ func writeInlineBody(header *mail.Header, body io.Reader, writer io.Writer) erro
}
// write the message body to the multipart message
-func writeMultipartBody(body io.Reader, w *mail.Writer) error {
- bh := mail.InlineHeader{}
- bh.SetContentType("text/plain", map[string]string{"charset": "UTF-8"})
-
+func writeMultipartBody(parts []*Part, w *mail.Writer) error {
bi, err := w.CreateInline()
if err != nil {
return errors.Wrap(err, "CreateInline")
}
defer bi.Close()
- bw, err := bi.CreatePart(bh)
- if err != nil {
- return errors.Wrap(err, "CreatePart")
- }
- defer bw.Close()
- if _, err := io.Copy(bw, body); err != nil {
- return errors.Wrap(err, "io.Copy")
+ for _, part := range parts {
+ bh := mail.InlineHeader{}
+ bh.SetContentType(part.MimeType, part.Params)
+ bw, err := bi.CreatePart(bh)
+ if err != nil {
+ return errors.Wrap(err, "CreatePart")
+ }
+ defer bw.Close()
+ if _, err := io.Copy(bw, part.Body); err != nil {
+ return errors.Wrap(err, "io.Copy")
+ }
}
+
return nil
}
@@ -1084,6 +1109,13 @@ func newReviewMessage(composer *Composer, err error) *reviewMessage {
if composer.attachKey {
spec = append(spec, ui.GridSpec{Strategy: ui.SIZE_EXACT, Size: ui.Const(1)})
}
+ if len(composer.textParts) > 0 {
+ spec = append(spec, ui.GridSpec{Strategy: ui.SIZE_EXACT, Size: ui.Const(1)})
+ spec = append(spec, ui.GridSpec{Strategy: ui.SIZE_EXACT, Size: ui.Const(1)})
+ for i := 0; i < len(composer.textParts); i++ {
+ spec = append(spec, ui.GridSpec{Strategy: ui.SIZE_EXACT, Size: ui.Const(1)})
+ }
+ }
// make the last element fill remaining space
spec = append(spec, ui.GridSpec{Strategy: ui.SIZE_WEIGHT, Size: ui.Const(1)})
@@ -1117,6 +1149,7 @@ func newReviewMessage(composer *Composer, err error) *reviewMessage {
if len(composer.attachments) == 0 && !composer.attachKey {
grid.AddChild(ui.NewText("(none)",
uiConfig.GetStyle(config.STYLE_DEFAULT))).At(i, 0)
+ i += 1
} else {
for _, a := range composer.attachments {
grid.AddChild(ui.NewText(a, uiConfig.GetStyle(config.STYLE_DEFAULT))).
@@ -1124,6 +1157,18 @@ func newReviewMessage(composer *Composer, err error) *reviewMessage {
i += 1
}
}
+ if len(composer.textParts) > 0 {
+ grid.AddChild(ui.NewText("Parts:",
+ uiConfig.GetStyle(config.STYLE_TITLE))).At(i, 0)
+ i += 1
+ grid.AddChild(ui.NewText("text/plain", uiConfig.GetStyle(config.STYLE_DEFAULT))).At(i, 0)
+ i += 1
+ for _, p := range composer.textParts {
+ grid.AddChild(ui.NewText(p.MimeType, uiConfig.GetStyle(config.STYLE_DEFAULT))).At(i, 0)
+ i += 1
+ }
+
+ }
}
return &reviewMessage{