Add mail render method
This commit is contained in:
parent
bdccab1419
commit
c29cc1593d
|
@ -16,14 +16,6 @@
|
|||
|
||||
package notifications
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"code.vikunja.io/api/pkg/mail"
|
||||
"code.vikunja.io/api/pkg/static"
|
||||
"code.vikunja.io/api/pkg/utils"
|
||||
"github.com/shurcooL/httpfs/html/vfstemplate"
|
||||
)
|
||||
|
||||
type Mail struct {
|
||||
from string
|
||||
to string
|
||||
|
@ -77,45 +69,3 @@ func (m *Mail) Line(line string) *Mail {
|
|||
|
||||
return m
|
||||
}
|
||||
|
||||
func RenderMail(m *Mail) (mailOpts *mail.Opts, err error) {
|
||||
|
||||
var htmlContent bytes.Buffer
|
||||
var plainContent bytes.Buffer
|
||||
|
||||
t, err := vfstemplate.ParseGlob(static.Templates, nil, "*.tmpl")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
boundary := "np" + utils.MakeRandomString(13)
|
||||
|
||||
data := make(map[string]interface{})
|
||||
|
||||
data["Greeting"] = m.greeting
|
||||
data["IntroLines"] = m.introLines
|
||||
data["OutroLines"] = m.outroLines
|
||||
data["ActionText"] = m.actionText
|
||||
data["ActionURL"] = m.actionURL
|
||||
data["Boundary"] = boundary
|
||||
|
||||
if err := t.ExecuteTemplate(&htmlContent, "mail-notification.html.tmpl", data); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := t.ExecuteTemplate(&plainContent, "mail-notification.plain.tmpl", data); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
mailOpts = &mail.Opts{
|
||||
From: m.from,
|
||||
To: m.to,
|
||||
Subject: m.subject,
|
||||
ContentType: mail.ContentTypeMultipart,
|
||||
Message: plainContent.String(),
|
||||
HTMLMessage: htmlContent.String(),
|
||||
Boundary: boundary,
|
||||
}
|
||||
|
||||
return mailOpts, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
// Vikunja is a to-do list application to facilitate your life.
|
||||
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public Licensee as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public Licensee for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public Licensee
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package notifications
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
"code.vikunja.io/api/pkg/mail"
|
||||
"code.vikunja.io/api/pkg/utils"
|
||||
templatehtml "html/template"
|
||||
templatetext "text/template"
|
||||
)
|
||||
|
||||
const mailTemplatePlain = `
|
||||
{{ .Greeting }}
|
||||
{{ range $line := .IntroLines}}
|
||||
{{ $line }}
|
||||
{{ end }}
|
||||
{{ if .ActionURL }}{{ .ActionText }}:
|
||||
{{ .ActionURL }}{{end}}
|
||||
{{ range $line := .OutroLines}}
|
||||
{{ $line }}
|
||||
{{ end }}`
|
||||
|
||||
const mailTemplateHTML = `
|
||||
<!doctype html>
|
||||
<html style="width: 100%; height: 100%; padding: 0; margin: 0;">
|
||||
<head>
|
||||
<meta name="viewport" content="width: display-width;">
|
||||
</head>
|
||||
<body style="width: 100%; padding: 0; margin: 0; background: #f1f5f8">
|
||||
<div style="width: 100%; font-family: 'Open Sans', sans-serif; text-rendering: optimizeLegibility">
|
||||
<div style="width: 600px; margin: 0 auto; text-align: justify;">
|
||||
<h1 style="font-size: 30px; text-align: center;">
|
||||
<img src="{{.FrontendURL}}images/logo-full.svg" style="height: 75px;" alt="Vikunja"/>
|
||||
</h1>
|
||||
<div style="border: 1px solid #dbdbdb; -webkit-box-shadow: 0.3em 0.3em 0.8em #e6e6e6; box-shadow: 0.3em 0.3em 0.8em #e6e6e6; color: #4a4a4a; padding: 5px 25px; border-radius: 3px; background: #fff;">
|
||||
<p>
|
||||
{{ .Greeting }}
|
||||
</p>
|
||||
|
||||
{{ range $line := .IntroLines}}
|
||||
<p>
|
||||
{{ $line }}
|
||||
</p>
|
||||
{{ end }}
|
||||
|
||||
{{ if .ActionURL }}
|
||||
<a href="{{ .ActionURL }}" title="{{ .ActionText }}"
|
||||
style="-webkit-box-shadow: 0.3em 0.3em 1em #b2d0ff; box-shadow: 0.3em 0.3em 1em #b2d0ff; background-color: #1973ff; border-color: transparent; color: #fff; text-decoration: none; text-align: center; text-rendering: optimizelegibility; text-transform: uppercase; font-weight: bold; font-size: 14px; padding: 10px 14px; margin: 10px auto; border-radius: 4px; user-select: none; display: block; width: 280px;font-family:sans-serif">
|
||||
{{ .ActionText }}
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
{{ range $line := .OutroLines}}
|
||||
<p>
|
||||
{{ $line }}
|
||||
</p>
|
||||
{{ end }}
|
||||
|
||||
{{ if .ActionURL }}
|
||||
<p style="color: #9CA3AF">
|
||||
If the button above doesn't work, copy the url below and paste it in your browsers address bar:<br/>
|
||||
{{ .ActionURL }}
|
||||
</p>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
func RenderMail(m *Mail) (mailOpts *mail.Opts, err error) {
|
||||
|
||||
var htmlContent bytes.Buffer
|
||||
var plainContent bytes.Buffer
|
||||
|
||||
plain, err := templatetext.New("mail-plain").Parse(mailTemplatePlain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
html, err := templatehtml.New("mail-plain").Parse(mailTemplateHTML)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
boundary := "np" + utils.MakeRandomString(13)
|
||||
|
||||
data := make(map[string]interface{})
|
||||
|
||||
data["Greeting"] = m.greeting
|
||||
data["IntroLines"] = m.introLines
|
||||
data["OutroLines"] = m.outroLines
|
||||
data["ActionText"] = m.actionText
|
||||
data["ActionURL"] = m.actionURL
|
||||
data["Boundary"] = boundary
|
||||
data["FrontendURL"] = config.ServiceFrontendurl.GetString()
|
||||
|
||||
err = plain.Execute(&plainContent, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = html.Execute(&htmlContent, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mailOpts = &mail.Opts{
|
||||
From: m.from,
|
||||
To: m.to,
|
||||
Subject: m.subject,
|
||||
ContentType: mail.ContentTypeMultipart,
|
||||
Message: plainContent.String(),
|
||||
HTMLMessage: htmlContent.String(),
|
||||
Boundary: boundary,
|
||||
}
|
||||
|
||||
return mailOpts, nil
|
||||
}
|
|
@ -81,3 +81,92 @@ func TestNewMail(t *testing.T) {
|
|||
assert.Equal(t, "And one more, because why not?", mail.introLines[3])
|
||||
})
|
||||
}
|
||||
|
||||
func TestRenderMail(t *testing.T) {
|
||||
mail := NewMail().
|
||||
From("test@example.com").
|
||||
To("test@otherdomain.com").
|
||||
Subject("Testmail").
|
||||
Greeting("Hi there,").
|
||||
Line("This is a line").
|
||||
Line("And another one").
|
||||
Action("The action", "https://example.com").
|
||||
Line("This should be an outro line").
|
||||
Line("And one more, because why not?")
|
||||
|
||||
mailopts, err := RenderMail(mail)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, mail.from, mailopts.From)
|
||||
assert.Equal(t, mail.to, mailopts.To)
|
||||
|
||||
assert.Equal(t, `
|
||||
Hi there,
|
||||
|
||||
This is a line
|
||||
|
||||
And another one
|
||||
|
||||
The action:
|
||||
https://example.com
|
||||
|
||||
This should be an outro line
|
||||
|
||||
And one more, because why not?
|
||||
`, mailopts.Message)
|
||||
assert.Equal(t, `
|
||||
<!doctype html>
|
||||
<html style="width: 100%; height: 100%; padding: 0; margin: 0;">
|
||||
<head>
|
||||
<meta name="viewport" content="width: display-width;">
|
||||
</head>
|
||||
<body style="width: 100%; padding: 0; margin: 0; background: #f1f5f8">
|
||||
<div style="width: 100%; font-family: 'Open Sans', sans-serif; text-rendering: optimizeLegibility">
|
||||
<div style="width: 600px; margin: 0 auto; text-align: justify;">
|
||||
<h1 style="font-size: 30px; text-align: center;">
|
||||
<img src="images/logo-full.svg" style="height: 75px;" alt="Vikunja"/>
|
||||
</h1>
|
||||
<div style="border: 1px solid #dbdbdb; -webkit-box-shadow: 0.3em 0.3em 0.8em #e6e6e6; box-shadow: 0.3em 0.3em 0.8em #e6e6e6; color: #4a4a4a; padding: 5px 25px; border-radius: 3px; background: #fff;">
|
||||
<p>
|
||||
Hi there,
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
This is a line
|
||||
</p>
|
||||
|
||||
<p>
|
||||
And another one
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<a href="https://example.com" title="The action"
|
||||
style="-webkit-box-shadow: 0.3em 0.3em 1em #b2d0ff; box-shadow: 0.3em 0.3em 1em #b2d0ff; background-color: #1973ff; border-color: transparent; color: #fff; text-decoration: none; text-align: center; text-rendering: optimizelegibility; text-transform: uppercase; font-weight: bold; font-size: 14px; padding: 10px 14px; margin: 10px auto; border-radius: 4px; user-select: none; display: block; width: 280px;font-family:sans-serif">
|
||||
The action
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<p>
|
||||
This should be an outro line
|
||||
</p>
|
||||
|
||||
<p>
|
||||
And one more, because why not?
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<p style="color: #9CA3AF">
|
||||
If the button above doesn't work, copy the url below and paste it in your browsers address bar:<br/>
|
||||
https://example.com
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`, mailopts.HTMLMessage)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue