Implemented Email templates relative paths
- Sakis Terz
-
Onderwerp Auteur
- Offline
Minder
Lees meer
- Berichten: 37
- Ontvangen bedankjes 0
9 maanden 2 weken geleden #3121
door Sakis Terz
Email templates relative paths werd gestart door Sakis Terz
Hi Ruud
I am using some links and some images in my email templates, but every time i re-open them the urls become relevant (e.g. <a href="subscribe").
Not sure if there is some filtering from the editor or is coming from your code.
Any idea?
Kind regards,
I am using some links and some images in my email templates, but every time i re-open them the urls become relevant (e.g. <a href="subscribe").
Not sure if there is some filtering from the editor or is coming from your code.
Any idea?
Kind regards,
Graag Inloggen deelnemen aan het gesprek.
- Ruud van Lent
-
- Offline
Minder
Lees meer
- Berichten: 1715
- Ontvangen bedankjes 111
9 maanden 2 weken geleden #3122
door Ruud van Lent
Beantwoord door Ruud van Lent in topic Email templates relative paths
Hi Sakis,
that is a editor 'feature' that (depending on your editor) can be turned on / off: note that this is then generic so when turning it off it will also be turned off in other extensions.
What I do is before saving the email template, turn off the editor (and check if all URL's are still absolute)
that is a editor 'feature' that (depending on your editor) can be turned on / off: note that this is then generic so when turning it off it will also be turned off in other extensions.
What I do is before saving the email template, turn off the editor (and check if all URL's are still absolute)
Graag Inloggen deelnemen aan het gesprek.
- Ruud van Lent
-
- Offline
Minder
Lees meer
- Berichten: 1715
- Ontvangen bedankjes 111
9 maanden 2 weken geleden - 9 maanden 2 weken geleden #3123
door Ruud van Lent
Beantwoord door Ruud van Lent in topic Email templates relative paths
Hi Sakis,
so did a deeper dive into this to see if I can improve
In the email send ochSubscriptions adds the following line:
<base href="[your domain]" />
What this does / should do, is instruct the email client to make a relative url (e.g. test-url) absolute (so: [your domain]/test-url)
This way you can use both absolute and relative urls in your email templates as these will then be handled by the email client.
but... what if the email client doesn't use / respect the 'base href' setting? Then the absolute urls will work, but the relative urls will not (as these point to nowhere).
tinyMCE can be configured to store urls as relative or absolute: this has impact on everything the editor is used for, so when changing it to store absolute urls (which we want in emails) then also in articles all urls will be absolute (which we don't want)...
So in the version above I have a version of ochSubscriptions that will convert all elements (a, img, link, script, form, input, video, audio, source) in the email template to absolute URLs when rendering and sending the email (so not in the template itself).
This way you can either use absolute or relative urls: absolute will stay unchanged 9as these can also point to another website) and relative urls will be made absolute pointing to your site.
Can you give this a test to see if it works as intended and solves this url nightmare
so did a deeper dive into this to see if I can improve

In the email send ochSubscriptions adds the following line:
<base href="[your domain]" />
What this does / should do, is instruct the email client to make a relative url (e.g. test-url) absolute (so: [your domain]/test-url)
This way you can use both absolute and relative urls in your email templates as these will then be handled by the email client.
but... what if the email client doesn't use / respect the 'base href' setting? Then the absolute urls will work, but the relative urls will not (as these point to nowhere).
tinyMCE can be configured to store urls as relative or absolute: this has impact on everything the editor is used for, so when changing it to store absolute urls (which we want in emails) then also in articles all urls will be absolute (which we don't want)...
So in the version above I have a version of ochSubscriptions that will convert all elements (a, img, link, script, form, input, video, audio, source) in the email template to absolute URLs when rendering and sending the email (so not in the template itself).
This way you can either use absolute or relative urls: absolute will stay unchanged 9as these can also point to another website) and relative urls will be made absolute pointing to your site.
Can you give this a test to see if it works as intended and solves this url nightmare

Laatst bewerkt 9 maanden 2 weken geleden doorRuud van Lent. Reden: new download versions!
Graag Inloggen deelnemen aan het gesprek.
- Sakis Terz
-
Onderwerp Auteur
- Offline
Minder
Lees meer
- Berichten: 37
- Ontvangen bedankjes 0
7 maanden 1 week geleden - 7 maanden 1 week geleden #3171
door Sakis Terz
Beantwoord door Sakis Terz in topic Email templates relative paths
Hi Ruud
Sorry for the late reply. I tried both the [your domain] and [your_domain] and they do not work.
Btw. I see that the email placeholders are using curly braces {}
Kind regards,
Sakis
Sorry for the late reply. I tried both the [your domain] and [your_domain] and they do not work.
Btw. I see that the email placeholders are using curly braces {}
Kind regards,
Sakis
Laatst bewerkt 7 maanden 1 week geleden doorSakis Terz.
Graag Inloggen deelnemen aan het gesprek.
- Ruud van Lent
-
- Offline
Minder
Lees meer
- Berichten: 1715
- Ontvangen bedankjes 111
7 maanden 1 week geleden - 7 maanden 1 week geleden #3172
door Ruud van Lent
Beantwoord door Ruud van Lent in topic Email templates relative paths
Hi Sakis,
I think there is some confusion. With [you domain] I mean you actual website domain.
So on my server that would be:
I think there is some confusion. With [you domain] I mean you actual website domain.
So on my server that would be:
- https
/onlinecommunityhub .nl/testlink
- or /testlink
Laatst bewerkt 7 maanden 1 week geleden doorRuud van Lent.
Graag Inloggen deelnemen aan het gesprek.
- Sakis Terz
-
Onderwerp Auteur
- Offline
Minder
Lees meer
- Berichten: 37
- Ontvangen bedankjes 0
7 maanden 1 week geleden #3173
door Sakis Terz
Beantwoord door Sakis Terz in topic Email templates relative paths
But my problem is exactly that, when I enter my actual domain, it gets stripped. This happen only with my domain. If I use urls pointing to outside domains it works.
Is there a placeholder I could use, instead of my actual domain?
Is there a placeholder I could use, instead of my actual domain?
Graag Inloggen deelnemen aan het gesprek.
- Sakis Terz
-
Onderwerp Auteur
- Offline
Minder
Lees meer
- Berichten: 37
- Ontvangen bedankjes 0
7 maanden 1 week geleden #3174
door Sakis Terz
Beantwoord door Sakis Terz in topic Email templates relative paths
Btw /testlink stays as is in the actual email message, leading nowhere
Graag Inloggen deelnemen aan het gesprek.
- Ruud van Lent
-
- Offline
Minder
Lees meer
- Berichten: 1715
- Ontvangen bedankjes 111
7 maanden 1 week geleden #3175
door Ruud van Lent
Beantwoord door Ruud van Lent in topic Email templates relative paths
What version of ochSubscriptions do you have installed?
In version 4.0.1 I have added the updated logic to always add the local domain name to the url: so when the editor strips it, when ochSubscriptions renders the email text from the template it will add it back
In version 4.0.1 I have added the updated logic to always add the local domain name to the url: so when the editor strips it, when ochSubscriptions renders the email text from the template it will add it back
Graag Inloggen deelnemen aan het gesprek.
- Sakis Terz
-
Onderwerp Auteur
- Offline
Minder
Lees meer
- Berichten: 37
- Ontvangen bedankjes 0
7 maanden 1 week geleden #3176
door Sakis Terz
Beantwoord door Sakis Terz in topic Email templates relative paths
Thanks for that!
I am currently on 3.13.3
Is 4.0.1 compatible with J4?
I am currently on 3.13.3
Is 4.0.1 compatible with J4?
Graag Inloggen deelnemen aan het gesprek.
- Ruud van Lent
-
- Offline
Minder
Lees meer
- Berichten: 1715
- Ontvangen bedankjes 111
7 maanden 1 week geleden #3177
door Ruud van Lent
Beantwoord door Ruud van Lent in topic Email templates relative paths
No it is not.
in your current install, locate file ContentConstructor.php and replace the function "prepareEmailBody" with the one below:
BACKUP and TEST
in your current install, locate file ContentConstructor.php and replace the function "prepareEmailBody" with the one below:
BACKUP and TEST

Code:
/**
* Function to prepare the Email body; add necessary HTML elements and framework
*
* @param string $body The body of the email
* @param string $subject The subject of the email
* @param string $style The style (css) of the email
*
* @return string
*/
private function prepareEmailBody($body, $subject, $style)
{
$charset = Factory::getApplication()->getDocument()->getCharset();
$preparedBody = '<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">' . "\n";
$preparedBody .= '<head>' . "\n";
$preparedBody .= '<!--[if gte mso 9]><xml><o:OfficeDocumentSettings><o:AllowPNG/><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml><![endif]-->' . "\n";
$preparedBody .= '<meta http-equiv="Content-Type" content="text/html; charset=' . strtolower($charset) . '" />' . "\n";
$preparedBody .= '<meta name="viewport" content="width=device-width, initial-scale=1.0" />' . "\n";
$preparedBody .= '<base href="' . Uri::root(false) . '" />' . "\n";
$preparedBody .= '<title>' . $subject . '</title>' . "\n";
$preparedBody .= $style;
$preparedBody .= '</head>' . "\n";
$preparedBody .= '<body yahoo="fix">' . $body . '</body>' . "\n";
$preparedBody .= '</html>';
// Load HTML content into DOMDocument
$dom = new \DOMDocument();
libxml_use_internal_errors(true); // Suppress warnings due to malformed HTML
$dom->loadHTML($preparedBody);
libxml_clear_errors();
$baseUrl = Uri::root(false);
// Define elements and attributes to be checked for relative URLs
$elementsToCheck = [
'a' => 'href',
'img' => 'src',
'link' => 'href',
'script' => 'src',
'form' => 'action',
'input' => 'src',
'video' => 'src',
'audio' => 'src',
'source' => ['src', 'srcset']
];
// Loop through each element and attribute in the list
foreach ($elementsToCheck as $tag => $attributes) {
$attributes = (array) $attributes; // Ensure it's an array for easy iteration
foreach ($dom->getElementsByTagName($tag) as $element) {
foreach ($attributes as $attribute) {
$url = $element->getAttribute($attribute);
// Check if the attribute value is a relative URL
if ($url) {
if (\strpos($url, $baseUrl) === 0) {
// Remove the base URL portion to make it relative
$url = \substr($url, \strlen($baseUrl));
$element->setAttribute($attribute, $url);
}
if (\parse_url($url, PHP_URL_SCHEME) === null) {
// Prepend base URL if it's a relative path
$element->setAttribute($attribute, \rtrim($baseUrl, '/') . '/' . \ltrim($url, '/'));
}
}
}
}
}
// // Handle inline styles (for background images)
// foreach ($dom->getElementsByTagName('*') as $element) {
// $style = $element->getAttribute('style');
// if (preg_match('/url\([\'"]?\/([^\'")]+)[\'"]?\)/i', $style, $matches)) {
// // Replace relative URL with absolute URL in the style attribute
// $absoluteUrl = rtrim($baseUrl, '/') . '/' . ltrim($matches[1], '/');
// $newStyle = str_replace($matches[0], "url('$absoluteUrl')", $style);
// $element->setAttribute('style', $newStyle);
// }
// }
// Save updated HTML content
$preparedBody = $dom->saveHTML();
return $preparedBody;
}
Graag Inloggen deelnemen aan het gesprek.