iCalendar の会議出席依頼を SMTP 経由で (以下のコードを使用して) 正しく送信していますが、ファイルを添付しようとすると、ファイルが iCalendar の一部として表示されません。Outlook で開いた後に .ics を保存すると、ファイル データ全体が取り除かれます。
私が使用しているコードは次のとおりです。
System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage();
msg.From = new System.Net.Mail.MailAddress("test1@test.com", "test1");
msg.To.Add(new System.Net.Mail.MailAddress("test2@test.com", "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\"> <\\;<\\;").Append(filename).Append(">\\;>\\; </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);
iCalendars の RFC ( https://www.rfc-editor.org/rfc/rfc5545 ) を確認しましたが、仕様に従ってすべてのことを行ったと思います。ファイルの読み込み方法 (Convert.ToBase64String ビット) に問題があるか、代替ビューに何かが欠けている (他の人が複数のビューを追加しているのを見たことがあります) と推測しています。
私が試したこと:
- Convert.ToBase64String(File.ReadAllBytes(file), Base64FormattingOptions.InsertLineBreaks) を Convert.ToBase64String(File.ReadAllBytes(file), Base64FormattingOptions.None) に置き換えます。
- System.Text.Encoding を使用してファイルを BASE64 に変換します (成功しません)。
- (MailMessage.Attachments を使用して) ファイルを電子メールに直接添付しますが、それは電子メールを通常の電子メールとして表示するだけです。
sourceforge の DDay.iCal プロジェクト ( http://sourceforge.net/projects/dday-ical/ ) も調べましたが、ファイルを添付するときにどのように機能するかわかりませんでした。
このための要件の 1 つは、ファイルをメールに埋め込む/添付する必要があることです。残念ながら、URI として追加することはできません。
誰でも助けることができますか?
更新: arnaudq のアドバイスに従って、RFC に記載されているように、行を 75 文字でラップするように実装しました。結果の 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:test1@test.com
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="test2@test.com":mailto:test2@test.com
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"> <\;<\;test.txt>\;&
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 マークアップではなく、メッセージの送信方法に問題があると思わせます。
何が間違っているのですか?