mirror of
https://github.com/muety/wakapi.git
synced 2023-08-10 21:12:56 +03:00
chore: use partial includes in mail templates to avoid code duplication
This commit is contained in:
parent
69f5d510dc
commit
87fadf46f7
@ -2,27 +2,24 @@ package routes
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/muety/wakapi/views"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/fs"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/muety/wakapi/config"
|
"github.com/muety/wakapi/config"
|
||||||
"github.com/muety/wakapi/models"
|
"github.com/muety/wakapi/models"
|
||||||
"github.com/muety/wakapi/utils"
|
"github.com/muety/wakapi/utils"
|
||||||
"github.com/muety/wakapi/views"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Init() {
|
|
||||||
loadTemplates()
|
|
||||||
}
|
|
||||||
|
|
||||||
type action func(w http.ResponseWriter, r *http.Request) (int, string, string)
|
type action func(w http.ResponseWriter, r *http.Request) (int, string, string)
|
||||||
|
|
||||||
var templates map[string]*template.Template
|
var templates map[string]*template.Template
|
||||||
|
|
||||||
|
func Init() {
|
||||||
|
loadTemplates()
|
||||||
|
}
|
||||||
|
|
||||||
func DefaultTemplateFuncs() template.FuncMap {
|
func DefaultTemplateFuncs() template.FuncMap {
|
||||||
return template.FuncMap{
|
return template.FuncMap{
|
||||||
"json": utils.Json,
|
"json": utils.Json,
|
||||||
@ -58,44 +55,6 @@ func DefaultTemplateFuncs() template.FuncMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadTemplates() {
|
|
||||||
tpls := template.New("").Funcs(DefaultTemplateFuncs())
|
|
||||||
templates = make(map[string]*template.Template)
|
|
||||||
|
|
||||||
// Use local file system when in 'dev' environment, go embed file system otherwise
|
|
||||||
templateFs := config.ChooseFS("views", views.TemplateFiles)
|
|
||||||
|
|
||||||
files, err := fs.ReadDir(templateFs, ".")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, file := range files {
|
|
||||||
tplName := file.Name()
|
|
||||||
if file.IsDir() || path.Ext(tplName) != ".html" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
templateFile, err := templateFs.Open(tplName)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
templateData, err := ioutil.ReadAll(templateFile)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
templateFile.Close()
|
|
||||||
|
|
||||||
tpl, err := tpls.New(tplName).Parse(string(templateData))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
templates[tplName] = tpl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func typeName(t uint8) string {
|
func typeName(t uint8) string {
|
||||||
if t == models.SummaryProject {
|
if t == models.SummaryProject {
|
||||||
return "project"
|
return "project"
|
||||||
@ -118,6 +77,16 @@ func typeName(t uint8) string {
|
|||||||
return "unknown"
|
return "unknown"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadTemplates() {
|
||||||
|
// Use local file system when in 'dev' environment, go embed file system otherwise
|
||||||
|
templateFs := config.ChooseFS("views", views.TemplateFiles)
|
||||||
|
if tpls, err := utils.LoadTemplates(templateFs, DefaultTemplateFuncs()); err == nil {
|
||||||
|
templates = tpls
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func defaultErrorRedirectTarget() string {
|
func defaultErrorRedirectTarget() string {
|
||||||
return fmt.Sprintf("%s/?error=unauthorized", config.Get().Server.BasePath)
|
return fmt.Sprintf("%s/?error=unauthorized", config.Get().Server.BasePath)
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,10 @@ import (
|
|||||||
"github.com/muety/wakapi/routes"
|
"github.com/muety/wakapi/routes"
|
||||||
"github.com/muety/wakapi/services"
|
"github.com/muety/wakapi/services"
|
||||||
"github.com/muety/wakapi/utils"
|
"github.com/muety/wakapi/utils"
|
||||||
"html/template"
|
"github.com/muety/wakapi/views/mail"
|
||||||
"io/ioutil"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
conf "github.com/muety/wakapi/config"
|
conf "github.com/muety/wakapi/config"
|
||||||
"github.com/muety/wakapi/views"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -33,6 +31,7 @@ type SendingService interface {
|
|||||||
type MailService struct {
|
type MailService struct {
|
||||||
config *conf.Config
|
config *conf.Config
|
||||||
sendingService SendingService
|
sendingService SendingService
|
||||||
|
templates utils.TemplateMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMailService() services.IMailService {
|
func NewMailService() services.IMailService {
|
||||||
@ -49,11 +48,18 @@ func NewMailService() services.IMailService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &MailService{sendingService: sendingService, config: config}
|
// Use local file system when in 'dev' environment, go embed file system otherwise
|
||||||
|
templateFs := conf.ChooseFS("views/mail", mail.TemplateFiles)
|
||||||
|
templates, err := utils.LoadTemplates(templateFs, routes.DefaultTemplateFuncs())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &MailService{sendingService: sendingService, config: config, templates: templates}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MailService) SendPasswordReset(recipient *models.User, resetLink string) error {
|
func (m *MailService) SendPasswordReset(recipient *models.User, resetLink string) error {
|
||||||
tpl, err := getPasswordResetTemplate(PasswordResetTplData{ResetLink: resetLink})
|
tpl, err := m.getPasswordResetTemplate(PasswordResetTplData{ResetLink: resetLink})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -67,7 +73,7 @@ func (m *MailService) SendPasswordReset(recipient *models.User, resetLink string
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MailService) SendWakatimeFailureNotification(recipient *models.User, numFailures int) error {
|
func (m *MailService) SendWakatimeFailureNotification(recipient *models.User, numFailures int) error {
|
||||||
tpl, err := getWakatimeFailureNotificationTemplate(WakatimeFailureNotificationNotificationTplData{
|
tpl, err := m.getWakatimeFailureNotificationTemplate(WakatimeFailureNotificationNotificationTplData{
|
||||||
PublicUrl: m.config.Server.PublicUrl,
|
PublicUrl: m.config.Server.PublicUrl,
|
||||||
NumFailures: numFailures,
|
NumFailures: numFailures,
|
||||||
})
|
})
|
||||||
@ -84,7 +90,7 @@ func (m *MailService) SendWakatimeFailureNotification(recipient *models.User, nu
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MailService) SendImportNotification(recipient *models.User, duration time.Duration, numHeartbeats int) error {
|
func (m *MailService) SendImportNotification(recipient *models.User, duration time.Duration, numHeartbeats int) error {
|
||||||
tpl, err := getImportNotificationTemplate(ImportNotificationTplData{
|
tpl, err := m.getImportNotificationTemplate(ImportNotificationTplData{
|
||||||
PublicUrl: m.config.Server.PublicUrl,
|
PublicUrl: m.config.Server.PublicUrl,
|
||||||
Duration: fmt.Sprintf("%.0f seconds", duration.Seconds()),
|
Duration: fmt.Sprintf("%.0f seconds", duration.Seconds()),
|
||||||
NumHeartbeats: numHeartbeats,
|
NumHeartbeats: numHeartbeats,
|
||||||
@ -102,7 +108,7 @@ func (m *MailService) SendImportNotification(recipient *models.User, duration ti
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *MailService) SendReport(recipient *models.User, report *models.Report) error {
|
func (m *MailService) SendReport(recipient *models.User, report *models.Report) error {
|
||||||
tpl, err := getReportTemplate(ReportTplData{report})
|
tpl, err := m.getReportTemplate(ReportTplData{report})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -115,68 +121,38 @@ func (m *MailService) SendReport(recipient *models.User, report *models.Report)
|
|||||||
return m.sendingService.Send(mail)
|
return m.sendingService.Send(mail)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPasswordResetTemplate(data PasswordResetTplData) (*bytes.Buffer, error) {
|
func (m *MailService) getPasswordResetTemplate(data PasswordResetTplData) (*bytes.Buffer, error) {
|
||||||
tpl, err := loadTemplate(tplNamePasswordReset)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var rendered bytes.Buffer
|
var rendered bytes.Buffer
|
||||||
if err := tpl.Execute(&rendered, data); err != nil {
|
if err := m.templates[m.fmtName(tplNamePasswordReset)].Execute(&rendered, data); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &rendered, nil
|
return &rendered, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getWakatimeFailureNotificationTemplate(data WakatimeFailureNotificationNotificationTplData) (*bytes.Buffer, error) {
|
func (m *MailService) getWakatimeFailureNotificationTemplate(data WakatimeFailureNotificationNotificationTplData) (*bytes.Buffer, error) {
|
||||||
tpl, err := loadTemplate(tplNameWakatimeFailureNotification)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var rendered bytes.Buffer
|
var rendered bytes.Buffer
|
||||||
if err := tpl.Execute(&rendered, data); err != nil {
|
if err := m.templates[m.fmtName(tplNameWakatimeFailureNotification)].Execute(&rendered, data); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &rendered, nil
|
return &rendered, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getImportNotificationTemplate(data ImportNotificationTplData) (*bytes.Buffer, error) {
|
func (m *MailService) getImportNotificationTemplate(data ImportNotificationTplData) (*bytes.Buffer, error) {
|
||||||
tpl, err := loadTemplate(tplNameImportNotification)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var rendered bytes.Buffer
|
var rendered bytes.Buffer
|
||||||
if err := tpl.Execute(&rendered, data); err != nil {
|
if err := m.templates[m.fmtName(tplNameImportNotification)].Execute(&rendered, data); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &rendered, nil
|
return &rendered, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getReportTemplate(data ReportTplData) (*bytes.Buffer, error) {
|
func (m *MailService) getReportTemplate(data ReportTplData) (*bytes.Buffer, error) {
|
||||||
tpl, err := loadTemplate(tplNameReport)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var rendered bytes.Buffer
|
var rendered bytes.Buffer
|
||||||
if err := tpl.Execute(&rendered, data); err != nil {
|
if err := m.templates[m.fmtName(tplNameReport)].Execute(&rendered, data); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &rendered, nil
|
return &rendered, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadTemplate(tplName string) (*template.Template, error) {
|
func (m *MailService) fmtName(name string) string {
|
||||||
tplFile, err := views.TemplateFiles.Open(fmt.Sprintf("mail/%s.tpl.html", tplName))
|
return fmt.Sprintf("%s.tpl.html", name)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer tplFile.Close()
|
|
||||||
|
|
||||||
tplData, err := ioutil.ReadAll(tplFile)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return template.
|
|
||||||
New(tplName).
|
|
||||||
Funcs(routes.DefaultTemplateFuncs()).
|
|
||||||
Parse(string(tplData))
|
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,13 @@ package utils
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
"io/fs"
|
||||||
|
"io/ioutil"
|
||||||
|
"path"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type TemplateMap map[string]*template.Template
|
||||||
|
|
||||||
func Json(data interface{}) template.JS {
|
func Json(data interface{}) template.JS {
|
||||||
d, err := json.Marshal(data)
|
d, err := json.Marshal(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -19,3 +24,40 @@ func ToRunes(s string) (r []string) {
|
|||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LoadTemplates(templateFs fs.FS, funcs template.FuncMap) (TemplateMap, error) {
|
||||||
|
tpls := template.New("").Funcs(funcs)
|
||||||
|
templates := make(map[string]*template.Template)
|
||||||
|
|
||||||
|
files, err := fs.ReadDir(templateFs, ".")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
tplName := file.Name()
|
||||||
|
if file.IsDir() || path.Ext(tplName) != ".html" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
templateFile, err := templateFs.Open(tplName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
templateData, err := ioutil.ReadAll(templateFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
templateFile.Close()
|
||||||
|
|
||||||
|
tpl, err := tpls.New(tplName).Parse(string(templateData))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
templates[tplName] = tpl
|
||||||
|
}
|
||||||
|
|
||||||
|
return templates, nil
|
||||||
|
}
|
||||||
|
88
views/mail/head.tpl.html
Normal file
88
views/mail/head.tpl.html
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width">
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<title>Wakapi</title>
|
||||||
|
<style>
|
||||||
|
@media only screen and (max-width: 620px) {
|
||||||
|
table[class=body] h1 {
|
||||||
|
font-size: 28px !important;
|
||||||
|
margin-bottom: 10px !important;
|
||||||
|
}
|
||||||
|
table[class=body] p,
|
||||||
|
table[class=body] ul,
|
||||||
|
table[class=body] ol,
|
||||||
|
table[class=body] td,
|
||||||
|
table[class=body] span,
|
||||||
|
table[class=body] a {
|
||||||
|
font-size: 16px !important;
|
||||||
|
}
|
||||||
|
table[class=body] .wrapper,
|
||||||
|
table[class=body] .article {
|
||||||
|
padding: 10px !important;
|
||||||
|
}
|
||||||
|
table[class=body] .content {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
table[class=body] .container {
|
||||||
|
padding: 0 !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
table[class=body] .main {
|
||||||
|
border-left-width: 0 !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
border-right-width: 0 !important;
|
||||||
|
}
|
||||||
|
table[class=body] .btn table {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
table[class=body] .btn a {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
table[class=body] .img-responsive {
|
||||||
|
height: auto !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------
|
||||||
|
PRESERVE THESE STYLES IN THE HEAD
|
||||||
|
------------------------------------- */
|
||||||
|
@media all {
|
||||||
|
.ExternalClass {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.ExternalClass,
|
||||||
|
.ExternalClass p,
|
||||||
|
.ExternalClass span,
|
||||||
|
.ExternalClass font,
|
||||||
|
.ExternalClass td,
|
||||||
|
.ExternalClass div {
|
||||||
|
line-height: 100%;
|
||||||
|
}
|
||||||
|
.apple-link a {
|
||||||
|
color: inherit !important;
|
||||||
|
font-family: inherit !important;
|
||||||
|
font-size: inherit !important;
|
||||||
|
font-weight: inherit !important;
|
||||||
|
line-height: inherit !important;
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
#MessageViewBody a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: inherit;
|
||||||
|
font-family: inherit;
|
||||||
|
font-weight: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
.btn-primary table td:hover {
|
||||||
|
background-color: #047857 !important;
|
||||||
|
}
|
||||||
|
.btn-primary a:hover {
|
||||||
|
background-color: #047857 !important;
|
||||||
|
border-color: #047857 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
@ -1,107 +1,14 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width">
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
||||||
<title>Wakapi – Data Import Finished</title>
|
|
||||||
<style>
|
|
||||||
@media only screen and (max-width: 620px) {
|
|
||||||
table[class=body] h1 {
|
|
||||||
font-size: 28px !important;
|
|
||||||
margin-bottom: 10px !important;
|
|
||||||
}
|
|
||||||
table[class=body] p,
|
|
||||||
table[class=body] ul,
|
|
||||||
table[class=body] ol,
|
|
||||||
table[class=body] td,
|
|
||||||
table[class=body] span,
|
|
||||||
table[class=body] a {
|
|
||||||
font-size: 16px !important;
|
|
||||||
}
|
|
||||||
table[class=body] .wrapper,
|
|
||||||
table[class=body] .article {
|
|
||||||
padding: 10px !important;
|
|
||||||
}
|
|
||||||
table[class=body] .content {
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
table[class=body] .container {
|
|
||||||
padding: 0 !important;
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
table[class=body] .main {
|
|
||||||
border-left-width: 0 !important;
|
|
||||||
border-radius: 0 !important;
|
|
||||||
border-right-width: 0 !important;
|
|
||||||
}
|
|
||||||
table[class=body] .btn table {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
table[class=body] .btn a {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
table[class=body] .img-responsive {
|
|
||||||
height: auto !important;
|
|
||||||
max-width: 100% !important;
|
|
||||||
width: auto !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------
|
{{ template "head.tpl.html" . }}
|
||||||
PRESERVE THESE STYLES IN THE HEAD
|
|
||||||
------------------------------------- */
|
|
||||||
@media all {
|
|
||||||
.ExternalClass {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.ExternalClass,
|
|
||||||
.ExternalClass p,
|
|
||||||
.ExternalClass span,
|
|
||||||
.ExternalClass font,
|
|
||||||
.ExternalClass td,
|
|
||||||
.ExternalClass div {
|
|
||||||
line-height: 100%;
|
|
||||||
}
|
|
||||||
.apple-link a {
|
|
||||||
color: inherit !important;
|
|
||||||
font-family: inherit !important;
|
|
||||||
font-size: inherit !important;
|
|
||||||
font-weight: inherit !important;
|
|
||||||
line-height: inherit !important;
|
|
||||||
text-decoration: none !important;
|
|
||||||
}
|
|
||||||
#MessageViewBody a {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: inherit;
|
|
||||||
font-family: inherit;
|
|
||||||
font-weight: inherit;
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
.btn-primary table td:hover {
|
|
||||||
background-color: #047857 !important;
|
|
||||||
}
|
|
||||||
.btn-primary a:hover {
|
|
||||||
background-color: #047857 !important;
|
|
||||||
border-color: #047857 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body class="" style="background-color: #f6f6f6; font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
|
<body class="" style="background-color: #f6f6f6; font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
|
||||||
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #f6f6f6;">
|
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #f6f6f6;">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
||||||
<td class="container" style="font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; Margin: 0 auto; max-width: 580px; padding: 10px; width: 580px;">
|
<td class="container" style="font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; Margin: 0 auto; max-width: 580px; padding: 10px; width: 580px;">
|
||||||
<div class="header" style="clear: both; Margin-top: 10px; text-align: center; width: 100%;">
|
{{ template "theader.tpl.html" . }}
|
||||||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
|
||||||
<tr>
|
|
||||||
<td class="content-block" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; font-size: 12px; color: #999999; text-align: center;">
|
|
||||||
<img src="https://wakapi.dev/assets/images/android-chrome-192x192.png?utm_source=mail" alt="Wakapi Logo" width="96" style="width: 96px">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content" style="box-sizing: border-box; display: block; Margin: 0 auto; max-width: 580px; padding: 10px;">
|
<div class="content" style="box-sizing: border-box; display: block; Margin: 0 auto; max-width: 580px; padding: 10px;">
|
||||||
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #ffffff; border-radius: 3px;">
|
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #ffffff; border-radius: 3px;">
|
||||||
@ -134,15 +41,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="footer" style="clear: both; Margin-top: 10px; text-align: center; width: 100%;">
|
{{ template "tfooter.tpl.html" . }}
|
||||||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
|
||||||
<tr>
|
|
||||||
<td class="content-block powered-by" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; font-size: 12px; color: #999999; text-align: center;">
|
|
||||||
Powered by <a href="https://wakapi.dev" style="color: #999999; font-size: 12px; text-align: center; text-decoration: none;">Wakapi.dev</a>.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
||||||
|
6
views/mail/mail.go
Normal file
6
views/mail/mail.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package mail
|
||||||
|
|
||||||
|
import "embed"
|
||||||
|
|
||||||
|
//go:embed *.html
|
||||||
|
var TemplateFiles embed.FS
|
@ -1,107 +1,14 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width">
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
||||||
<title>Wakapi – Report</title>
|
|
||||||
<style>
|
|
||||||
@media only screen and (max-width: 620px) {
|
|
||||||
table[class=body] h1 {
|
|
||||||
font-size: 28px !important;
|
|
||||||
margin-bottom: 10px !important;
|
|
||||||
}
|
|
||||||
table[class=body] p,
|
|
||||||
table[class=body] ul,
|
|
||||||
table[class=body] ol,
|
|
||||||
table[class=body] td,
|
|
||||||
table[class=body] span,
|
|
||||||
table[class=body] a {
|
|
||||||
font-size: 16px !important;
|
|
||||||
}
|
|
||||||
table[class=body] .wrapper,
|
|
||||||
table[class=body] .article {
|
|
||||||
padding: 10px !important;
|
|
||||||
}
|
|
||||||
table[class=body] .content {
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
table[class=body] .container {
|
|
||||||
padding: 0 !important;
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
table[class=body] .main {
|
|
||||||
border-left-width: 0 !important;
|
|
||||||
border-radius: 0 !important;
|
|
||||||
border-right-width: 0 !important;
|
|
||||||
}
|
|
||||||
table[class=body] .btn table {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
table[class=body] .btn a {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
table[class=body] .img-responsive {
|
|
||||||
height: auto !important;
|
|
||||||
max-width: 100% !important;
|
|
||||||
width: auto !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------
|
{{ template "head.tpl.html" . }}
|
||||||
PRESERVE THESE STYLES IN THE HEAD
|
|
||||||
------------------------------------- */
|
|
||||||
@media all {
|
|
||||||
.ExternalClass {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.ExternalClass,
|
|
||||||
.ExternalClass p,
|
|
||||||
.ExternalClass span,
|
|
||||||
.ExternalClass font,
|
|
||||||
.ExternalClass td,
|
|
||||||
.ExternalClass div {
|
|
||||||
line-height: 100%;
|
|
||||||
}
|
|
||||||
.apple-link a {
|
|
||||||
color: inherit !important;
|
|
||||||
font-family: inherit !important;
|
|
||||||
font-size: inherit !important;
|
|
||||||
font-weight: inherit !important;
|
|
||||||
line-height: inherit !important;
|
|
||||||
text-decoration: none !important;
|
|
||||||
}
|
|
||||||
#MessageViewBody a {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: inherit;
|
|
||||||
font-family: inherit;
|
|
||||||
font-weight: inherit;
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
.btn-primary table td:hover {
|
|
||||||
background-color: #047857 !important;
|
|
||||||
}
|
|
||||||
.btn-primary a:hover {
|
|
||||||
background-color: #047857 !important;
|
|
||||||
border-color: #047857 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body class="" style="background-color: #f6f6f6; font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
|
<body class="" style="background-color: #f6f6f6; font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
|
||||||
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #f6f6f6;">
|
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #f6f6f6;">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
||||||
<td class="container" style="font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; Margin: 0 auto; max-width: 580px; padding: 10px; width: 580px;">
|
<td class="container" style="font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; Margin: 0 auto; max-width: 580px; padding: 10px; width: 580px;">
|
||||||
<div class="header" style="clear: both; Margin-top: 10px; text-align: center; width: 100%;">
|
{{ template "theader.tpl.html" . }}
|
||||||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
|
||||||
<tr>
|
|
||||||
<td class="content-block" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; font-size: 12px; color: #999999; text-align: center;">
|
|
||||||
<img src="https://wakapi.dev/assets/images/android-chrome-192x192.png?utm_source=mail" alt="Wakapi Logo" width="96" style="width: 96px">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content" style="box-sizing: border-box; display: block; Margin: 0 auto; max-width: 580px; padding: 10px;">
|
<div class="content" style="box-sizing: border-box; display: block; Margin: 0 auto; max-width: 580px; padding: 10px;">
|
||||||
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #ffffff; border-radius: 3px;">
|
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #ffffff; border-radius: 3px;">
|
||||||
@ -180,15 +87,8 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<div class="footer" style="clear: both; Margin-top: 10px; text-align: center; width: 100%;">
|
|
||||||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
{{ template "tfooter.tpl.html" . }}
|
||||||
<tr>
|
|
||||||
<td class="content-block powered-by" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; font-size: 12px; color: #999999; text-align: center;">
|
|
||||||
Powered by <a href="https://wakapi.dev" style="color: #999999; font-size: 12px; text-align: center; text-decoration: none;">Wakapi.dev</a>.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
||||||
|
@ -1,107 +1,14 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width">
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
||||||
<title>Wakapi – Reset Password</title>
|
|
||||||
<style>
|
|
||||||
@media only screen and (max-width: 620px) {
|
|
||||||
table[class=body] h1 {
|
|
||||||
font-size: 28px !important;
|
|
||||||
margin-bottom: 10px !important;
|
|
||||||
}
|
|
||||||
table[class=body] p,
|
|
||||||
table[class=body] ul,
|
|
||||||
table[class=body] ol,
|
|
||||||
table[class=body] td,
|
|
||||||
table[class=body] span,
|
|
||||||
table[class=body] a {
|
|
||||||
font-size: 16px !important;
|
|
||||||
}
|
|
||||||
table[class=body] .wrapper,
|
|
||||||
table[class=body] .article {
|
|
||||||
padding: 10px !important;
|
|
||||||
}
|
|
||||||
table[class=body] .content {
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
table[class=body] .container {
|
|
||||||
padding: 0 !important;
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
table[class=body] .main {
|
|
||||||
border-left-width: 0 !important;
|
|
||||||
border-radius: 0 !important;
|
|
||||||
border-right-width: 0 !important;
|
|
||||||
}
|
|
||||||
table[class=body] .btn table {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
table[class=body] .btn a {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
table[class=body] .img-responsive {
|
|
||||||
height: auto !important;
|
|
||||||
max-width: 100% !important;
|
|
||||||
width: auto !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------
|
{{ template "head.tpl.html" . }}
|
||||||
PRESERVE THESE STYLES IN THE HEAD
|
|
||||||
------------------------------------- */
|
|
||||||
@media all {
|
|
||||||
.ExternalClass {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.ExternalClass,
|
|
||||||
.ExternalClass p,
|
|
||||||
.ExternalClass span,
|
|
||||||
.ExternalClass font,
|
|
||||||
.ExternalClass td,
|
|
||||||
.ExternalClass div {
|
|
||||||
line-height: 100%;
|
|
||||||
}
|
|
||||||
.apple-link a {
|
|
||||||
color: inherit !important;
|
|
||||||
font-family: inherit !important;
|
|
||||||
font-size: inherit !important;
|
|
||||||
font-weight: inherit !important;
|
|
||||||
line-height: inherit !important;
|
|
||||||
text-decoration: none !important;
|
|
||||||
}
|
|
||||||
#MessageViewBody a {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: inherit;
|
|
||||||
font-family: inherit;
|
|
||||||
font-weight: inherit;
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
.btn-primary table td:hover {
|
|
||||||
background-color: #047857 !important;
|
|
||||||
}
|
|
||||||
.btn-primary a:hover {
|
|
||||||
background-color: #047857 !important;
|
|
||||||
border-color: #047857 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body class="" style="background-color: #f6f6f6; font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
|
<body class="" style="background-color: #f6f6f6; font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
|
||||||
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #f6f6f6;">
|
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #f6f6f6;">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
||||||
<td class="container" style="font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; Margin: 0 auto; max-width: 580px; padding: 10px; width: 580px;">
|
<td class="container" style="font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; Margin: 0 auto; max-width: 580px; padding: 10px; width: 580px;">
|
||||||
<div class="header" style="clear: both; Margin-top: 10px; text-align: center; width: 100%;">
|
{{ template "theader.tpl.html" . }}
|
||||||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
|
||||||
<tr>
|
|
||||||
<td class="content-block" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; font-size: 12px; color: #999999; text-align: center;">
|
|
||||||
<img src="https://wakapi.dev/assets/images/android-chrome-192x192.png?utm_source=mail" alt="Wakapi Logo" width="96" style="width: 96px">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content" style="box-sizing: border-box; display: block; Margin: 0 auto; max-width: 580px; padding: 10px;">
|
<div class="content" style="box-sizing: border-box; display: block; Margin: 0 auto; max-width: 580px; padding: 10px;">
|
||||||
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #ffffff; border-radius: 3px;">
|
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #ffffff; border-radius: 3px;">
|
||||||
@ -135,15 +42,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="footer" style="clear: both; Margin-top: 10px; text-align: center; width: 100%;">
|
{{ template "tfooter.tpl.html" . }}
|
||||||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
|
||||||
<tr>
|
|
||||||
<td class="content-block powered-by" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; font-size: 12px; color: #999999; text-align: center;">
|
|
||||||
Powered by <a href="https://wakapi.dev" style="color: #999999; font-size: 12px; text-align: center; text-decoration: none;">Wakapi.dev</a>.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
||||||
|
9
views/mail/tfooter.tpl.html
Normal file
9
views/mail/tfooter.tpl.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<div class="footer" style="clear: both; Margin-top: 10px; text-align: center; width: 100%;">
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
||||||
|
<tr>
|
||||||
|
<td class="content-block powered-by" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; font-size: 12px; color: #999999; text-align: center;">
|
||||||
|
Powered by <a href="https://wakapi.dev" style="color: #999999; font-size: 12px; text-align: center; text-decoration: none;">Wakapi.dev</a>.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
9
views/mail/theader.tpl.html
Normal file
9
views/mail/theader.tpl.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<div class="header" style="clear: both; Margin-top: 10px; text-align: center; width: 100%;">
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
||||||
|
<tr>
|
||||||
|
<td class="content-block" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; font-size: 12px; color: #999999; text-align: center;">
|
||||||
|
<img src="https://wakapi.dev/assets/images/android-chrome-192x192.png?utm_source=mail" alt="Wakapi Logo" width="96" style="width: 96px">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
@ -1,107 +1,14 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width">
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
||||||
<title>Wakapi – WakaTime Connection Failure</title>
|
|
||||||
<style>
|
|
||||||
@media only screen and (max-width: 620px) {
|
|
||||||
table[class=body] h1 {
|
|
||||||
font-size: 28px !important;
|
|
||||||
margin-bottom: 10px !important;
|
|
||||||
}
|
|
||||||
table[class=body] p,
|
|
||||||
table[class=body] ul,
|
|
||||||
table[class=body] ol,
|
|
||||||
table[class=body] td,
|
|
||||||
table[class=body] span,
|
|
||||||
table[class=body] a {
|
|
||||||
font-size: 16px !important;
|
|
||||||
}
|
|
||||||
table[class=body] .wrapper,
|
|
||||||
table[class=body] .article {
|
|
||||||
padding: 10px !important;
|
|
||||||
}
|
|
||||||
table[class=body] .content {
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
table[class=body] .container {
|
|
||||||
padding: 0 !important;
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
table[class=body] .main {
|
|
||||||
border-left-width: 0 !important;
|
|
||||||
border-radius: 0 !important;
|
|
||||||
border-right-width: 0 !important;
|
|
||||||
}
|
|
||||||
table[class=body] .btn table {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
table[class=body] .btn a {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
table[class=body] .img-responsive {
|
|
||||||
height: auto !important;
|
|
||||||
max-width: 100% !important;
|
|
||||||
width: auto !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------
|
{{ template "head.tpl.html" . }}
|
||||||
PRESERVE THESE STYLES IN THE HEAD
|
|
||||||
------------------------------------- */
|
|
||||||
@media all {
|
|
||||||
.ExternalClass {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.ExternalClass,
|
|
||||||
.ExternalClass p,
|
|
||||||
.ExternalClass span,
|
|
||||||
.ExternalClass font,
|
|
||||||
.ExternalClass td,
|
|
||||||
.ExternalClass div {
|
|
||||||
line-height: 100%;
|
|
||||||
}
|
|
||||||
.apple-link a {
|
|
||||||
color: inherit !important;
|
|
||||||
font-family: inherit !important;
|
|
||||||
font-size: inherit !important;
|
|
||||||
font-weight: inherit !important;
|
|
||||||
line-height: inherit !important;
|
|
||||||
text-decoration: none !important;
|
|
||||||
}
|
|
||||||
#MessageViewBody a {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: inherit;
|
|
||||||
font-family: inherit;
|
|
||||||
font-weight: inherit;
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
.btn-primary table td:hover {
|
|
||||||
background-color: #047857 !important;
|
|
||||||
}
|
|
||||||
.btn-primary a:hover {
|
|
||||||
background-color: #047857 !important;
|
|
||||||
border-color: #047857 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body class="" style="background-color: #f6f6f6; font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
|
<body class="" style="background-color: #f6f6f6; font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
|
||||||
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #f6f6f6;">
|
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #f6f6f6;">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
||||||
<td class="container" style="font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; Margin: 0 auto; max-width: 580px; padding: 10px; width: 580px;">
|
<td class="container" style="font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; Margin: 0 auto; max-width: 580px; padding: 10px; width: 580px;">
|
||||||
<div class="header" style="clear: both; Margin-top: 10px; text-align: center; width: 100%;">
|
{{ template "theader.tpl.html" . }}
|
||||||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
|
||||||
<tr>
|
|
||||||
<td class="content-block" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; font-size: 12px; color: #999999; text-align: center;">
|
|
||||||
<img src="https://wakapi.dev/assets/images/android-chrome-192x192.png?utm_source=mail" alt="Wakapi Logo" width="96" style="width: 96px">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content" style="box-sizing: border-box; display: block; Margin: 0 auto; max-width: 580px; padding: 10px;">
|
<div class="content" style="box-sizing: border-box; display: block; Margin: 0 auto; max-width: 580px; padding: 10px;">
|
||||||
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #ffffff; border-radius: 3px;">
|
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #ffffff; border-radius: 3px;">
|
||||||
@ -134,15 +41,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="footer" style="clear: both; Margin-top: 10px; text-align: center; width: 100%;">
|
{{ template "tfooter.tpl.html" . }}
|
||||||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
|
||||||
<tr>
|
|
||||||
<td class="content-block powered-by" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; font-size: 12px; color: #999999; text-align: center;">
|
|
||||||
Powered by <a href="https://wakapi.dev" style="color: #999999; font-size: 12px; text-align: center; text-decoration: none;">Wakapi.dev</a>.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
||||||
|
@ -2,5 +2,5 @@ package views
|
|||||||
|
|
||||||
import "embed"
|
import "embed"
|
||||||
|
|
||||||
//go:embed *.html mail/*.html
|
//go:embed *.html
|
||||||
var TemplateFiles embed.FS
|
var TemplateFiles embed.FS
|
||||||
|
Loading…
Reference in New Issue
Block a user