You could use a custom filter to do this. Here's a simple example I use for mailing lists which replaces #NAME with the name of the recipient:
-module(filter_inject_firstname).
-export([inject_firstname/3]).
-include("zotonic.hrl").
inject_firstname(Body, undefined, _Context) ->
Body;
inject_firstname(Body, Recipient, _Context) ->
Val = case proplists:get_value(props, Recipient, []) of
Props when is_list(Props) ->
[{email, proplists:get_value(email, Recipient)},
{name_first, proplists:get_value(name_first, Props)},
{name_surname, proplists:get_value(name_surname, Props)},
{name_surname_prefix, proplists:get_value(name_surname_prefix, Props)}];
_ ->
[{email, proplists:get_value(email, Recipient)}]
end,
Name = proplists:get_value(name_first, Val),
iolist_to_binary(re:replace(Body, "#NAME", Name, [global])).