Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions internal/web/blocks/wrapper.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="format-detection" content="telephone=no, date=no, address=no, email=no">
<meta name="color-scheme" content="light only">
<meta name="supported-color-schemes" content="light only">
<title>{{.Subject}}</title>
<!--[if mso]>
<xml>
Expand Down
1 change: 1 addition & 0 deletions internal/web/handlers/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ func New(cfg *config.Config, db *db.DB, logger *slog.Logger, v *views.Engine, oi
Settings: settings,
Sendry: sendryMgr,
MultiSend: &cfg.Sendry.MultiSend,
PublicURL: cfg.Server.PublicURL,
Logger: logger.With("component", "router"),
})

Expand Down
17 changes: 17 additions & 0 deletions internal/web/handlers/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package handlers

import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"time"
Expand Down Expand Up @@ -647,11 +648,27 @@ func (h *Handlers) TemplateTest(w http.ResponseWriter, r *http.Request) {
globalVars = make(map[string]string)
}

// Merge request variables (override global)
if varsJSON := r.FormValue("variables"); varsJSON != "" {
var reqVars map[string]any
if err := json.Unmarshal([]byte(varsJSON), &reqVars); err == nil {
for k, v := range reqVars {
if s, ok := v.(string); ok {
globalVars[k] = s
} else {
globalVars[k] = fmt.Sprintf("%v", v)
}
}
}
}

// Render template with variables
subject := renderTemplateVars(t.Subject, globalVars)
html := renderTemplateVars(t.HTML, globalVars)
text := renderTemplateVars(t.Text, globalVars)

html = makeAbsoluteURLs(html, h.cfg.Server.PublicURL)

// Send test email
req := &sendry.SendRequest{
From: from,
Expand Down
9 changes: 9 additions & 0 deletions internal/web/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ type EmailRouter struct {
settings *repository.SettingsRepository
sendry *sendry.Manager
cfg *config.MultiSendConfig
publicURL string
logger *slog.Logger

mu sync.Mutex
Expand All @@ -79,6 +80,7 @@ type RouterConfig struct {
Settings *repository.SettingsRepository
Sendry *sendry.Manager
MultiSend *config.MultiSendConfig
PublicURL string
Logger *slog.Logger
}

Expand All @@ -91,6 +93,7 @@ func NewEmailRouter(cfg RouterConfig) *EmailRouter {
settings: cfg.Settings,
sendry: cfg.Sendry,
cfg: cfg.MultiSend,
publicURL: cfg.PublicURL,
logger: cfg.Logger,
rrCounters: make(map[string]int),
}
Expand Down Expand Up @@ -294,6 +297,12 @@ func (r *EmailRouter) resolveTemplate(ctx context.Context, req *APISendRequest)
html := renderVars(tmpl.HTML, data)
text := renderVars(tmpl.Text, data)

if r.publicURL != "" {
base := strings.TrimRight(r.publicURL, "/")
html = strings.ReplaceAll(html, `src="/uploads/`, `src="`+base+`/uploads/`)
html = strings.ReplaceAll(html, `src="/static/`, `src="`+base+`/static/`)
}

return &sendry.SendRequest{
From: req.From,
To: req.To,
Expand Down
10 changes: 5 additions & 5 deletions internal/web/views/block_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ <h3>Template Variables</h3>
</p>
<ul class="var-list" id="vars-list"></ul>
<div id="vars-empty" style="text-align:center; color:var(--text-muted); padding:2rem; display:none;">
No variables found. Use <code>{{"{{"}}.VarName{{"}}"}}</code> syntax in your HTML.
No variables found. Use <code>{{"{{"}}VarName{{"}}"}}</code> syntax in your HTML.
</div>
</div>
</div>
Expand All @@ -205,12 +205,12 @@ <h3>Template Variables</h3>
// Replace variables that have test values
for (var key in testValues) {
if (testValues[key]) {
var pattern = LP + '.' + key + '}}';
var pattern = LP + key + '}}';
html = html.split(pattern).join(testValues[key]);
}
}
// Remaining variables — show as grey badges
html = html.replace(/\{\{\.(\w+)\}\}/g, function(match, name) {
html = html.replace(/\{\{(\w+)\}\}/g, function(match, name) {
return '<span style="background:#E4E4E4;color:#959595;padding:2px 6px;border-radius:3px;font-size:11px;font-family:monospace;">' + name + '</span>';
});
return html;
Expand Down Expand Up @@ -288,7 +288,7 @@ <h3>Template Variables</h3>

if (_pickerMode === 'replace') {
// Replace variable with the actual URL
var varPattern = LP + '.' + _replaceVarName + '}}';
var varPattern = LP + _replaceVarName + '}}';
textarea.value = textarea.value.split(varPattern).join(file.url);
textarea.dispatchEvent(new Event('input'));
closeImagePicker();
Expand Down Expand Up @@ -324,7 +324,7 @@ <h3>Template Variables</h3>

// Find all template variables
var vars = {};
var re = /\{\{\.(\w+)\}\}/g;
var re = /\{\{(\w+)\}\}/g;
var m;
while ((m = re.exec(html)) !== null) {
var full = m[0];
Expand Down
4 changes: 2 additions & 2 deletions internal/web/views/block_view.html
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,11 @@ <h1>{{.Block.Name}}</h1>
var content = html;
for (var key in testValues) {
if (testValues[key]) {
content = content.split('{{"{{"}}.' + key + '}}').join(testValues[key]);
content = content.split('{{"{{"}}' + key + '}}').join(testValues[key]);
}
}
// Remaining variables — show as grey badges
var varRe = new RegExp('\\{\\{\\.(\\w+)\\}\\}', 'g');
var varRe = new RegExp('\\{\\{(\\w+)\\}\\}', 'g');
content = content.replace(varRe, function(m, name) {
return '<span style="background:#E4E4E4;color:#959595;padding:2px 6px;border-radius:3px;font-size:11px;font-family:monospace;">' + name + '</span>';
});
Expand Down
2 changes: 1 addition & 1 deletion internal/web/views/settings_variables.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ <h3>Variables</h3>
<tbody>
{{range .Variables}}
<tr>
<td><code>{{`{{`}}.{{.Key}}{{`}}`}}</code></td>
<td><code>{{`{{`}}{{.Key}}{{`}}`}}</code></td>
<td>{{.Value}}</td>
<td class="text-muted">{{.Description}}</td>
<td>{{.UpdatedAt.Format "2006-01-02 15:04"}}</td>
Expand Down
Loading