1

I am writing a system to send out bulk emails to clients and for each site we store an HTML and Text version of the email so that if the users mail client doesn't support HTML the text view is still formatted correctly and as we want.

We don't want to just generate the plain text version from the HTML version as it adds in lots of menu links and other text which isn't formatted as we want.

This works fine in ASP classic with the Persits Email Component = http://www.aspemail.com/ as we add the HTML string as the Body and the text string as the AltBody.

However I am having trouble replicating this in C# .NET 4.5

I have followed as many examples as possible but my method that returns the MailMessage object which needs to pass the HTML looking for images/banners and then replace the URLS with ContentIDs and LinkedResources is somehow returning an email that looks great in HTML and Simple HTML View (in Thunderbird).

However whatever I do the plain text view seems to always be a version of the HTML that the object is trying to convert into text RATHER than the textual string we have pre-formatted and want to use.

If I debug the code I can see that the string is correct before I add it to the alternative view so I don't know what else I need to do.

In my method that parses the HTML, adds linked resources and returns a MailMessage object I have the following code:

<pre>
/* I pass in a custom SiteEmail object with 2 properties HTMLEmail and TextEmail that hold both versions of the email */
public MailMessage ParseEmailImages(SiteEmail siteEmail)
{
    MailMessage email = new MailMessage();

    // extract the HTML version as we need to parse it to swap URLs for ContentID/Resources and paths etc
    string HTML = siteEmail.HTMLEmail;

    // this is a generic list to hold all my picture resource objects that I find (swapping image URLs to paths and contentIDs)
    List<LinkedResource> pictureResources = new List<LinkedResource>(); 


    // code to find all the paths, create image resource objects and add them to my list - and modify the HTML to reference
    // the new ContentIDs I swap the URLs for so the images are embedded in the email
    // ..... code .....

    // finished finding resource objects build email parts and return to caller

    // Add each alternate view to the message.

    // add the HTML view using my newly parsed HTML string
    ContentType HtmlContentType = new ContentType("text/html; charset=UTF-8");
    AlternateView altViewHTML = AlternateView.CreateAlternateViewFromString(HTML, HtmlContentType);
    altViewHTML.TransferEncoding = TransferEncoding.QuotedPrintable;

    // when I check here the siteEmail.TextEmail holds the CORRECT textual string I want BUT it's not displaying in the sent email

    ContentType PlainContentType = new ContentType("text/plain; charset=UTF-8");

    // as we didn't need to change anything in the text view we can just reference it straight out my custom email object siteEmail
    AlternateView altViewText = AlternateView.CreateAlternateViewFromString(siteEmail.TextEmail, PlainContentType);
    altViewText.TransferEncoding = TransferEncoding.QuotedPrintable;

    // loop through all my picture resource objects and ensure they are embedded into the HTML email
    foreach (LinkedResource pictureResource in pictureResources)
    {
        pictureResource.TransferEncoding = TransferEncoding.Base64;
        altViewHTML.LinkedResources.Add(pictureResource);
    }



    // add both parts of the email (text/html) which are both alternative views to message
    email.AlternateViews.Add(altViewText);
    email.AlternateViews.Add(altViewHTML);



    // return email object
    return email;
}


// a very cut down example of the calling method
public bool SendEmail()
{
    // parse our email object
    MailMessage EmailMailMessage = this.ParseEmailImages(this.SiteEmail);

    // send email
    EmailMailMessage.From = new MailAddress(this.SendFromEmail, this.SendFromName);

    EmailMailMessage.Subject = this.SendSubject;

    // ensure encoding is correct for Arabic/Japanese sites and body transfer method is correct
    EmailMailMessage.BodyEncoding = Encoding.UTF8;
        EmailMailMessage.BodyTransferEncoding = TransferEncoding.QuotedPrintable;

        SmtpClient client = new SmtpClient();

    // this in a try catch and more complex
    client.Send(this.EmailMailMessage);

}
</pre>

I have tried playing about with the encoding formats, just adding one alternative view and so on but cannot seem to get it to send out the same email as my old ASP Classic code e.g a multipart email with 2 boundaries, 1 for the text version WE WANT TO USE and one with the HTML version. It always seems to create it's own Plain Text version from the HTML version which I don't want to happen.

Any help or ideas would be much appreciated.

Thanks in advance for any help!

