Umbraco.Forms.Issues icon indicating copy to clipboard operation
Umbraco.Forms.Issues copied to clipboard

Razor Email Templates and absolute img/href paths?

Open mistyn8 opened this issue 6 months ago • 1 comments

Which Umbraco Forms version are you using? (Please write the exact version, example: 13.4.0)

13.5.0

Which Umbraco version are you using? (Please write the exact version, example: 13.5.2)

13.8.1

Issue summary

When using Model.BodyHtml, Model.HeaderHtml or Model.FooterHtml if we have sanitised locallinks in the rte for a.href or img.src when the email is sent we end up with relative paths in the email, which will cause issues as the email is out of context.. (even hardcoding rather than localLink UDIS will end up with RTE sanitising the url from absolute to relative, without messing with rte config but that would then apply globally and not just for when required lilke here in email generation)

Specifics

Currently working around this.. but feels like it's something forms should be doing for us.. with an extenstion method to pass in the section required and the site root (following the pattern for other hardcoded assets in the example template using a var siteDomain = Context.Request.Scheme + "://" + Context.Request.Host;)

Or perhaps this could be an extension in core to lean on... _htmlLocalLinkParser.EnsureInternalLinks(text: Model.BodyHtml, preview: false, urlMode: UrlMode.Absolute) ??

HtmlAgilityPack as a workaround seems a sensible approach currently..

// need to update localLink giving relative path to absolute
if (Model.BodyHtml?.ToString() is string html)
{
    var doc = new HtmlDocument();
    doc.LoadHtml(html);

    if (doc.DocumentNode.SelectNodes("//a[@href]") is HtmlNodeCollection links)
    {
        foreach (var link in links)
        {
            var href = link.GetAttributeValue("href", "");
            if (href.StartsWith('/'))
            {
                link.SetAttributeValue("href", $"{siteDomain}{href}");
            }
        }
        Model.BodyHtml = new HtmlString(doc.DocumentNode.OuterHtml);
    }

    if (doc.DocumentNode.SelectNodes("//img[@src]") is HtmlNodeCollection images)
    {
        foreach (var img in images)
        {
            var src = img.GetAttributeValue("src", "");
            if (src.StartsWith('/'))
            {
                img.SetAttributeValue("src", $"{siteDomain}{src}");
            }
        }
        Model.BodyHtml = new HtmlString(doc.DocumentNode.OuterHtml);
    }

}

Steps to reproduce

Umbraco forms send razor template email, with links to udis (content or media) the generated email contain relative paths that won't suffice.

Expected result / actual result

all relative paths should be made absolute, either provide an extension method to pass a domain, a canonical url set in forms appsettings, or taking the current domain from the httpContext. (would need to support mutli-lang and cultures too?)

mistyn8 avatar Jun 18 '25 09:06 mistyn8

Just checked in UmbForms 16.0.0 on Umb 16.0.0 and the same foible exists.. relative locallinks (content and media) remain relative urls.

Image

Image

Image

mistyn8 avatar Jun 18 '25 11:06 mistyn8

Hi @mistyn8,

This is a really great bug report, so thank you for being thorough! There is an underlying change that needs to be made in Umbraco CMS first, so I have opened a PR for that issue. Once merged in and released, a fix can then be applied to Umbraco Forms 13/16.

rickbutterfield avatar Sep 19 '25 12:09 rickbutterfield

This issue has been mentioned on Umbraco community forum. There might be relevant details there:

https://forum.umbraco.com/t/broken-url-when-inserting-a-link-to-a-text-control/6335/14

umbracocommunity avatar Nov 06 '25 00:11 umbracocommunity