Add attachments support to composer
Closes: https://todo.sr.ht/~sircmpwn/koushin/13
This commit is contained in:
parent
7f48702b83
commit
08b259bd50
3 changed files with 57 additions and 9 deletions
|
@ -270,7 +270,13 @@ func handleCompose(ectx echo.Context) error {
|
|||
msg.Text = ctx.FormValue("text")
|
||||
msg.InReplyTo = ctx.FormValue("in_reply_to")
|
||||
|
||||
err := ctx.Session.DoSMTP(func(c *smtp.Client) error {
|
||||
form, err := ctx.MultipartForm()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get multipart form: %v", err)
|
||||
}
|
||||
msg.Attachments = form.File["attachments"]
|
||||
|
||||
err = ctx.Session.DoSMTP(func(c *smtp.Client) error {
|
||||
return sendMessage(c, &msg)
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
|
||||
<h2>Compose new message</h2>
|
||||
|
||||
<form method="post" action="">
|
||||
<form method="post" action="" enctype="multipart/form-data">
|
||||
<input type="hidden" name="in_reply_to" value="{{.Message.InReplyTo}}">
|
||||
|
||||
<label for="from">From:</label>
|
||||
<input type="email" name="from" id="from" value="{{.Message.From}}">
|
||||
<input type="email" name="from" id="from" required value="{{.Message.From}}">
|
||||
<br><br>
|
||||
<label for="to">To:</label>
|
||||
<input type="email" name="to" id="to" multiple value="{{.Message.ToString}}">
|
||||
<input type="email" name="to" id="to" multiple required value="{{.Message.ToString}}">
|
||||
<br><br>
|
||||
<label for="subject">Subject:</label>
|
||||
<input type="text" name="subject" id="subject" value="{{.Message.Subject}}">
|
||||
|
@ -23,6 +23,9 @@
|
|||
<label for="text">Body:</label><br>
|
||||
<textarea name="text" id="text" cols="80" rows="20">{{.Message.Text}}</textarea>
|
||||
<br><br>
|
||||
<label for="attachments">Attachments:</label>
|
||||
<input type="file" name="attachments" id="attachments" multiple>
|
||||
<br><br>
|
||||
<input type="submit" value="Send">
|
||||
</form>
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -26,17 +27,49 @@ func quote(r io.Reader) (string, error) {
|
|||
}
|
||||
|
||||
type OutgoingMessage struct {
|
||||
From string
|
||||
To []string
|
||||
Subject string
|
||||
InReplyTo string
|
||||
Text string
|
||||
From string
|
||||
To []string
|
||||
Subject string
|
||||
InReplyTo string
|
||||
Text string
|
||||
Attachments []*multipart.FileHeader
|
||||
}
|
||||
|
||||
func (msg *OutgoingMessage) ToString() string {
|
||||
return strings.Join(msg.To, ", ")
|
||||
}
|
||||
|
||||
func writeAttachment(mw *mail.Writer, att *multipart.FileHeader) error {
|
||||
var h mail.AttachmentHeader
|
||||
h.Set("Content-Type", att.Header.Get("Content-Type"))
|
||||
h.SetFilename(att.Filename)
|
||||
|
||||
aw, err := mw.CreateAttachment(h)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create attachment: %v", err)
|
||||
}
|
||||
defer aw.Close()
|
||||
|
||||
f, err := att.Open()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open attachment: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if _, err := io.Copy(aw, f); err != nil {
|
||||
return fmt.Errorf("failed to write attachment: %v", err)
|
||||
}
|
||||
|
||||
if err := f.Close(); err != nil {
|
||||
return fmt.Errorf("failed to close attachment: %v", err)
|
||||
}
|
||||
if err := aw.Close(); err != nil {
|
||||
return fmt.Errorf("failed to close attachment writer: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (msg *OutgoingMessage) WriteTo(w io.Writer) error {
|
||||
from := []*mail.Address{{"", msg.From}}
|
||||
|
||||
|
@ -78,6 +111,12 @@ func (msg *OutgoingMessage) WriteTo(w io.Writer) error {
|
|||
return fmt.Errorf("failed to close text part: %v", err)
|
||||
}
|
||||
|
||||
for _, att := range msg.Attachments {
|
||||
if err := writeAttachment(mw, att); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := mw.Close(); err != nil {
|
||||
return fmt.Errorf("failed to close mail writer: %v", err)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue