Email from .net with Calendar Invite and File Attachment not Rendering on Outlook

PapaMac 1 Reputation point
2022-04-08T11:35:12.277+00:00

I'm trying to send an email using MailMessage on .net framework that has an HTML body, a Calendar Invite, and a File attachment.

I send it to our office365 corporate email and gmail for testing. It renders correctly on gmail, but not on office365. If I send it with only the calendar invite (no file attachment) it works fine on both email providers. But when I send it with an another file attachment the calendar invite doesn't render on out look anymore, but the attachment and .ics file is in there.

I've read that you should be putting your email body, and calendar invite on their own different AlternateView.

Am I missing something here?

Gmail
191308-gmail.png

Outlook
191315-outlook.png

Here's my code:

static void Main(string[] args)  
    {  
        string _from = "emailsender";  
        string _subj = "TEST EMAIL " + DateTime.Now.ToString("G");  
        string _body = "Hi Mark,<br/><br/>THIS IS A TEST EMAIL<br/><br/>WITH A Calendar Invite and File Attachment<br/><br/>Regards<br/>TESTER";  
        _body = CheckWellFormedHtml(_body);  
  
        MailMessage msg = new MailMessage();  
        msg.From = new MailAddress(_from);  
        msg.To.Add("email1");  
        msg.To.Add("email2");  
        msg.Subject = _subj;  
  
        AlternateView avBody = AlternateView.CreateAlternateViewFromString(_body, Encoding.UTF8, MediaTypeNames.Text.Html);  
        msg.AlternateViews.Add(avBody);  
  
  
        // Generate Calendar Invite ---------------------------------------------------  
        StringBuilder str = new StringBuilder();  
        str.AppendLine("BEGIN:VCALENDAR");  
        str.AppendLine("PRODID:-//Schedule a Meeting");  
        str.AppendLine("VERSION:2.0");  
        str.AppendLine("METHOD:REQUEST");  
        str.AppendLine("BEGIN:VEVENT");  
        str.AppendLine(string.Format("DTSTART:{0:yyyyMMddTHHmmssZ}", DateTime.Now.AddMinutes(+330)));  
        str.AppendLine(string.Format("DTSTAMP:{0:yyyyMMddTHHmmssZ}", DateTime.UtcNow));  
        str.AppendLine(string.Format("DTEND:{0:yyyyMMddTHHmmssZ}", DateTime.Now.AddMinutes(+660)));  
        str.AppendLine("LOCATION: " + "abcd");  
        str.AppendLine(string.Format("UID:{0}", Guid.NewGuid()));  
        str.AppendLine(string.Format("DESCRIPTION:{0}", msg.Body));  
        str.AppendLine(string.Format("X-ALT-DESC;FMTTYPE=text/html:{0}", msg.Body));  
        str.AppendLine(string.Format("SUMMARY:{0}", msg.Subject));  
        str.AppendLine(string.Format("ORGANIZER:MAILTO:{0}", msg.From.Address));  
  
        str.AppendLine(string.Format("ATTENDEE;CN=\"{0}\";RSVP=TRUE:mailto:{1}", msg.To[0].DisplayName, msg.To[0].Address));  
  
        str.AppendLine("BEGIN:VALARM");  
        str.AppendLine("TRIGGER:-PT15M");  
        str.AppendLine("ACTION:DISPLAY");  
        str.AppendLine("DESCRIPTION:Reminder");  
        str.AppendLine("END:VALARM");  
        str.AppendLine("END:VEVENT");  
        str.AppendLine("END:VCALENDAR");  
  
  
        // Attach Calendar Invite ------------------------------------------------------  
        byte[] byteArray = Encoding.ASCII.GetBytes(str.ToString());  
        MemoryStream stream = new MemoryStream(byteArray);  
  
        Attachment attach = new Attachment(stream, "invite.ics");  
        attach.TransferEncoding = TransferEncoding.QuotedPrintable;  
        msg.Attachments.Add(attach);  
  
        ContentType contype = new ContentType("text/calendar");  
        contype.CharSet = "UTF-8";  
        contype.Parameters.Add("method", "REQUEST");  
        contype.Parameters.Add("name", "invite.ics");              
  
        AlternateView avCal = AlternateView.CreateAlternateViewFromString(str.ToString(), contype);  
        avCal.TransferEncoding = TransferEncoding.QuotedPrintable;  
        msg.AlternateViews.Add(avCal);  
  
  
        // File Attachment --------------------------------------------------------------  
        string filePath = @"C:\TESTFile.txt";  
        string fileName = Path.GetFileName(filePath);  
        byte[] bytes = File.ReadAllBytes(filePath);  
        msg.Attachments.Add(new Attachment(new MemoryStream(bytes), fileName));  
  
  
        //Now sending a mail with attachment ICS file. ----------------------------------  
        SmtpClient smtpclient = new SmtpClient();  
        smtpclient.Host = "smtp.gmail.com"; //-------this has to given the Mailserver IP  
        smtpclient.EnableSsl = true;  
        smtpclient.Port = 587;  
        smtpclient.Credentials = new System.Net.NetworkCredential(_from, "*****");  
        smtpclient.Send(msg);  
        Console.WriteLine("Email Sent");  
        Console.ReadLine();  
    }  
  
    public static string CheckWellFormedHtml(string txt)  
    {  
        if (txt == null)  
            return "";  
        else  
        {  
            StringBuilder htmlTop = new StringBuilder();  
            StringBuilder htmlBottom = new StringBuilder();  
  
            if (!txt.ToUpper().Contains("<!DOCTYPE"))  
            {  
                // If the txt already contains a doc type then we assume that the rest of the html is valid  
  
                htmlTop.Append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" ");  
                htmlTop.Append("\"http://www.w3.org/TR/html4/loose.dtd\">");  
                // Html at the top of the email  
                if (!txt.ToUpper().Contains("<HTML>") & !txt.ToUpper().Contains("< HTML>") & !txt.ToUpper().Contains("<HTML >") & !txt.ToUpper().Contains("< HTML >"))  
                    htmlTop.Append("<html>");  
                if (!txt.ToUpper().Contains("<HEAD>") & !txt.ToUpper().Contains("< HEAD>") & !txt.ToUpper().Contains("<HEAD >") & !txt.ToUpper().Contains("< HEAD >"))  
                    htmlTop.Append("<head>");  
                if (!txt.ToUpper().Contains("<TITLE>") & !txt.ToUpper().Contains("< TITLE>") & !txt.ToUpper().Contains("<TITLE >") & !txt.ToUpper().Contains("< TITLE >"))  
                    htmlTop.Append("<title>Untitled Document</title>");  
                if (!txt.ToUpper().Contains("</HEAD>") & !txt.ToUpper().Contains("</ HEAD>") & !txt.ToUpper().Contains("</HEAD >") & !txt.ToUpper().Contains("</ HEAD >"))  
                    htmlTop.Append("</head>");  
                if (!txt.ToUpper().Contains("<BODY>") & !txt.ToUpper().Contains("< BODY>") & !txt.ToUpper().Contains("<BODY >") & !txt.ToUpper().Contains("< BODY >"))  
                    htmlTop.Append("<body>");  
  
                // Html at the bottom of the email  
                if (!txt.ToUpper().Contains("</BODY>") & !txt.ToUpper().Contains("</ BODY>") & !txt.ToUpper().Contains("</BODY >") & !txt.ToUpper().Contains("</ BODY >"))  
                    htmlBottom.Append("</body>");  
                if (!txt.ToUpper().Contains("</HTML>") & !txt.ToUpper().Contains("</ HTML>") & !txt.ToUpper().Contains("</HTML >") & !txt.ToUpper().Contains("</ HTML >"))  
                    htmlBottom.Append("</html>");  
  
                txt = htmlTop.ToString() + txt + htmlBottom.ToString();  
            }  
  
            return txt;  
        }  
    }  
ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,250 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Lan Huang-MSFT 25,471 Reputation points Microsoft Vendor
    2022-04-11T07:40:01.437+00:00

    Hi @PapaMac ,
    The root cause of this problem is: When your email contain attachments, MailMessage will generate message like this:

    multipart/mixed  
      multipart/alternative  
        text/plain  
        text/calendar;method=REQUEST  
      multipart/mixed  
        content-type (with a content-disposition:attachment)  
    

    But Outlook365 expect the message to be:

    multipart/mixed  
      multipart/alternative  
        text/plain  
        text/calendar;method=REQUEST  
      content-type (with a content-disposition:attachment)  
    

    When Outlook receive wrong attachment format. Some how, It'll ignore the calendar part.
    I think you can use MailKit instead of System.Net.Mail to send emails. By using this library, the message format can be controlled.
    Best regards,
    Lan Huang


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.
    0 comments No comments