Rick Savoy
Rick Savoy

Reputation: 341

SQL Server HTML Body Email not formatting correctly (added XML)

The Story: We have a requirement to send periodic requests to customer requesting they re-certify thier profiles that are in our system. Curently this in a manual process but we have dscided to automate it by using SQL Server's email capabilites.

My solution: I'm curently working on the body of the email which will then be emailed to the customer. Required in the body are the contact information and a table with each process that needs to be recertified.

The problem: The difficulty I am encountering is that, even though I'm moving (it looks like) from top to bottom, the HTML email body I've developed is not formatting properly and I can't tell why not.

Here is my SQL code

WITH htmlresult AS (
SELECT 
''AS RowNumber 
,'<html><head><title></title></head> 
    <body> <BR>' AS HtmlData

UNION ALL

select top 1
''AS RowNumber 
, 'Date: &nbsp;&nbsp; '  + CAST(GETDATE() AS VARCHAR(12)) + '<BR><BR> ' + 
  'Re: Annual Re-certification Information Profiles'  + '<BR><BR> ' + 
  'Contact Name: &nbsp;&nbsp; ' + dbo.DueTempTbl.[Contact]  + ' &nbsp;&nbsp; 
Email: ' + dbo.DueTempTbl.[EMAIL] + ' <BR>' +
  'GenName: &nbsp;&nbsp; ' + dbo.DueTempTbl.[GenName]+ '<BR> ' +
  'GenNumber: &nbsp;&nbsp; ' + dbo.DueTempTbl.[Gen#] + '<BR><BR> ' AS 
 HtmlData
FROM  dbo.DueTempTbl 
WHERE  [RECERTDUE] Between DATEADD(DAY, -180, GETDATE()) And DATEADD(DAY, 
+60, GETDATE())  
AND ((dbo.DueTempTbl.[Terr])='AZ1') AND ((LTrim(RTrim([EMAIL])))<>'')
AND [Gen#]=623113

UNION ALL

SELECT 
'' AS RowNumber 
, 'The annual re-certification of your information profiles are due for 
 those expiring <BR> in the next ninety (90) days. ' + 
  'It is necessary to complete this re-certification in advance to ensure no 
<BR> interruption of future service.  <br><br>'  AS HtmlData

union all

SELECT '' AS RowNumber 
,'  <br><br><table><tr style="background-color: #5D7B9D; font-weight: bold; 
color: white;">
    <td>ID Number</td><td>Description</td><td>Recert Due Date</td></tr>' AS 
HtmlData

Union All     

SELECT ROW_NUMBER() OVER (ORDER BY [IDNumber]) AS RowNumber
,'<td>' + CAST([IDNumber] as VARCHAR(10)) + '</td><td>' + RTrim([WasteName]) 
+ '</td>' + 
 '<td>' + CAST([RECERTDUE]as VARCHAR(12)) + '</td>' AS HtmlData
FROM  dbo.DueTempTbl 
WHERE  [RECERTDUE] Between DATEADD(DAY, -180, GETDATE()) And DATEADD(DAY, 
+60, GETDATE())  
AND [Gen#]=623113
SELECT HtmlData =
    CASE RowNumber%2
        WHEN 0 THEN '<tr style="background-color: #F7F6F3">' + HtmlData + 
'</tr>'
        ELSE '<tr>' + HtmlData + '</tr>'
    END
FROM htmlresult

UNION ALL

SELECT '</table><BR><BR> Thank you for allowing us to provide you with 
reliable and safe service.  <BR> ' +
       'We strive for excellence in providing these services and we hope 
that this has been your <BR> experience ' +
       'with us.</body></html>' 

Here is the output I was expecting

<html>
<head>
<title></title>
</head>
<body>
<BR>Date: &nbsp;&nbsp; Sep  7 2018 
<BR><BR> Re: Annual Re-certification of Information Profiles
<BR><BR> Contact Name: &nbsp;&nbsp; Paul Bunyan &nbsp;&nbsp; Email: 
[email protected]                            
<BR>Gen Name: &nbsp;&nbsp; Some Company   
<BR>Gen Number: &nbsp;&nbsp; 623113<BR><BR>
<table>
<tr style="background-color: #F7F6F3">The annual re-certification of your 
Information Profiles are due for those expiring <BR> in the next ninety (90)
 days. It is necessary to complete this process in advance to ensure no <BR> 
interruption of service.  <br><br></tr>
<tr style="background-color: #F7F6F3"> <br><br><table><tr style="background- 
color: #5D7B9D; font-weight: bold; color: white;">    
<td>IDNumber</td><td>Decription</td><td>Recert Due Date</td></tr></tr>
<tr><td>780877</td><td>quas vidit docendi pro</td><td>Sep 13 2018 </td></tr>
<tr style="background-color: #F7F6F3"><td>780878</td><td>Lorem ipsum 
dolor</td><td>Sep 13 2018 </td></tr>
<tr><td>780879</td><td>sit amet</td><td>Sep 13 2018 </td></tr>
<tr style="background-color: #F7F6F3"><td>780880</td><td>uisset eligendi 
ius</td><td>Sep 13 2018 </td></tr>
<tr><td>780881</td><td>vix illum commune</td><td>Sep 13 2018 </td></tr>
<tr style="background-color: #F7F6F3"><td>780882</td><td>mea omnesque 
liberavisse</td><td>Sep 13 2018 </td></tr>
<tr><td>780883</td><td>suscipiantur cu</td><td>Sep 13 2018 </td></tr>
<tr style="background-color: #F7F6F3"><td>780884</td><td>cam appareat mei 
ut</td><td>Sep 13 2018 </td></tr>
<tr><td>780885</td><td>sit maiorum repudiare</td><td>Sep 13 2018 </td></tr>
<tr style="background-color: #F7F6F3"><td>780886</td><td>olum dicat 
fabellas</td><td>Sep 13 2018 </td></tr>
<tr><td>780937</td><td>vidit docendi pro</td><td>Sep 13 2018 </td></tr>
</table><BR><BR>
Thank you for allowing us to provide you with reliable and safe services. We 
strive for excellence in providing these services and we hope that this has 
been your 
<BR> experience with us.
</body></html>

And here is what I got

<tr style="background-color: #F7F6F3">
<html>
<head>
<title></title>
</head>
<body>
<BR>Date: &nbsp;&nbsp; Sep  7 2018
<BR><BR> Re: Annual Re-certification of Information Profiles
<BR><BR> Contact Name: &nbsp;&nbsp; Paul Bunyan &nbsp;&nbsp; Email: 
[email protected]
<BR>Gen Name: &nbsp;&nbsp; Some Company
<BR>Gen Number: &nbsp;&nbsp; 623113<BR><BR>        
<BR>Date: &nbsp;&nbsp; Sep  7 2018
<BR><BR> Re: Annual Re-certification of Information Profiles
<BR><BR> Contact Name: &nbsp;&nbsp; Paul Bunyan &nbsp;&nbsp; Email: 
[email protected]
<BR>Gen Name: &nbsp;&nbsp; Some Company
<BR>Gen Number: &nbsp;&nbsp; 623113<BR><BR>
<tr style="background-color: #F7F6F3">The annual re-certification of your 
Information Profiles are due for those expiring 
<BR> in the next ninety (90) days. It is necessary to complete this process 
in advance to ensure no <BR> interruption of service.  <br><br></tr>
<tr style="background-color: #F7F6F3"> <br><br><table><tr style="background- 
color: #5D7B9D; font-weight: bold; color: white;">      
<td>IDNumber</td><td>Decription</td><td>Recert Due Date</td></tr></tr>
<tr><td>780877</td><td>quas vidit docendi pro</td><td>Sep 13 2018 </td></tr>
<tr style="background-color: #F7F6F3"><td>780878</td><td>Lorem ipsum 
dolor</td><td>Sep 13 2018 </td></tr>
<tr><td>780879</td><td>sit amet</td><td>Sep 13 2018 </td></tr>
<tr style="background-color: #F7F6F3"><td>780880</td><td>uisset eligendi 
ius</td><td>Sep 13 2018 </td></tr>
<tr><td>780881</td><td>vix illum commune</td><td>Sep 13 2018 </td></tr>
<tr style="background-color: #F7F6F3"><td>780882</td><td>mea omnesque 
liberavisse</td><td>Sep 13 2018 </td></tr>
<tr><td>780883</td><td>suscipiantur cu</td><td>Sep 13 2018 </td></tr>
<tr style="background-color: #F7F6F3"><td>780884</td><td>cam appareat mei 
ut</td><td>Sep 13 2018 </td></tr>
<tr><td>780885</td><td>sit maiorum repudiare</td><td>Sep 13 2018 </td></tr>
<tr style="background-color: #F7F6F3"><td>780886</td><td>olum dicat 
fabellas</td><td>Sep 13 2018 </td></tr>
<tr><td>780937</td><td>vidit docendi pro</td><td>Sep 13 2018 </td></tr>
</table><BR><BR> Thank you for allowing us to provide you with reliable and 
safe services. We strive for excellence in providing these services and we 
hope that this has been your <BR> experience with us.</body></html>

(SQL Server 2008R2)

By the way, I really should give credit to Steve Moore, the source I used in development of this code. http://www.sqlservercentral.com/articles/T-SQL/99398/

Upvotes: 2

Views: 546

Answers (2)

Rick Savoy
Rick Savoy

Reputation: 341

Ok, XML worked! Here is the final code that I used and it is producing well formated HTML.

Declare @Body varchar(max),
      @TableHead varchar(max),
      @TableTail varchar(max),
      @Message1 varchar (max),
      @Message2 varchar (max),
      @genNum as integer,
      @HTMLHead as varchar(max),
      @TableBody varchar(max)

SET @genNum = 623113      

Set NoCount On;

SELECT TOP 1 @Message1 ='Date: &nbsp;&nbsp; '  + CAST(GETDATE() AS VARCHAR(12)) + '<BR><BR> ' + 
  'Re: Annual Re-certification of Information Profiles'  + '<BR><BR> ' + 
  'Contact Name: &nbsp;&nbsp; ' + dbo.TblRecertsDueTemp.[Contact]  + ' &nbsp;&nbsp; Email: ' + 
  dbo.TblRecertsDueTemp.[EMAIL] + ' <BR> ' +
  'Generator Name: &nbsp;&nbsp; ' + dbo.TblRecertsDueTemp.[GenName]+ '<BR> ' +
  'Generator Number: &nbsp;&nbsp; ' + dbo.TblRecertsDueTemp.[Gen#] + '<BR><BR> '
FROM  dbo.TblRecertsDueTemp 
WHERE  DBO.FN_ChangeToDate([RECERTDUE])  Between DATEADD(DAY, -180, GETDATE()) And DATEADD(DAY, +60, GETDATE())  
AND [Gen#]=@genNum;

SET @Message2 = @Message1 + '<table style="width:533px;border-collapse: collapse; border: none;"> <tr><td>The annual re-certification of your Information Profiles are due for those expiring in the next ninety (90) days. It is necessary to complete this process in advance to ensure no interruption of future services. We have a <a href="url">simple Web form</a> for you to use to complete this process. <a href="url">Click here</a> to see directions on how to complete these recertifications. </td></tr> </table> <BR><BR> '

Set @HTMLHead = '<!DOCTYPE html> <html><head>' +
                  '<style>' +
                  'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:11pt;} ' +
              '</style>' +
              '</head>' +
              '<body>'

Set @TableHead =  '<table cellpadding=0 cellspacing=0 border=0>' +
              '<tr style="background-color: #5D7B9D; font-weight: bold; color: white;">' +      
              '  <td>WIP</td>'+
              '  <td>Decription</td>'+
              '  <td>Recert Due Date</td>'+
              '</tr>' 

Set @TableTail = '</table></body></html>'; 
Select @TableBody = (SELECT ROW_NUMBER() OVER (ORDER BY [WIP])  % 2 As [TRRow],
    CAST([IP] AS VARCHAR(10)) + '   '  As [TD], 
    RTrim([ProcessName]) As [TD],
    CONVERT(varchar,DBO.FN_ChangeToDate([RECERTDUE]),101) As [TD]
FROM  dbo.TblRecertsDueTemp 
WHERE  DBO.FN_ChangeToDate([RECERTDUE])  Between DATEADD(DAY, -180, GETDATE()) And DATEADD(DAY, +60, GETDATE())  
AND [Gen#]=@genNum
For XML raw('tr'), Elements)

-- Replace the entity codes and row numbers
Set @TableBody = Replace(@TableBody, '_x0020_', space(1))
Set @TableBody = Replace(@TableBody, '_x003D_', '=')
Set @TableBody = Replace(@TableBody, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#C6CDDD>')
Set @TableBody = Replace(@TableBody, '<TRRow>0</TRRow>', '')

Select @Body = @HTMLHead+ @Message2 + @TableHead + @TableBody + @TableTail

-- return output
Select @Body

(Developed with the help of Robert Davis- http://www.sqlservercentral.com/blogs/robert_davis/2010/06/15/Building-HTML-Emails-With-SQL-Server-and-XML/)

Upvotes: 0

Xedni
Xedni

Reputation: 4715

Assuming you're talking about that chunk of mising values

10. [email protected]
10. <BR>Gen Name: &nbsp;&nbsp; Some Company     11. <BR>Gen Name: &nbsp;&nbsp; Some Company
12. <BR>Gen Number: &nbsp;&nbsp; 623113<BR><BR>        
13. <BR>Date: &nbsp;&nbsp; Sep  7 2018
14. <BR><BR> Re: Annual Re-certification of Information Profiles
15. <BR><BR> Contact Name: &nbsp;&nbsp; Paul Bunyan &nbsp;&nbsp; Email: 
16. [email protected]
17. <BR>Gen Name: &nbsp;&nbsp; Some Company

it's probably because this section of code is not returning any data

select top 1
''AS RowNumber 
, 'Date: &nbsp;&nbsp; '  + CAST(GETDATE() AS VARCHAR(12)) + '<BR><BR> ' + 
  'Re: Annual Re-certification Information Profiles'  + '<BR><BR> ' + 
  'Contact Name: &nbsp;&nbsp; ' + dbo.DueTempTbl.[Contact]  + ' &nbsp;&nbsp; 
Email: ' + dbo.DueTempTbl.[EMAIL] + ' <BR>' +
  'GenName: &nbsp;&nbsp; ' + dbo.DueTempTbl.[GenName]+ '<BR> ' +
  'GenNumber: &nbsp;&nbsp; ' + dbo.DueTempTbl.[Gen#] + '<BR><BR> ' AS 
 HtmlData
FROM  dbo.DueTempTbl 
WHERE  [RECERTDUE] Between DATEADD(DAY, -180, GETDATE()) And DATEADD(DAY, 
+60, GETDATE())  
AND ((dbo.DueTempTbl.[Terr])='AZ1') AND ((LTrim(RTrim([EMAIL])))<>'')
AND [Gen#]=623113

I'd strongly recommend against writing HTML in SQL, but if you must, I would further discourage you from using string concatenation in favor of XML manipulation (which HTML is basically a subset)

Upvotes: 1

Related Questions