2015-03-17 6 views
2

У меня есть запросы на встречу iCalendar, отправляемые правильно через SMTP (используя код ниже), но когда я пытаюсь прикрепить файл, файл не отображается как часть iCalendar. При сохранении .ics после его открытия в Outlook все данные файла были удалены.Присоединение файла к iCalendar

Вот код, я использую:

System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage(); 
msg.From = new System.Net.Mail.MailAddress("[email protected]", "test1"); 
msg.To.Add(new System.Net.Mail.MailAddress("[email protected]", "test2")); 
msg.Subject = "Subject1"; 
msg.Body = "Body line 1\r\nBody line 2\r\nBody line 3"; 

System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType("text/calendar"); 
ct.Parameters.Add("method", "REQUEST"); 
ct.Parameters.Add("name", "meeting.ics"); 

System.Text.StringBuilder sb = new System.Text.StringBuilder(); 
sb.AppendLine("BEGIN:VCALENDAR"); 

sb.AppendLine("PRODID:-/Microsoft Corporation//Outlook 15.0 MIMEDIR//EN"); 
sb.AppendLine("VERSION:2.0"); 
sb.AppendLine("METHOD:REQUEST"); 
sb.AppendLine("X-MS-OLK-FORCEINSPECTOROPEN:TRUE"); 

sb.AppendLine("BEGIN:VEVENT"); 

string file = "D:\\LoadedDate.xlsx"; 
string filename = Path.GetFileName(file); 

sb.Append("ATTACH;ENCODING=BASE64;VALUE=BINARY;X-FILENAME="); 
sb.Append(filename).Append(":").AppendLine(Convert.ToBase64String(File.ReadAllBytes(file), Base64FormattingOptions.InsertLineBreaks)); 

