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.Text = ctx.FormValue("text")
|
||||||
msg.InReplyTo = ctx.FormValue("in_reply_to")
|
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)
|
return sendMessage(c, &msg)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -8,14 +8,14 @@
|
||||||
|
|
||||||
<h2>Compose new message</h2>
|
<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}}">
|
<input type="hidden" name="in_reply_to" value="{{.Message.InReplyTo}}">
|
||||||
|
|
||||||
<label for="from">From:</label>
|
<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>
|
<br><br>
|
||||||
<label for="to">To:</label>
|
<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>
|
<br><br>
|
||||||
<label for="subject">Subject:</label>
|
<label for="subject">Subject:</label>
|
||||||
<input type="text" name="subject" id="subject" value="{{.Message.Subject}}">
|
<input type="text" name="subject" id="subject" value="{{.Message.Subject}}">
|
||||||
|
@ -23,6 +23,9 @@
|
||||||
<label for="text">Body:</label><br>
|
<label for="text">Body:</label><br>
|
||||||
<textarea name="text" id="text" cols="80" rows="20">{{.Message.Text}}</textarea>
|
<textarea name="text" id="text" cols="80" rows="20">{{.Message.Text}}</textarea>
|
||||||
<br><br>
|
<br><br>
|
||||||
|
<label for="attachments">Attachments:</label>
|
||||||
|
<input type="file" name="attachments" id="attachments" multiple>
|
||||||
|
<br><br>
|
||||||
<input type="submit" value="Send">
|
<input type="submit" value="Send">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"mime/multipart"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -26,17 +27,49 @@ func quote(r io.Reader) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type OutgoingMessage struct {
|
type OutgoingMessage struct {
|
||||||
From string
|
From string
|
||||||
To []string
|
To []string
|
||||||
Subject string
|
Subject string
|
||||||
InReplyTo string
|
InReplyTo string
|
||||||
Text string
|
Text string
|
||||||
|
Attachments []*multipart.FileHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *OutgoingMessage) ToString() string {
|
func (msg *OutgoingMessage) ToString() string {
|
||||||
return strings.Join(msg.To, ", ")
|
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 {
|
func (msg *OutgoingMessage) WriteTo(w io.Writer) error {
|
||||||
from := []*mail.Address{{"", msg.From}}
|
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)
|
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 {
|
if err := mw.Close(); err != nil {
|
||||||
return fmt.Errorf("failed to close mail writer: %v", err)
|
return fmt.Errorf("failed to close mail writer: %v", err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue