How to properly insert user input into HTML mail so that it's properly escaped?

E.g. when a user enters <br> so that it’s not going to be interpreted as a line break

You can use the following technique which will allow you to produce the html markup easily while escaping any user inputs.

  1. Generate the HTML inside a variable
  2. Convert the variable to a string using AS:NodeToString() function

Example input:

<ROOT>
  <Source test="&lt;br/&gt;"/>
</ROOT>

Example XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
  xmlns:AS="http://schema.advantages.cz/AsapFunctions"
  xmlns:date="http://exslt.org/dates-and-times" exclude-result-prefixes="AS date">

  <xsl:template match="ROOT">
    <ROOT>
      <xsl:apply-templates select="Source"/>
    </ROOT>
  </xsl:template>

  <xsl:template match="Source">
    <!-- generate the html into a variable first -->
    <xsl:variable name="body">
      <html>
        <xsl:value-of select="@test"/>
      </html>
    </xsl:variable>
    <Mail>
      <Body>
        <!-- here you convert everything from a node-set to a string -->
        <xsl:value-of select="AS:NodeToString(AS:NodeSet($body))"/>
      </Body>
    </Mail>
   </xsl:template>
</xsl:stylesheet>