Sitecore: WFFM Send Email Message does not remove field tokens when there is no Field Data

I ran into an issue with our WFFM (8.1 rev. 160523) implementation on Sitecore XP 8.1 where the email sent by WFFM “Send Message Action” does not remove un-expanded tokens from the email body. This scenario comes up when you have optional fields in your form and the user does not supply values for the optional fields. The default implementation seems to have a bug and I couldn’t find an option on the form or at the field level to change this behavior.

Thinking that may be the Field Ids in the form got messed up, I decided to create a test form from scratch with just two fields TEST FIELD 1 and TEST FIELD 2 (Optional).

Form Creation:

Send Email Editor:

Public View:

Output Email Body:
TEST FIELD 1: GIRISH
TEST FIELD 2: [TEST FIELD 2]

We basically don’t want [TEST FIELD 2] to show up at all. If you look at the html it still contains the label id token.

1
[<label id="{42435BFE-8225-445A-3568-ACBF16E6CD862}">TEST FIELD 2</label>]

Solution:
I ended up implementing a custom pipeline processor for processMessage. Basically, just dotpeeked the Sitecore.Forms.Core.Pipelines.ProcessMessage class in the Sitecore.Forms.Core.dll assembly and copied the existing code add then added the code to remove un-expanded tokens at the end. Finally, I used a patch file to hook my processor in to the pipeline. Don’t forget to publish the patch file to the App_Config/Include folder and also ensure that it’s loaded after the Sitecore.Forms.config file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
public class ProcessMessage
{
    private readonly string srcReplacer;
    private readonly string shortHrefReplacer;
    private readonly string shortHrefMediaReplacer;
    private readonly string hrefReplacer;

    public IItemRepository ItemRepository { get; set; }

    public IFieldProvider FieldProvider { get; set; }

    public ProcessMessage()
        : this(DependenciesManager.WebUtil)
    {
    }

    public ProcessMessage(IWebUtil webUtil)
    {
        Assert.IsNotNull((object)webUtil, "webUtil");
        this.srcReplacer = string.Join(string.Empty, new string[3] { "src="", webUtil.GetServerUrl(), "/~" });
        this.shortHrefReplacer = string.Join(string.Empty, new string[3] { "
href=\"", webUtil.GetServerUrl(), "/" });
        this.shortHrefMediaReplacer = string.Join(string.Empty, new string[3] { "href=\"", webUtil.GetServerUrl(), "/~/" });
        this.hrefReplacer = this.shortHrefReplacer + "~";
    }

    public void ExpandTokens(ProcessMessageArgs args)
    {
        Assert.IsNotNull((object)this.ItemRepository, "ItemRepository");
        Assert.IsNotNull((object)this.FieldProvider, "FieldProvider");

        foreach (AdaptedControlResult field in args.Fields)
        {
            IFieldItem fieldItem = this.ItemRepository.CreateFieldItem(this.ItemRepository.GetItem(field.FieldID));
            var str1 = field.Value;
            var str2 = "";
            try
            {
                str2 = this.FieldProvider.GetAdaptedValue(field.FieldID, str1);
            }
            catch(Exception)
            {
                str2 = str1;
            }


            if(string.IsNullOrWhiteSpace(str2))
            {
                 Sitecore.Diagnostics.Log.Error("WFFM Field Error Field Name: " + field.FieldName + "; FieldID:" +     field.FieldID, this);
            }

            str2 = str2.Replace("src="/sitecore/shell/themes/standard/-", this.srcReplacer)
                        .Replace("
href="/sitecore/shell/themes/standard/-", this.hrefReplacer)
                        .Replace("on\\w*=".*?"", string.Empty);

            if (args.MessageType == MessageType.Sms)
            {
                args.Mail.Replace("[{0}]".FormatWith((object)fieldItem.FieldDisplayName), str2);
                args.Mail.Replace("[{0}]".FormatWith((object)fieldItem.Name), str2);
            }
            else
            {
                if (!string.IsNullOrEmpty(field.Parameters) && args.IsBodyHtml)
                {
                    if (field.Parameters.StartsWith("multipleline"))
                        str2 = str2.Replace(Environment.NewLine, "<br/>");
                    if (field.Parameters.StartsWith("secure") && field.Parameters.Contains("<schidden>"))
                        str2 = Regex.Replace(str2, "\\d", "*");
                }
                string str3 = Regex.Replace(args.Mail.ToString(), "\\[<label id="" + (object)fieldItem.ID + "">[^<]+?</label>]",     str2).Replace(fieldItem.ID.ToString(), str2);
                args.Mail.Clear().Append(str3);
            }
            args.From = args.From.Replace("[" + (object)fieldItem.ID + "]", str2);
            args.From = args.From.Replace(fieldItem.ID.ToString(), str2);
            args.To.Replace(string.Join(string.Empty, new string[3] { "[", fieldItem.ID.ToString(), "]" }), str2);
            args.To.Replace(string.Join(string.Empty, new string[1] { fieldItem.ID.ToString()}), str2);
            args.CC.Replace(string.Join(string.Empty, new string[3] { "[", fieldItem.ID.ToString(), "]" }), str2);
            args.CC.Replace(string.Join(string.Empty, new string[1] { fieldItem.ID.ToString()}), str2);
            args.Subject.Replace(string.Join(string.Empty, new string[3] { "[", fieldItem.ID.ToString(), "]" }), str2);
            args.From = args.From.Replace("[" + fieldItem.FieldDisplayName + "]", str2);
            args.To.Replace(string.Join(string.Empty, new string[3] { "[", fieldItem.FieldDisplayName, "]" }), str2);
            args.CC.Replace(string.Join(string.Empty, new string[3] { "[", fieldItem.FieldDisplayName, "]" }), str2);
            args.Subject.Replace(string.Join(string.Empty, new string[3] { "[", fieldItem.FieldDisplayName, "]"}), str2);
            args.From = args.From.Replace("[" + field.FieldName + "]", str2);
            args.To.Replace(string.Join(string.Empty, new string[3] { "[", field.FieldName, "]" }), str2);
            args.CC.Replace(string.Join(string.Empty, new string[3] { "[", field.FieldName, "]" }), str2);
            args.Subject.Replace(string.Join(string.Empty, new string[3] { "[", field.FieldName, "]" }), str2);

        }

        //remove unexpanded tokens
        var str4 = Regex.Replace(args.Mail.ToString(), "\\[<label id=".*">[^<]+?</label>]", "");
        args.Mail.Clear().Append(str4);
    }
}

Patch File:

1
2
3
4
5
6
7
8
9
10
11
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
    <pipelines>
       <processMessage>
             <processor type="Client.Sitecore.Custom.Forms.ProcessMessage, Client.Sitecore.Custom.Forms" method="ExpandTokens" patch:instead="*[@method='ExpandTokens']">
                 <ItemRepository ref="/sitecore/wffm/itemRepository"/>
                 <FieldProvider ref="/sitecore/wffm/fieldProvider"/>
             </processor>
       </processMessage>
    </pipelines>
</sitecore>