7

I use ClientApiService from Sitecore 9.1 to send e-mails programmatically and I don't use custom facests to store custom token information.

I have automated message based on web item with usage of custom token $my-html$

This is my code:

public IClientApiService ClientApiService { get; }

public ClientSamples(IClientApiService clientApiService)
{
    ClientApiService = clientApiService;
}

public void SendAutomatedExample(Guid messageId, ContactIdentifier identifier, object htmlContent)
{
    var messageOpitons = new AutomatedMessage();

    messageOpitons.MessageId = messageId;
    messageOpitons.ContactIdentifier = identifier;
    messageOpitons.CustomTokens = new Dictionary<string, object> { {"my-html", htmlContent} };

    ClientApiService.SendAutomatedMessage(messageOpitons);
}

When I pass string as htmlContent service.SendAutomatedExample(someId, someidentifier, "<span>test</span>"), then Contact get correct email which has replaced $my-html$. But it has plain text and not html.

When I pass MvcHtmlString as htmlContent service.SendAutomatedExample(someId, someidentifier, new MvcHtmlString("<span>test</span>")), then Contact get email with $my-html$ replaced by {}.

Additional information: I need to render some dynamic html table as custom token I am not able to use custom facests for this scenario

9

Solution

Posted on Git Gist

Existing page emails

Probably, it's better to use Existing Page email template for this purpose.

If you really want to implement it with tokens, use explanation bellow.

Tokens replacement explanation

There is Sitecore.EmailCampaign.Cm.Pipelines.SendEmail.FillEmail processor in SendEmail pipeline. It uses GetMailFiller(args)?.FillEmail(); code.

MailFiller has FillBody method. And implemtation of this abstract class HtmlMailFiller has implementation:

this.Email.HtmlBody = this._htmlMailBase.ReplaceTokens(body);

And then it's goes to :

public virtual string ReplaceTokens(string text)
{
   if (this.PersonalizationManager != null)
      text = this.PersonalizationManager.ModifyText(text);
   return text;
}

Where _htmlMailBase has PersonalizationManager, which contains ReplaceTokens method. You could review Sitecore.Modules.EmailCampaign.Core.Personalization.PersonalizationManager class for more details.

Why HTML token are passed as plain text

Method PersonalizationManager - ReplaceTokens encodes token values:

text = text.Replace("$" + key + "$", WebUtility.HtmlEncode(str));

So, you'll need to redefine pipeline to achieve replacement with HTML.

  • Fantastic answer, can you add in how you would customize the replacement pipeline to achieve the result? – Pete Navarra Mar 27 at 21:29
  • I wish I could use existing web page, but I trigger e-mail with help of custom controller outside from sitecore. And I should pass an array of custom items to render them as a table. – Mickey P Mar 28 at 8:53
  • I was wrong with first explanation with array of characters. I fixed it in answer. Also, I published code on Git Gist. But really think twice before using it, as it some kind of hacking default Sitecore behaviour. – Igor Zharikov Mar 28 at 9:27
  • Found same thing about HtmlEncode in PersonalizationManager and started to implement all this custom stuff, but with one difference - I am trying to inherit from WebPageMail and override PersonalizationManager property with custom implementation, but you saved my day, thank you so much – Mickey P Mar 28 at 10:41
  • Sad news, but this approach doesn't work :c EcmMessage from SendMessageArgs contains Body with replaced tokens and they are encoded. So all this custom code doesn't affect it. Also In Sitecore9.1 MailFiller depenends on PipelineHelper and EcmSettings – Mickey P Mar 28 at 13:21
0

I agreed with Igor, it is very unsafe to use such manipulations, but I found dirty solution for this :)

Working solution to Sitecore 9.1 based on Igor's gist - solution with decoding of message

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.