--- /dev/null
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:date="http://exslt.org/dates-and-times"
+ xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:output
+ omit-xml-declaration = "yes"
+ doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
+ doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" />
+ <xsl:param name="source_ip_href">
+ <!-- customize this -->
+ <!-- <xsl:text>http://www.tana.it/lookup.php?host=</xsl:text> -->
+ <xsl:text>http://network-tools.com/default.asp?prog=lookup&host=</xsl:text>
+ <!-- alternative examples:
+ <xsl:text>http://www.ip-adress.com/reverse_ip/</xsl:text>
+ -->
+ </xsl:param>
+ <xsl:template match="feedback">
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:variable name="title">
+ Feedback from
+ <xsl:value-of select="report_metadata/org_name"/>
+ </xsl:variable>
+ <head>
+ <title>
+ <xsl:value-of select="$title"/>
+ </title>
+ <style type="text/css" id="internal-style">
+ body {
+ font-family: Arial, Helvetica, sans-serif;
+ color: #003300;
+ background-color: #ffcc66;
+ }
+ table, p {
+ margin: 1em;
+ padding: 4pt;
+ background-color: #ffeeaa;
+ border: 3pt solid #776633;
+ }
+ td, th {
+ margin: 2pt;
+ padding: 2pt;
+ border: 1pt solid #776633;
+ }
+ .pass {
+ background-color: #11bb00;
+ }
+ .fail {
+ background-color: #cc0000;
+ }
+ .dkimpolicy {
+ background-color: #ffff66;
+ }
+ .error {
+ background-color: #bbaaaa;
+ font-weight: bold;
+ }
+ .softfail {
+ background-color: #ff8866;
+ }
+ .reject {
+ background-color: #cc0000;
+ }
+ .quarantine {
+ background-color: #ff8866;
+ }
+ .normal {
+ }
+ .field {
+ font-weight: bold;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>
+ <xsl:value-of select="$title"/>
+ </h1>
+ <p>
+ <xsl:apply-templates select="report_metadata"/>
+ <br/>
+ <xsl:apply-templates select="policy_published"/>
+ </p>
+ <table>
+ <tr>
+ <th>
+ Relaying IP
+ </th>
+ <th>
+ message count
+ </th>
+ <th>
+ reason and disposition
+ </th>
+ <th>
+ From header
+ <br/>
+ (opt. envelope)
+ </th>
+ <th>
+ SPF
+ </th>
+ <xsl:variable name="signatures">
+ <xsl:for-each select="record/auth_results">
+ <xsl:sort select="count(dkim)"
+ data-type="number" order="descending"/>
+ <xsl:if test="position()=1">
+ <xsl:value-of select="count(dkim)"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:if test="$signatures > 0">
+ <th>
+ DKIM
+ </th>
+ <xsl:if test="$signatures > 1">
+ <th>
+ 2nd DKIM
+ </th>
+ <xsl:if test="$signatures > 2">
+ <th>
+ 3rd DKIM
+ </th>
+ </xsl:if>
+ </xsl:if>
+ </xsl:if>
+ </tr>
+ <xsl:text>
+ </xsl:text>
+ <xsl:apply-templates select="record"/>
+ </table>
+ <p>
+ <b><u>Legend</u><br/>
+ disposition: </b>
+ <span class="quarantine">quarantine</span>,
+ <span class="reject">reject</span>.<br/>
+ <b>spf: </b>
+ <span class="pass">pass</span>,
+ <span class="fail">fail</span>,
+ <span class="softfail">softfail</span>,
+ <span class="error">temperror or permerror</span>.<br/>
+ <b>dkim: </b>
+ <span class="pass">pass</span>,
+ <span class="fail">fail</span>,
+ <span class="dkimpolicy">policy</span>.
+ </p>
+ </body>
+ </html>
+ </xsl:template>
+ <xsl:template match="policy_published">
+ <span class="field">Domain: </span>
+ <xsl:value-of select="domain"/>
+ <xsl:text>; </xsl:text>
+ <span class="field">DKIM: </span>
+ <xsl:apply-templates select="adkim"/>
+ <xsl:text>; </xsl:text>
+ <span class="field">SPF: </span>
+ <xsl:apply-templates select="aspf"/>
+ <xsl:text>; </xsl:text>
+ <span class="field">policy published: </span>
+ <xsl:value-of select="p"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="sp"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="pct"/>
+ </xsl:template>
+ <xsl:template match="adkim|aspf">
+ <xsl:variable name="alignment">
+ <xsl:value-of select="."/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$alignment='r'">
+ <xsl:text>relaxed</xsl:text>
+ </xsl:when>
+ <xsl:when test="$alignment='s'">
+ <xsl:text>strict</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>{$alignment}</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="report_metadata">
+ <span class="field">Id: </span>
+ <xsl:value-of select="report_id"/>
+ <xsl:text>; </xsl:text>
+ <span class="field">begin: </span>
+ <xsl:call-template name="date-range">
+ <xsl:with-param name="utime" select="date_range/begin"/>
+ </xsl:call-template>
+ <xsl:text>; </xsl:text>
+ <span class="field">end: </span>
+ <xsl:call-template name="date-range">
+ <xsl:with-param name="utime" select="date_range/end"/>
+ </xsl:call-template>
+ <xsl:for-each select="error">
+ <xsl:if test="position()=1">
+ <br/>
+ <span class="field">Error: </span>
+ </xsl:if>
+ <span class="error">
+ <xsl:value-of select="."/>
+ </span>
+ <xsl:if test="not(position()=last())">
+ <br/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="date-range">
+ <xsl:param name="utime" select="0"/>
+ <xsl:choose>
+ <xsl:when test="function-available('date:add')">
+ <xsl:value-of
+ select="date:add('1970-01-01T00:00:00', date:duration($utime))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$utime"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="record">
+ <tr>
+ <xsl:apply-templates select="row"/>
+ <xsl:apply-templates select="identifiers|identities"/>
+ <xsl:apply-templates select="auth_results"/>
+ </tr>
+ <xsl:text>
+ </xsl:text>
+ </xsl:template>
+ <xsl:template match="row">
+ <td>
+ <a>
+ <xsl:attribute name="href">
+ <xsl:value-of select="$source_ip_href"/>
+ <xsl:value-of select="source_ip"/>
+ </xsl:attribute>
+ <xsl:value-of select="source_ip"/>
+ </a>
+ </td>
+ <td align="right">
+ <xsl:value-of select="count"/>
+ </td>
+ <td>
+ <xsl:attribute name="class">
+ <xsl:variable name="disposition">
+ <xsl:value-of select="policy_evaluated/disposition"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$disposition='reject'">
+ <xsl:text>reject</xsl:text>
+ </xsl:when>
+ <xsl:when test="$disposition='quarantine'">
+ <xsl:text>quarantine</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>normal</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:for-each select="policy_evaluated/reason">
+ <xsl:value-of select="type"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="comment"/>
+ <br/>
+ </xsl:for-each>
+ </td>
+ </xsl:template>
+ <xsl:template match="identifiers|identities">
+ <td>
+ <xsl:value-of select="header_from"/>
+ <xsl:if test="count(envelope_to) > 0">
+ <br/>
+ <xsl:value-of select="envelope_to"/>
+ </xsl:if>
+ </td>
+ </xsl:template>
+ <xsl:template match="auth_results">
+ <xsl:apply-templates select="spf"/><!-- one -->
+ <xsl:apply-templates select="dkim"/><!-- zero or more -->
+ </xsl:template>
+ <xsl:template name="class_attribute">
+ <xsl:attribute name="class">
+ <xsl:variable name="result">
+ <xsl:value-of select="result"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$result='pass'">
+ <xsl:text>pass</xsl:text>
+ </xsl:when>
+ <xsl:when test="$result='fail' or $result='hardfail'">
+ <xsl:text>fail</xsl:text>
+ </xsl:when>
+ <xsl:when test="$result='temperror' or $result='permerror'">
+ <xsl:text>error</xsl:text>
+ </xsl:when>
+ <xsl:when test="$result='policy'">
+ <xsl:text>dkimpolicy</xsl:text>
+ </xsl:when>
+ <xsl:when test="$result='softfail'">
+ <xsl:text>softfail</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>normal</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:template>
+ <xsl:template match="spf">
+ <td>
+ <xsl:call-template name="class_attribute" />
+ <xsl:value-of select="domain"/>
+ <br/>
+ <xsl:value-of select="scope"/>
+ <br/>
+ <xsl:value-of select="human_result"/>
+ </td>
+ </xsl:template>
+ <xsl:template match="dkim">
+ <td>
+ <xsl:call-template name="class_attribute" />
+ <xsl:value-of select="domain"/>
+ <br/>
+ <xsl:value-of select="selector"/>
+ <br/>
+ <xsl:value-of select="human_result"/>
+ </td>
+ </xsl:template>
+</xsl:stylesheet>
+