From 4decdda2cdc271b83dbb52eb491fd9745b7c0fd1 Mon Sep 17 00:00:00 2001 From: tsushanth <78000697+tsushanth@users.noreply.github.com> Date: Wed, 24 Jun 2026 18:33:02 -0700 Subject: [PATCH] fix: read template body from local file path when configured When GOTRUE_MAILER_TEMPLATES_* is set to a local file path (absolute path, relative path, or file:// URI), the template loader was prepending SiteURL and issuing an HTTP GET, which silently fetched the site's HTML page instead of the intended template file. Add a path-vs-URL check in loadEntryBody: values starting with '/', './', or 'file://' are read directly from disk with os.ReadFile. Only values that begin with 'http' (or lack a recognized prefix) are handled via the existing HTTP fetch path. The silent SiteURL-prepend fallback is preserved for relative URL fragments as before. Fixes #2589 --- internal/mailer/templatemailer/template.go | 28 ++++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/internal/mailer/templatemailer/template.go b/internal/mailer/templatemailer/template.go index a0de7f4f20..98cc98ce64 100644 --- a/internal/mailer/templatemailer/template.go +++ b/internal/mailer/templatemailer/template.go @@ -7,6 +7,7 @@ import ( "html/template" "io" "net/http" + "os" "strings" "sync" "time" @@ -452,14 +453,27 @@ func (o *Cache) loadEntryBody( temp := template.Must(template.New("").Parse(tempStr)) return temp, nil } - if !strings.HasPrefix(url, "http") { - url = cfg.SiteURL + url - } - tempStr, err := o.fetch(ctx, cfg, url) - if err != nil { - err = wrapError(ctx, typ, "template_body_http_error", err) - return nil, err + var tempStr string + if strings.HasPrefix(url, "file://") || strings.HasPrefix(url, "/") || strings.HasPrefix(url, "./") { + // Local file path: strip optional file:// scheme and read from disk. + filePath := strings.TrimPrefix(url, "file://") + data, rerr := os.ReadFile(filePath) + if rerr != nil { + rerr = wrapError(ctx, typ, "template_body_file_error", rerr) + return nil, rerr + } + tempStr = string(data) + } else { + if !strings.HasPrefix(url, "http") { + url = cfg.SiteURL + url + } + var ferr error + tempStr, ferr = o.fetch(ctx, cfg, url) + if ferr != nil { + ferr = wrapError(ctx, typ, "template_body_http_error", ferr) + return nil, ferr + } } temp, err := template.New(url).Parse(tempStr)