Hi, without code on how you create the email it is not easy to help, but I guess this link can help https://antecknat.se/blog/2016/03/07/xhtmlstring-render-blocks-and-convert-link-to-external-without-htmlhelper/
It is for epi 8, but I don't think the xhtmlstring have changed and should still be valid
There really is no code to show because I'm not doing anything fancy to the value that the user entered into the page in the "EmailTemplate" property. The property is just a basic property that when in the editor renders as the TinyMCE editor.
Here is the property on my pagetype that the user fills in with what the emails should say when sent out:
[CultureSpecific]
[Display(Name = "Email template for visitor submission",
GroupName = SystemTabNames.Content,
Description = "Message sent to the submitter once the event has been sucessfully submitted.",
Order = 250)]
[Searchable(false)]
public override XhtmlString EmailTemplateBodyMessage { get; set; }
When the user fills out the contents of that property and adds images and links to make the email more presentable, then i take the actual XhtmlString result and add it to the body of the email and send it out via SMTP.
When examining that property before i assign it to the email body the URL's are in relative fashion and look as they do in my original post.
I also tried the code above via that link you posted by trying to parse the URL fragments out of the XhtmlString result but the result is the same. Is there a setting or something that needs to be applied to allow images and links to not be saved as relative within the editor and stored in the XhtmlString property?
Ugh, this was harder then I though
This should have worked:
public static XhtmlString ToExternalLinks(this XhtmlString xhtmlString)
{
var result = new StringBuilder();
foreach (var fragment in xhtmlString.Fragments)
{
var urlFragment = fragment as UrlFragment;
result.Append(urlFragment != null ? UrlResolver.Current.GetUrl((new UrlBuilder(urlFragment.InternalFormat)), new VirtualPathArguments() { ContextMode = ContextMode.Default, ForceAbsolute = true }) : fragment.InternalFormat);
}
return new XhtmlString(result.ToString());
}
Since epi have added "ForceAbsolute = true" in the VirtualPathArguments, but did it work here? No.
So if you have Geta.EPi.Extensions installed, you can instead use this
public static XhtmlString ToExternalLinks(this XhtmlString xhtmlString)
{
var result = new StringBuilder();
foreach (var fragment in xhtmlString.Fragments)
{
var urlFragment = fragment as UrlFragment;
result.Append(urlFragment != null ? UrlResolver.Current.GetUrl((new UrlBuilder(urlFragment.InternalFormat)), new VirtualPathArguments() { ContextMode = ContextMode.Default }).AddHost() : fragment.InternalFormat);
}
return new XhtmlString(result.ToString());
}
If you don't have that addon and don't want to install it, you need these extensions too
public class UriHelpers
{
/// <summary>
/// Returns base URI for the site.
/// </summary>
/// <returns>Base site URI</returns>
public static Uri GetBaseUri()
{
var context = HttpContext.Current != null ? new HttpContextWrapper(HttpContext.Current) : null;
return GetBaseUri(context, SiteDefinition.Current);
}
/// <summary>
/// Returns base URI for the site.
/// </summary>
/// <returns>Base site URI</returns>
public static Uri GetBaseUri(HttpContextBase context, SiteDefinition siteDefinition)
{
var siteUri = context != null
? context.Request.Url
: siteDefinition.SiteUrl;
var scheme = context != null && !string.IsNullOrEmpty(context.Request.Headers["X-Forwarded-Proto"])
? context.Request.Headers["X-Forwarded-Proto"].Split(',')[0]
: siteUri?.Scheme;
var urlBuilder = new UrlBuilder(siteUri)
{
Scheme = scheme ?? "https"
};
return urlBuilder.Uri;
}
}
/// <summary>
/// String extensions.
/// </summary>
public static class StringExtensions
{
/// <summary>
/// Adds scheme and host to a relative URL. Uses UriHelpers.GetBaseUri() to retrieve base URL for the scheme and host.
/// </summary>
/// <param name="url">URL</param>
/// <returns>Returns URL with scheme and host.</returns>
public static string AddHost(this string url)
{
return url.AddHost(UriHelpers.GetBaseUri);
}
/// <summary>
/// Adds scheme and host to a relative URL.
/// </summary>
/// <param name="url">URL</param>
/// <param name="getBaseUri">Function which returns base URL.</param>
/// <returns>Returns URL with scheme and host.</returns>
public static string AddHost(this string url, Func<Uri> getBaseUri)
{
var baseUri = getBaseUri();
var uri = new Uri(baseUri, url).ToString();
return
new UriBuilder(uri) { Scheme = baseUri.Scheme, Port = -1 }
.ToString();
}
}
https://github.com/Geta/EPi.Extensions/blob/master/src/Geta.EPi.Extensions/StringExtensions.cs
https://github.com/Geta/EPi.Extensions/blob/master/src/Geta.EPi.Extensions/Helpers/UriHelpers.cs
Hope it works then :)
In one of our page types on our site we have a property that allows end users to create email templates that are used for sending out automated emails to visitors of te website. Inside the property they can add images and links, but the problem i am finding is that images and links are being stored inside the TinyMCE editor as relative paths so when the email is sent out the visitor cannot view the image or get to the actual link.
So for example, an image added to the property in the TinyMCE editor is stored like this:
As you can see the above URL is not the correct format that i need:
Even if i put the URL above in the browser on a icognito tab and adjust the URL to include the base URL of the site, it asks me to login to the website but the image is not locked and is public, which tells me the URL given is more the editor URL and not the public URL that i need.
The same goes for regular links to content as well.
How can i go abouts resolving this so that when an image is added to the TinyMCE editor or even a link that the URL is actually the public one so that when i generate the emails and take the content from the email template property that the URL's are properly formed and not relative