diff options
-rw-r--r-- | plugins/base/handlers.go | 8 | ||||
-rw-r--r-- | plugins/base/public/compose.html | 9 | ||||
-rw-r--r-- | plugins/base/smtp.go | 49 |
3 files changed, 57 insertions, 9 deletions
diff --git a/plugins/base/handlers.go b/plugins/base/handlers.go index 133052c..e939cc5 100644 --- a/plugins/base/handlers.go +++ b/plugins/base/handlers.go @@ -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 { diff --git a/plugins/base/public/compose.html b/plugins/base/public/compose.html index 5f0b904..0e16acf 100644 --- a/plugins/base/public/compose.html +++ b/plugins/base/public/compose.html @@ -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> diff --git a/plugins/base/smtp.go b/plugins/base/smtp.go index 9ade78f..81da6ef 100644 --- a/plugins/base/smtp.go +++ b/plugins/base/smtp.go @@ -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) } |