<?php
/**
 * Performs simple keyword replacement on the email before sending.
 *
 * @package silverstripe-newsletter-keywords
 */
class NewsletterEmailKeywordsExtension extends Extension {

	public function onBeforeSend() {
		$body         = $this->owner->Body();
		$replacements = $this->owner->Newsletter()->getKeywordReplacements($this->owner);
		$keywords     = array();

		$body = is_object($body) ? $body->forTemplate() : $body;
		$body = preg_replace('/"[^"]*%7B%24(\w+)%7D/', '"{\$$1}', $body);

		foreach ($replacements as $k => $v) {
			$keywords[] = "{\$$k}";
		}

		$this->owner->setBody(DBField::create('HTMLText', str_replace(
			$keywords, array_values($replacements), $body
		)));
	}
}
<?php
/**
 * Performs simple keyword replacement on the email before sending.
 *
 * @package silverstripe-newsletter-keywords
 */
class NewsletterEmailKeywordsExtension extends Extension {

	public function onBeforeSend() {
		$body         = $this->owner->Body();
		$replacements = $this->owner->Newsletter()->getKeywordReplacements($this->owner);
		$keywords     = array();

		foreach ($replacements as $k => $v) {
			$keywords[] = "{\$$k}";
		}

		$this->owner->setBody(DBField::create('HTMLText', str_replace(
			$keywords,
			array_values($replacements),
			is_object($body) ? $body->forTemplate() : $body
		)));
	}

}

--- 
+++ 
@@ -11,15 +11,15 @@
 		$replacements = $this->owner->Newsletter()->getKeywordReplacements($this->owner);
 		$keywords     = array();
 
+		$body = is_object($body) ? $body->forTemplate() : $body;
+		$body = preg_replace('/"[^"]*%7B%24(\w+)%7D/', '"{\$$1}', $body);
+
 		foreach ($replacements as $k => $v) {
 			$keywords[] = "{\$$k}";
 		}
 
 		$this->owner->setBody(DBField::create('HTMLText', str_replace(
-			$keywords,
-			array_values($replacements),
-			is_object($body) ? $body->forTemplate() : $body
+			$keywords, array_values($replacements), $body
 		)));
 	}
-
 }
Replace escaped keywords in attributes.
