我只是想知道是否有可能在没有在服务器上安装Outlook并使用COM Interop(我想在服务器上不惜一切代价避免)的情况下向人们发送会议请求.
我们在Windows 2003域中安装了Exchange 2003,并且所有用户都是域用户.我想我可以发送'回合iCal/vCal或其他东西,但我想知道是否有一种适当的标准方式通过Exchange发送会议请求而没有Outlook?
如果重要的话,这是C#/ .net.
向Outlook发送会议请求(并将其识别)的方式如下:
准备一个iCalendar文件,请务必设置这些附加属性,因为Outlook需要它们:
UID
SEQUENCE
CREATED
LAST-MODIFIED
DTSTAMP
准备multipart/alternative
邮件:
第1部分:( text/html
或任何你喜欢的) - 它显示给"普通"邮件阅读器或作为后备,并包含人类可读形式的事件摘要
第2部分:text/calendar; method=REQUEST
保存ics文件的内容(header method
参数必须与ics中的方法匹配).注意正确的文本编码,声明charset
头参数不会受到伤害.
第3部分:(可选)附加.ics文件本身,以便普通邮件阅读器可以为用户提供点击的内容.Outlook并不真正需要附件,因为它只是读取text/calendar
部分.
将邮件发送给Outlook用户.如果你把一切都搞定了,那么邮件就会显示为会议请求,并在接受时完成考勤按钮和用户日历中的自动输入.
设置处理响应的内容(它们会转到会议组织者).我还无法让自动与会者跟踪与Exchange邮箱一起使用,因为该事件在组织者日历中不存在.Outlook需要UID和SEQUENCES来满足它的期望,但是使用UID你可以解决这个问题.
有关ics文件格式的详细信息和特性的帮助,请务必访问Masahide Kanzaki的iCalendar规范摘录.它们是黑暗中的光,比通过RFC 2445啃你的方式要好得多.但话说回来,也许.NET存在一个方便的库.
请参阅sourceforge上的DDay.iCal C#库:http:
//sourceforge.net/projects/dday-ical/
然后阅读此代码项目文章:http:
//www.codeproject.com/Articles/17980/Adding-iCalendar-Support-to-Your-Program-Part-1
并阅读:
使用C#导出事件到iCalendar和vCalendar格式
iCalendar是一个很棒的通用解决方案,DDay.iCal库是从.NET完成此任务的好方法,但我相信Exchange Web Services(EWS)在原始问题的上下文中是更好的解决方案(Exchange,C# /.净).
如果您使用的是.NET语言(如C#),则应使用EWS Managed API包装器,这极大地简化了使用EWS的过程.
从文档中,以下是如何使用EWS托管API创建会议并将请求发送给被邀请者:
// Create the appointment. Appointment appointment = new Appointment(service); // Set properties on the appointment. Add two required attendees and one optional attendee. appointment.Subject = "Status Meeting"; appointment.Body = "The purpose of this meeting is to discuss status."; appointment.Start = new DateTime(2009, 3, 1, 9, 0, 0); appointment.End = appointment.Start.AddHours(2); appointment.Location = "Conf Room"; appointment.RequiredAttendees.Add("user1@contoso.com"); appointment.RequiredAttendees.Add("user2@contoso.com"); appointment.OptionalAttendees.Add("user3@contoso.com"); // Send the meeting request to all attendees and save a copy in the Sent Items folder. appointment.Save(SendInvitationsMode.SendToAllAndSaveCopy);
您可以使用iCal标准(RFC 5545)通过邮件将会议请求发送到Outlook。
您无法通过这种方式发送待办事项。您可以发送“约会”,但这些约会在Outlook中显示为.ics附件,必须“盲目”接受。
会议请求会以很好的预览显示在Outlook中,可以接受或拒绝。发送程序可以在会议发送后修改或取消会议。
使用DDay.iCal .Net库创建有效的iCal项很容易
下面的代码是一个完整的工作示例。它使用有效的iCal会议请求构建一个字符串,然后通过邮件发送它。
该代码创建具有以下内容的邮件:
用于简单邮件客户端的纯文本正文
用于现代邮件客户端中的diplay的HTML正文
iCal会议请求为AlternateView(将在Outlook中显示)
iCal会议请求作为附件(可用于Outlook以外的邮件客户端)
该代码显示了如何添加:
描述文字为HTML,在Outlook中看起来更好
优先级,可见性(公共/私有/机密)
可选的管理器(将显示在Outlook中,而不是邮件发件人中)
可选参加者
可选警报
会议的可选附件。将显示在Outlook的日历中
一些重要的细节:
邮件发件人(或可选的组织者)和邮件收件人必须不同,才能在Outlook中工作
.ics中的METHOD和Mime.ContentType中的METHOD必须匹配
会议必须在未来进行,以使这项工作在展望中得以实现
.ics部分必须是MIME邮件中的最后一个alterView部分
有关Outlook解释.ics文件的方式的详细信息,请参见[MS-OXCICAL]:iCalendar到约会对象转换算法
我们将使用以下程序集:
using System; using System.IO; using System.Net.Mail; using DDay.iCal; using DDay.iCal.Serialization.iCalendar;
对于DDay.iCal,足以下载DDay.iCal二进制文件。如果要添加某些功能,最好查看DDay.iCal源,因为文档已过时,并且源包含相当完整的测试,可以执行其所有功能。
const string filepath = @"C:\temp\ical.test.ics"; // use PUBLISH for appointments // use REQUEST for meeting requests const string METHOD = "REQUEST"; // Properties of the meeting request // keep guid in sending program to modify or cancel the request later Guid uid = Guid.Parse("2B127C67-73B3-43C5-A804-5666C2CA23C9"); string VisBetreff = "This is the subject of the meeting request"; string TerminVerantwortlicherEmail = "mr.asker@myorg.com"; string bodyPlainText = "This is the simple iCal plain text msg"; string bodyHtml = "This is the simple iCal HTML message"; string location = "Meeting room 101"; // 1: High // 5: Normal // 9: low int priority = 1; //===================================== MailMessage message = new MailMessage(); message.From = new MailAddress("sender@myorg.com"); message.To.Add(new MailAddress(TerminVerantwortlicherEmail)); message.Subject = "[VIS-Termin] " + VisBetreff; // Plain Text Version message.Body = bodyPlainText; // HTML Version string htmlBody = bodyHtml; AlternateView HTMLV = AlternateView.CreateAlternateViewFromString(htmlBody, new System.Net.Mime.ContentType("text/html")); // iCal IICalendar iCal = new iCalendar(); iCal.Method = METHOD; iCal.ProductID = "My Metting Product"; // Create an event and attach it to the iCalendar. Event evt = iCal.Create(); evt.UID = uid.ToString(); evt.Class = "PUBLIC"; // Needed by Outlook evt.Created = new iCalDateTime(DateTime.Now); evt.DTStamp = new iCalDateTime(DateTime.Now); evt.Transparency = TransparencyType.Transparent; // Set the event start / end times evt.Start = new iCalDateTime(2014, 10, 3, 8, 0, 0); evt.End = new iCalDateTime(2014, 10, 3, 8, 15, 0); evt.Location = location; //var organizer = new Organizer("the.organizer@myCompany.com"); //evt.Organizer = organizer; // Set the longer description of the event, plain text evt.Description = bodyPlainText; // Event description HTML text // X-ALT-DESC;FMTTYPE=text/html var prop = new CalendarProperty("X-ALT-DESC"); prop.AddParameter("FMTTYPE", "text/html"); prop.AddValue(bodyHtml); evt.AddProperty(prop); // Set the one-line summary of the event evt.Summary = VisBetreff; evt.Priority = priority; //--- attendes are optional IAttendee at = new Attendee("mailto:Peter.Black@MyOrg.com"); at.ParticipationStatus = "NEEDS-ACTION"; at.RSVP = true; at.Role = "REQ-PARTICIPANT"; evt.Attendees.Add(at); // Let’s also add an alarm on this event so we can be reminded of it later. Alarm alarm = new Alarm(); // Display the alarm somewhere on the screen. alarm.Action = AlarmAction.Display; // This is the text that will be displayed for the alarm. alarm.Summary = "Upcoming meeting: " + VisBetreff; // The alarm is set to occur 30 minutes before the event alarm.Trigger = new Trigger(TimeSpan.FromMinutes(-30)); //--- Attachments string filename = "Test.docx"; // Add an attachment to this event IAttachment attachment = new DDay.iCal.Attachment(); attachment.Data = ReadBinary(@"C:\temp\Test.docx"); attachment.Parameters.Add("X-FILENAME", filename); evt.Attachments.Add(attachment); iCalendarSerializer serializer = new iCalendarSerializer(); serializer.Serialize(iCal, filepath); // the .ics File as a string string iCalStr = serializer.SerializeToString(iCal); // .ics as AlternateView (used by Outlook) // text/calendar part: method=REQUEST System.Net.Mime.ContentType calendarType = new System.Net.Mime.ContentType("text/calendar"); calendarType.Parameters.Add("method", METHOD); AlternateView ICSview = AlternateView.CreateAlternateViewFromString(iCalStr, calendarType); // Compose message.AlternateViews.Add(HTMLV); message.AlternateViews.Add(ICSview); // must be the last part // .ics as Attachment (used by mail clients other than Outlook) Byte[] bytes = System.Text.Encoding.ASCII.GetBytes(iCalStr); var ms = new System.IO.MemoryStream(bytes); var a = new System.Net.Mail.Attachment(ms, "VIS-Termin.ics", "text/calendar"); message.Attachments.Add(a); // Send Mail SmtpClient client = new SmtpClient(); client.Send(message);
这里是ReadBinary()函数:
private static byte[] ReadBinary(string fileName) { byte[] binaryData = null; using (FileStream reader = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { binaryData = new byte[reader.Length]; reader.Read(binaryData, 0, (int)reader.Length); } return binaryData; }
像这样在配置文件中配置SmtpClient最简单:
... ...