Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

String.Format failing on style section of HTML Email Template

I am sending HTML email template using Bodybuilder and a mail sending service. I used this link learn.

https://www.c-sharpcorner.com/article/send-email-using-templates-in-asp-net-core-applications/

Anyway, I created my email template using an external service (https://topol.io/).

It is giving me errors when I try to use the generated HTML file with the String.FOrmat command referenced in the first link. I finally figured out it is this section of code causing the String.Format to fail.

This is my c# code that normally works with other HTML templates:

using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
            {
                builder.HtmlBody = SourceReader.ReadToEnd();
            }

string messagebody = string.Format(builder.HtmlBody,
                    //Not important
                    );

Now, this style code in the HTML causes the String.Format to crash (or the bodybuilder, I'm not sure exactly which one has the issue, it fails at string.format).

<style type="text/css">
        #outlook a {
            padding: 0;
        }

        .ReadMsgBody {
            width: 100%;
        }

        .ExternalClass {
            width: 100%;
        }

            .ExternalClass * {
                line-height: 100%;
            }

        body {
            margin: 0;
            padding: 0;
            -webkit-text-size-adjust: 100%;
            -ms-text-size-adjust: 100%;
        }

        table, td {
            border-collapse: collapse;
            mso-table-lspace: 0pt;
            mso-table-rspace: 0pt;
        }

        img {
            border: 0;
            height: auto;
            line-height: 100%;
            outline: none;
            text-decoration: none;
            -ms-interpolation-mode: bicubic;
        }

        p {
            display: block;
            margin: 13px 0;
        }
    </style>
    <!--[if !mso]><!-->
    <style type="text/css">
        @media only screen and (max-width:480px) {
            @-ms-viewport {
                width: 320px;
            }

            @viewport {
                width: 320px;
            }
        }
    </style>
    <style type="text/css">
        @media only screen and (min-width:480px) {
            .mj-column-per-100 {
                width: 100% !important;
            }

            .mj-column-per-60 {
                width: 60% !important;
            }

            .mj-column-per-40 {
                width: 40% !important;
            }

            .mj-column-per-50 {
                width: 50% !important;
            }
        }
    </style>
    <!--[if mso]><xml>
            <o:OfficeDocumentSettings>
            <o:AllowPNG/>
            <o:PixelsPerInch>96</o:PixelsPerInch>
            </o:OfficeDocumentSettings></xml><![endif]-->
    <!--[if lte mso 11]><style type="text/css">.outlook-group-fix {    width:100% !important;  }</style>
        <![endif]-->
    <!--[if !mso]><!-->
    <link href="https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700" rel="stylesheet" type="text/css">
    <link href="https://fonts.googleapis.com/css?family=Merriweather" rel="stylesheet" type="text/css">
    <style type="text/css">
        @import url(https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700);
        @import url(https://fonts.googleapis.com/css?family=Merriweather);
    </style>
    <!--<![endif]-->

Any ideas? I am open to suggestions of how to put this CSS section externally if the reason for the failure is not obvious.

like image 992
dave317 Avatar asked Jun 14 '18 08:06

dave317


2 Answers

You are getting that error because curly braces are used in string.Format as a place holder for a value parameter.

One way to fix your problem is replacing braces with double braces:

using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile))
            {
                builder.HtmlBody = SourceReader.ReadToEnd();
            }

string htmlBody = builder.HtmlBody.Replace("{", "{{").Replace("}","}}")
string messagebody = string.Format(htmlBody,
                    //Not important
                    );
like image 69
matramos Avatar answered Nov 15 '22 17:11

matramos


You are calling String.Format on a string that contains lots of CSS definitions. CSS definitions include many { and } pairs. String.Format interprets { and } pairs as placeholders for substitution but, that is not what they represent in your string.

Why do you need to use String.Format in this scenario?

Why not instead do,

builder.HtmlBody = File.ReadAllText(pathToFile);

If //Not important is, in fact important, you could escape the braces in your template, as per this answer. So that braces you do not want to substitute become '{{' and '}}' respectively.

Basically, run a further one time preparation step on your template, switching { for {{ and } for }} unless they represent a placeholder you would like to substitute.

like image 31
Jodrell Avatar answered Nov 15 '22 17:11

Jodrell