user2334626
  • 197
  • 1
  • 1
  • 12
  • Why are both the HTML view and the simple text view alternative views? – Maciej Jun 17 '13 at 15:51
  • Well I am just going off tutorials I have seen online as no-one here knows what they are doing. I thought you would have to create two parts for the email, one HTML, one Text then add them to the multipart email with boundaries. If there is something I am missing then please let me know what I should be doing in regards to taking a view out so I can get both the HTML I want AND the text view I want. – user2334626 Jun 18 '13 at 11:35
  • Can you try switching the two lines where you add your alternative views? Add the HTML one first. – Maciej Jun 18 '13 at 13:27
  • Plus if I remove the HTML alternative view what object do I add all my picture resource objects to? The MailMessage object email won't accept them and I shouldn't be adding them to the text alternative view object. So I need a solution that will allow me to replace the images with picture resources and have two views (text as I want it to appear and my reformatted HTML) – user2334626 Jun 18 '13 at 13:27
  • you are right, you need the alternative view to add your images – Maciej Jun 18 '13 at 13:30
  • Have you tried to read your email using multiple email clients? – Maciej Jun 18 '13 at 13:37
  • I will try that now but we have a specific textual string we want to add and use as the alternative view. So I don't understand why it is not taking that text for the alternative view and making it's own version up from the HTML? If I debug the code I can see that my textual string is being added to this line of code == AlternateView altViewText = AlternateView.CreateAlternateViewFromString(siteEmail.TextEmail, PlainContentType); So I don't know why its not taking my textual value into that objects method and using it for that alternative view – user2334626 Jun 18 '13 at 14:16
  • I have tried viewing it in Hotmail and Gmail (hotmails new Outlook does the same thing - shows its own version of the text) and Gmail does an inbetween version (simple HTML in Thunderbird) - also if I view the source code in Gmail I can see that the text version (text alternative view) is the exact text I am putting in so I don't know why its ignoring it - I will show you some of the source in the next comment as I am running out of characters! – user2334626 Jun 18 '13 at 14:31
  • To: "Robert Reid" Date: 18 Jun 2013 15:27:05 +0100 Subject: My Subject for 18-06-2013 Content-Type: multipart/alternative; boundary=--boundary_0_69b1ab1e-1eba-439a-bd78-73c8a9e73c5a ----boundary_0_69b1ab1e-1eba-439a-bd78-73c8a9e73c5a Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Jobs By Email=0D=0A=0D=0ADear Jobseeker=0D=0AWelcome to the lates= t edition of your personalised Jobs By Email search results.=0D=0A= =0D=0APlease find below 10 vacancy(ies) fitting your search terms= .=0D=0A=0D=0APLEASE NOTE: A maximum of 10 – user2334626 Jun 18 '13 at 14:32
  • as you can see it is using quoted printable encoding, and there are no links at the top of the plain text version - however viewing the plain text version in Thunderbird I get a converted version of my HTML view which means a whole load of links (menu links converted into simple text links) - which as you can see from the source of the text view are not present at all. This is why we do our own formatting for the text view to make it look nice in simple text mode as well as styled nicely for HTML viewers. All I do know is the ASP Classic Email COM object worked with both views. – user2334626 Jun 18 '13 at 14:35
  • what if you remove the HTML view altogether? what happens? – Maciej Jun 18 '13 at 15:01
  • if I do that, how do I attach all the banners/images as embedded images with contentID's as linked resources? Also how does the MailMessage know to use the HTML string (after reformatting, with all src="http://blah/img.gif" replaced with src="ContentId:RandomNo" and then the image files encoded and attached (to what?) – user2334626 Jun 18 '13 at 15:26
  • the image files are embedded (probably as bytes) in the email. I wanted to know what the email looks like in an email client if you simply include the plain text version (no images, etc.). – Maciej Jun 18 '13 at 15:35
  • perhaps this will help? http://idevelopdotnet.wordpress.com/2009/03/04/content-transfer-encoding-systemnetmailmailmessage/ – Maciej Jun 18 '13 at 15:40
  • Yes if I just include the text version with no images and no alternative view for the HTML - so I am just adding an alternative view for the text THEN I get the correct TEXT email through to my client (no HTML version - but a correct textual version) – user2334626 Jun 18 '13 at 15:53
  • that article doesn't help - a) I'm not getting garbage characters and b) changing .IsBodyHtml=false; .Body=null; and the encoding to SevenBit from QuotedPrintable doesn't do anything different - I still get the HTML version as it should be and then the mail client (or object) is making up its own text version (even though its correct in the source of the email) and ignoring the string I pass in for it. GRRR! – user2334626 Jun 18 '13 at 16:38
  • frustrating. Do you have a complete sample? – Maciej Jun 18 '13 at 16:57
  • yes but it wont fit in this little box! I can email it to you if you want? – user2334626 Jun 18 '13 at 17:13
  • Check it out here on dropbox - the HelperLib class is static and just for logging (as we are going to be doing big batch processes) - the class is just called , the CreateAndSendEmail method called which parses the images and then sends the email. Remember I need to convert image URLs into full paths on the server and change the src attributes into ContentID which is what all the RegEx does >> https://www.dropbox.com/s/kcfcpe0gux9507c/myemailclass.txt – user2334626 Jun 18 '13 at 17:20
  • Did you have a chance to look at the example code? Anyone? Any help would be much appreciated on this. – user2334626 Jun 20 '13 at 09:53
  • By the way I have found out that if I remove the code that converts src=absolute URLS to images into linked resources and then attaches those to the HTML alternative view then the code works fine. I can see both the HTML view and Text View I provide. The "Show Remote Content" button has to be pressed in the mail client to show the images as they are obviously still stored on the server but this seems to be the only way I can get it to work. Seems like a bug to me! – user2334626 Jun 25 '13 at 12:41

1 Answers1

2

The answer seems to be that there is a bug in the MailMessage class. I have been told to report this as such on the Microsoft .NET forum.

It seems that the issue lies in the use of LinkedResources.

If I remove the code that adds the LinkedResources to the HTML alternative view then the code works fine and I can see both my Plain Text and HTML views in my mail client.

Therefore I have to leave the images as externally linked resources that are loaded into the email when the user presses any "load remote content" button in their email client.

user2334626
  • 197
  • 1
  • 1
  • 12