Mark
Mark

Reputation: 1

Email with Calendar Invite and File Attachment not Rendering on Outlook

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 outlook

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;
        }
    }

Upvotes: 0

Views: 959

Answers (1)

Dmitry Streblechenko
Dmitry Streblechenko

Reputation: 66255

Make sure attachments are not in a separate MIME part, but rather a part of VCALENDAR. Make sure you specify BINARY attribute (they default to URI).

ATTACH;ENCODING=BASE64;VALUE=BINARY;X-FILENAME="TestFileName.txt"
    :RnJvbToJVGVzdCBBY2NvdW50IDx0ZXN0QGRpbWFzdHIuY29tPg0KVG86CWRtaXRyeUBkaW1hc
    ...

Upvotes: 0

Related Questions