foreach (System.Net.Mail.MailAddress to in msg.To) 
{ 
    sb.AppendLine(String.Format("ATTENDEE;CN=\"{0}\";RSVP=TRUE:mailto:{1}", String.IsNullOrEmpty(to.DisplayName) ? to.Address : to.DisplayName, to.Address)); 
} 
sb.AppendLine("CLASS:PUBLIC"); 
sb.Append("CREATED:").AppendLine(DateTime.Now.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z")); 
sb.Append("DESCRIPTION:").Append(msg.Body.Replace("\r\n", "\\n")).Append("\\n <<").Append(filename).AppendLine(">> \\n"); 

     string dt = DateTime.Now.AddHours(1).ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"); 
     sb.AppendLine("DTSTART:" + dt); 
     sb.AppendLine("DTSTAMP:" + dt); 
     sb.AppendLine("DTEND:" + DateTime.Now.AddHours(5).ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z")); 
     sb.AppendLine("LAST-MODIFIED:"); 
     sb.Append("LOCATION:").AppendLine("Location1"); 
     sb.AppendLine(String.Format("ORGANIZER;CN=\"{0}\":mailto:{0}", msg.From.Address)); 
     sb.AppendLine("PRIORITY:5"); 
     sb.AppendLine("SEQUENCE:0"); 
     sb.Append("SUMMARY;LANGUAGE=en-gb:").AppendLine(msg.Subject); 
     sb.AppendLine("TRANSP:OPAQUE"); 

     // UID should be unique. 
     sb.Append("UID:").AppendLine(Guid.NewGuid().ToString()); 
     sb.Append("X-ALT-DESC;FMTTYPE=text/html:<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\\n"); 
     sb.Append("<HTML>\\n").Append("<HEAD>\\n").Append("<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html\\; charset=iso-8859-1\">\\n").Append("<META NAME=\"Generator\" CONTENT=\"MS Exchange Server version 14.03.0162.000\">\\n"); 
     sb.Append("<TITLE>").Append(msg.Subject).Append("</TITLE>\\n"); 
     sb.Append("</HEAD>\\n").Append("<BODY>\\n").Append("<!--Converted from text/rtf format -->\\n\\n"); 
     sb.Append("<P DIR=LTR><SPAN LANG=\"en-gb\"><FONT FACE=\"Calibri\">").Append(msg.Body.Replace("\r\n", "</FONT></SPAN></P>\\n\\n<P DIR=LTR><SPAN LANG=\"en-gb\"><FONT FACE=\"Calibri\">")).Append("</FONT></SPAN></P>\\n\\n"); 
     sb.Append("<P DIR=LTR><SPAN LANG=\"en-gb\"><FONT FACE=\"Arial\" SIZE=2 COLOR=\"#000000\"> &lt\\;&lt\\;").Append(filename).Append("&gt\\;&gt\\; </FONT></SPAN></P>\\n\\n"); 
     sb.Append("</BODY>\\n").AppendLine("</HTML>"); 

     sb.AppendLine("X-MICROSOFT-CDO-BUSYSTATUS:BUSY"); 
     sb.AppendLine("X-MICROSOFT-CDO-IMPORTANCE:1"); 
     sb.AppendLine("X-MICROSOFT-DISALLOW-COUNTER:FALSE"); 
     sb.AppendLine("X-MS-OLK-AUTOFILLLOCATION:FALSE"); 
     sb.AppendLine("X-MS-OLK-AUTOSTARTCHECK:FALSE"); 
     sb.AppendLine("X-MS-OLK-CONFTYPE:0"); 
     sb.AppendFormat("X-MS-OLK-SENDER;CN=\"{0}\":mailto:{0}", msg.From.Address).AppendLine(); 

     sb.AppendLine("STATUS:TENTATIVE"); 
     sb.AppendLine("BEGIN:VALARM"); 
     sb.AppendLine("TRIGGER:-PT15M"); 
     sb.AppendLine("ACTION:DISPLAY"); 
     sb.AppendLine("DESCRIPTION:Reminder"); 
     sb.AppendLine("END:VALARM"); 
     sb.AppendLine("END:VEVENT"); 

     sb.AppendLine("END:VCALENDAR"); 

     System.Net.Mail.AlternateView av = System.Net.Mail.AlternateView.CreateAlternateViewFromString(sb.ToString(), ct); 

     msg.AlternateViews.Add(av); 

     System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient("mailserver"); 
     client.Send(msg); 

Я имел взгляд на RFC для iCalendars (http://tools.ietf.org/html/rfc5545), и я думаю, что я сделал все согласно тому, что говорит спецификация. Я предполагаю, что есть проблема с тем, как файл читается (бит Convert.ToBase64String), или я что-то пропускаю с альтернативным представлением (я видел, как другие люди добавляли несколько просмотров).

вещи я пытался:

  • Замена Convert.ToBase64String (File.ReadAllBytes (файл), Base64FormattingOptions.InsertLineBreaks) с Convert.ToBase64String (File.ReadAllBytes (файл), Base64FormattingOptions.None).
  • Использование System.Text.Encoding для преобразования файла в BASE64 (без успеха).
  • Присоединение файлов к электронной почте напрямую (с использованием MailMessage.Attachments), но это просто делает сообщение электронной почты в виде обычного письма .

Я также имел взглянуть на проект DDay.iCal на SourceForge (http://sourceforge.net/projects/dday-ical/), но я не мог понять, как это работает, когда дело доходило до прикрепления файла.

Одно требование, которое я имею для этого, заключается в том, что файл должен быть вставлен/прикреплен к электронной почте, к сожалению, я не могу добавить его в URI.

Может ли кто-нибудь помочь?

Обновление: Следуя совету arnaudq, я реализовал обертывание линий с 75 символами, как указано в RFC. В результате MIME сообщение выглядит следующим образом:

BEGIN:VCALENDAR 
PRODID:-//Microsoft Corporation//Outlook 15.0 MIMEDIR//EN 
VERSION:2.0 
METHOD:REQUEST 
X-MS-OLK-FORCEINSPECTOROPEN:TRUE 
BEGIN:VEVENT 
ATTACH;ENCODING=BASE64;VALUE=BINARY;X-FILENAME=test.txt:U0ZMb2dObwlTRkxvYWR 
lZERhdGUNCjkxNzY3NC8xCTI3LzExLzIwMTIgMTg6MzANCjkxMjIwNS8xCTI3LzExLzIwMTIgM 
Tg6MzANCjkxMjI0Ni8xCTI3LzExLzIwMTIgMTg6MzANCjkxMjI1Mi8xCTI3LzExLzIwMTIgMTg 
6MzANCjkxMjQyMS8xCTI3LzExLzIwMTIgMTg6MzANCjkxMjQyMi8xCTI3LzExLzIwMTIgMTg6M 
zANCjkxNTMyMS8xCTI3LzExLzIwMTIgMTg6MzANCjkxNTQzNS8xCTI3LzExLzIwMTIgMTg6MzA 
NCjkxNTU5OS8xCTI3LzExLzIwMTIgMTg6MzANCjkxNjc3NC8xCTI3LzExLzIwMTIgMTg6MzANC 
jkxNjk1OS8xCTI3LzExLzIwMTIgMTg6MzANCjkxNjk2MC8xCTI3LzExLzIwMTIgMTg6MzANCjk 
xNzM2Ny8xCTI3LzExLzIwMTIgMTg6MzANCjkxNzQzNC8xCTI3LzExLzIwMTIgMTg6MzANCjkxN 
DczMS8xCTI3LzExLzIwMTIgMTg6MzANCjkxNDczMi8xCTI3LzExLzIwMTIgMTg6MzANCjkxNDc 
0My8xCTI3LzExLzIwMTIgMTg6MzANCjkxNDc0NC8xCTI3LzExLzIwMTIgMTg6MzANCjkxNDc0N 
S8xCTI3LzExLzIwMTIgMTg6MzANCjkxNDc0Ni8xCTI3LzExLzIwMTIgMTg6MzANCjkxNDc2MS8 
xCTI3LzExLzIwMTIgMTg6MzANCjkxNDc2Mi8xCTI3LzExLzIwMTIgMTg6MzANCjkxNDc2My8xC 
TI3LzExLzIwMTIgMTg6MzANCjkxNTYzNS8xCTI3LzExLzIwMTIgMTg6MzANCjkxNTYzOC8xCTI 
3LzExLzIwMTIgMTg6MzANCjkxNTY0MC8xCTI3LzExLzIwMTIgMTg6MzANCjkxNTY0MS8xCTI3L 
zExLzIwMTIgMTg6MzANCjkxNTY1OS8xCTI3LzExLzIwMTIgMTg6MzANCjkxNTc3Ni8xCTI3LzE 
xLzIwMTIgMTg6MzANCjkxNTc3Ny8xCTI3LzExLzIwMTIgMTg6MzANCjkxNTc3OC8xCTI3LzExL 
zIwMTIgMTg6MzANCg== 
ATTENDEE;CN="Test 1";RSVP=TRUE:mailto:[email protected] 
CLASS:PUBLIC 
CREATED:20150318T095735Z 
DESCRIPTION:Body line 1 
Body line 2 
Body line 3 
<<test.txt>> 
DTSTART:20150318T105735Z 
DTSTAMP:20150318T105735Z 
DTEND:20150318T145735Z 
LAST-MODIFIED: 
LOCATION:Location1 
ORGANIZER;CN="[email protected]":mailto:[email protected] 
PRIORITY:5 
SEQUENCE:0 
SUMMARY;LANGUAGE=en-gb:Subject1 
TRANSP:OPAQUE 
UID:40306717-c29a-42d1-b03e-0240a93c2ea2 
X-ALT-DESC;FMTTYPE=text/html:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//E 
N"><HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html\; charse 
t=iso-8859-1"><META NAME="Generator" CONTENT="MS Exchange Server version 1 
4.03.0162.000"><TITLE>Subject1</TITLE></HEAD><BODY><!--Converted from text 
/rtf format --><P DIR=LTR><SPAN LANG="en-gb"><FONT FACE="Calibri">Body lin 
e 1</FONT></SPAN></P><P DIR=LTR><SPAN LANG="en-gb"><FONT FACE="Calibri"></ 
FONT></SPAN></P>Body line 2</FONT></SPAN></P><P DIR=LTR><SPAN LANG="en-gb" 
><FONT FACE="Calibri"></FONT></SPAN></P>Body line 3<P DIR=LTR><SPAN LANG=" 
en-gb"><FONT FACE="Arial" SIZE=2 COLOR="#000000"> &lt\;&lt\;test.txt&gt\;& 
gt\; </FONT></SPAN></P></BODY></HTML> 
X-MICROSOFT-CDO-BUSYSTATUS:BUSY 
X-MICROSOFT-CDO-IMPORTANCE:1 
X-MICROSOFT-DISALLOW-COUNTER:FALSE 
X-MS-OLK-AUTOFILLLOCATION:FALSE 
X-MS-OLK-AUTOSTARTCHECK:FALSE 
X-MS-OLK-CONFTYPE:0 
STATUS:TENTATIVE 
BEGIN:VALARM 
TRIGGER:-PT15M 
ACTION:DISPLAY 
DESCRIPTION:Reminder 
END:VALARM 
END:VEVENT 
END:VCALENDAR 

К сожалению, это все еще не работает, и файл (в данном случае простой текстовый файл) не приходит через с записью календаря в Outlook.

Что действительно интересно, так это сохранение вышеуказанного сообщения MIME в файл вручную и переименование в .ics, после чего его открытие делает правильно отображенный файл. Это заставляет меня думать, что что-то не так с тем, как я отправляю сообщение, вместо разметки iCalendar.

Любые идеи, что не так?

+0

ли вы найти решение? –

+0

К сожалению, нет. Я сдался в конце и просто отправлю второе письмо с прикрепленными файлами. –

ответ

1

Во-первых, хотя вы используете разрывы строк, похоже, что вы не используете разрывы строк, ожидаемые iCalendar. Короче говоря, каждая строка после первой должна иметь префикс с пробелом, а строки должны иметь длину менее 75 октетов.См https://tools.ietf.org/html/rfc5545#section-3.1

(В общем, для этого типа проблемы-взаимодействия, показывая нам сообщение конечного результата MIME является более полезным, чем код, который был использован для его генерации)

Тогда, насколько я помню, Outlook предпочитает вложения, которые должны передаваться в multipart/related, содержащие поток iCalendar и вложение в разных частях mime. См. Пример https://tools.ietf.org/html/rfc6047#section-4.6.

Наконец, вы можете попробовать отправить приглашение с вложением из Outlook и посмотреть, как структурировано сообщение MIME, которое он отправляет.

+0

Теперь я обновил вопрос - кажется, что обертка зафиксировала сообщение MIME (создание и открытие работы вручную.) Отображается прикрепленный файл), но он по-прежнему теряется при отправке почтового сообщения через Smtp. Я что-то пропустил с помощью AlternateView? –

+0

Ну, это, вероятно, означает, что клиент не любит встроенное свойство icalendar ATTACHMENT. Вы посмотрели RFC6047 или попытались посмотреть, что отправляет Outlook при отправке приглашения с приложением? – arnaudq

+0

Я просмотрел RFC6047, мое встроенное вложение, похоже, соответствует ему правильно, но я не мог понять, как отправить многостраничное электронное письмо с использованием свойства cid через .NET с использованием SMTP. Я попытался сохранить форму .ics form Outlook, а мой - в том же формате (почти достаточно). Если я сохраню свою .ics в файловой системе вместо ее отправки по электронной почте, тогда откройте ее, файл откроется в Outlook со встроенным вложением. Я думаю, что либо способ отправки электронной почты, либо сервера Exchange, либо Outlook на стороне клиента должен удалить удаленный файл, но я не знаю, как узнать, что или почему это происходит. –

2

@paul, я внесла следующие изменения и свою работу для меня. Мне нужно проверить это исправление на всех почтовых клиентах. Я тестировал на MS Outlook 2013, ios, MS Outlook 2010 и отлично работает.

MailMessage msg = new MailMessage(); 
AlternateView alternate = AlternateView.CreateAlternateViewFromString(body, null, "text/html"); 
Stream stream = new MemoryStream(attachment.Bytes);// Bytes of file 
LinkedResource resource = new LinkedResource(stream);                
resource.ContentId = attachment.Name.Replace(".", "") + DateTime.Now.Ticks.ToString(); 
resource.ContentType.Name = attachment.Name;//Name of file    
resource.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;        
alternate.LinkedResources.Add(resource); 
msg.AlternateViews.Add(alternate); 

Я не модифицируя .ics файл, чтобы добавить ATTACH свойство (ATTACH; Encoding = BASE64; VALUE = BINARY, X-FILENAME =)

2
String iCall = CreateICal(); 


      System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType("text/calendar"); 
      ct.Parameters.Add("charset", @"utf-8"); 
      ct.Parameters.Add("method", "REQUEST"); 
      AlternateView avCal = AlternateView.CreateAlternateViewFromString(iCall, ct); 



      System.Net.Mime.ContentType cthtml = new System.Net.Mime.ContentType("text/html"); 
      cthtml.Parameters.Add("charset", @"utf-8"); 
      AlternateView avHtml = AlternateView.CreateAlternateViewFromString(this.mHTML, cthtml); 

      mail.AlternateViews.Add(avHtml); 
      mail.AlternateViews.Add(avCal); 


      foreach (LinkedResource resource in arrattach) 
      { 
       avHtml.LinkedResources.Add(resource); 
      } 

      client.Send(mail); 

 Смежные вопросы

  • Нет связанных вопросов^_^