C# 在没有 Outlook 的情况下发送 Outlook 会议请求?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/461889/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sending Outlook meeting requests without Outlook?
提问by Michael Stum
I just wonder if it is possible to send Meeting Requests to people without having Outlook installed on the Server and using COM Interop (which I want to avoid on a server at all costs).
我只是想知道是否可以在没有在服务器上安装 Outlook 并使用 COM Interop(我想不惜一切代价避免在服务器上)的情况下向人们发送会议请求。
We have Exchange 2003 in a Windows 2003 Domain and all users are domain Users. I guess I can send 'round iCal/vCal or something, but I wonder if there is a proper standard way to send Meeting Requests through Exchange without Outlook?
我们在 Windows 2003 域中有 Exchange 2003,所有用户都是域用户。我想我可以发送“round iCal/vCal”或其他内容,但我想知道是否有一种适当的标准方法可以在没有 Outlook 的情况下通过 Exchange 发送会议请求?
This is C#/.net if it matters.
如果重要的话,这是 C#/.net。
采纳答案by Tomalak
The way to send a meeting request to Outlook (and have it recognized) goes like this:
向 Outlook 发送会议请求(并使其被识别)的方式如下:
- prepare an iCalendar file, be sure to set these additional properties, as Outlook needs them:
- prepare a
multipart/alternative
mail:- Part 1:
text/html
(or whatever you like) - this is displayed to "ordinary" mail readers or as a fall-back and contains a summary of the event in human readable form - Part 2:
text/calendar; method=REQUEST
, holds the contents of the ics file (the headermethod
parameter must match the method in the ics). Watch out for the correct text encoding, declaring acharset
header parameter won't hurt. - Part 3: Optionally, attach the .ics file itself, so ordinary mail readers can offer the user something to click on. Outlook does not really require the attachment because it just reads the
text/calendar
part.
- Part 1:
- Send the mail to an outlook user. If you got everything right the mail shows up as a meeting request, complete with attendance buttons and automatic entry in the users calendar upon accept.
- Set up something that processes the responses (they go to the meeting organizer). I have not yet been able to get automatic attendee tracking to work with an Exchange mailbox because the event won't exist in the organizers calendar. Outlook needs the UIDs and SEQUENCES to match it's expectations, but with a UID you made up this will hardly work.
- 准备一个 iCalendar 文件,确保设置这些附加属性,因为 Outlook 需要它们:
- 准备
multipart/alternative
邮件:- 第 1 部分:(
text/html
或您喜欢的任何内容)- 这将显示给“普通”邮件阅读器或作为后备,并包含人类可读形式的事件摘要 - 第 2 部分:
text/calendar; method=REQUEST
, 保存 ics 文件的内容(headermethod
参数必须与 ics 中的方法匹配)。注意正确的文本编码,声明charset
标题参数不会有什么坏处。 - 第 3 部分:(可选)附加 .ics 文件本身,这样普通的邮件阅读器就可以为用户提供一些可以点击的东西。Outlook 并不真正需要附件,因为它只是读取
text/calendar
部分。
- 第 1 部分:(
- 将邮件发送给 Outlook 用户。如果一切顺利,邮件将显示为会议请求,并带有出席按钮,并在接受后自动进入用户日历。
- 设置一些处理响应的东西(他们去会议组织者)。我还没有能够使用 Exchange 邮箱进行自动与会者跟踪,因为组织者日历中不存在该活动。Outlook 需要 UIDs 和 SEQUENCES 来匹配它的期望,但是使用您编造的 UID 这几乎不起作用。
For help on the details and peculiarities of the ics file format, be sure to visit the iCalendar Specification Excerpts by Masahide Kanzaki. They are a light in the dark, much better than gnawing your way through RFC 2445. But then again, maybe a handy library exists for .NET.
有关 ics 文件格式的详细信息和特性的帮助,请务必访问Masahide Kanzaki的iCalendar 规范摘录。它们是黑暗中的一盏灯,比通过RFC 2445啃你的方式要好得多。但话又说回来,也许 .NET 存在一个方便的库。
回答by Stefan Steiger
See the DDay.iCal C# library on sourceforge:
http://sourceforge.net/projects/dday-ical/
请参阅 sourceforge 上的 DDay.iCal C# 库:http:
//sourceforge.net/projects/dday-ical/
Then read this codeproject article:
http://www.codeproject.com/Articles/17980/Adding-iCalendar-Support-to-Your-Program-Part-1
然后阅读这篇代码项目文章:http:
//www.codeproject.com/Articles/17980/Adding-iCalendar-Support-to-Your-Program-Part-1
And read this:
Export event with C# to iCalendar and vCalendar format
回答by saille
The code below will send a meeting request in such a way that Outlook will render Accept/Decline buttons.
下面的代码将以 Outlook 呈现接受/拒绝按钮的方式发送会议请求。
Note that UID must be unique per meeting, I've used a GUID.
请注意,每个会议的 UID 必须是唯一的,我使用了 GUID。
Also note you need to replace CREATED, DTSTART, DTEND, DTSTAMP, LAST-MODIFIED. These are UTC date/times.
另请注意,您需要替换 CREATED、DTSTART、DTEND、DTSTAMP、LAST-MODIFIED。这些是 UTC 日期/时间。
var m = new MailMessage();
m.Subject = "Meeting";
m.Body = "";
string iCal =
@"BEGIN:VCALENDAR
PRODID:-//Microsoft Corporation//Outlook 14.0 MIMEDIR//EN
VERSION:2.0
METHOD:PUBLISH
X-MS-OLK-FORCEINSPECTOROPEN:TRUE
BEGIN:VEVENT
CLASS:PUBLIC
CREATED:20140423T045933Z
DESCRIPTION:desc
DTEND:20140430T080000Z
DTSTAMP:20140423T045933Z
DTSTART:20140430T060000Z
LAST-MODIFIED:20140423T045933Z
LOCATION:location...
PRIORITY:5
SEQUENCE:0
SUMMARY;LANGUAGE=en-us:Summary...
TRANSP:OPAQUE
UID:D8BFD357-88A7-455C-86BC-C2CECA9AC5C6
X-MICROSOFT-CDO-BUSYSTATUS:BUSY
X-MICROSOFT-CDO-IMPORTANCE:1
X-MICROSOFT-DISALLOW-COUNTER:FALSE
X-MS-OLK-AUTOFILLLOCATION:FALSE
X-MS-OLK-CONFTYPE:0
BEGIN:VALARM
TRIGGER:-PT60M
ACTION:DISPLAY
DESCRIPTION:Reminder
END:VALARM
END:VEVENT
END:VCALENDAR";
using (var iCalView = AlternateView.CreateAlternateViewFromString(iCal, new System.Net.Mime.ContentType("text/calendar")))
{
m.AlternateViews.Add(iCalView);
var c = new SmtpClient();
// Send message
c.Send(m);
}
This assumes you have a local SMTP server configured in your config file:
这假设您在配置文件中配置了本地 SMTP 服务器:
<system.net>
<mailSettings>
<smtp deliveryMethod="Network" from="[email protected]">
<network defaultCredentials="true" host="smtp.example.local" />
</smtp>
</mailSettings>
</system.net>
回答by Oran Dennison
iCalendar is a great general-purpose solution, and the DDay.iCal library is a great way to do this from .NET, but I believe Exchange Web Services(EWS) are a better solution in the context of the original question (Exchange, C#/.NET).
iCalendar 是一个很好的通用解决方案,而 DDay.iCal 库是从 .NET 执行此操作的好方法,但我相信Exchange Web Services(EWS) 在原始问题的上下文中是更好的解决方案(Exchange、C# /。网)。
And if you're using a .NET language such as C#, you should use the EWS Managed APIwrapper which greatly simplifies working with EWS.
如果您使用的是 C# 等 .NET 语言,则应使用EWS 托管 API包装器,它极大地简化了使用 EWS 的过程。
From the docs, here's how to use the EWS Managed API to create a meeting and send the request to invitees:
从docs,这里是如何使用 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("[email protected]");
appointment.RequiredAttendees.Add("[email protected]");
appointment.OptionalAttendees.Add("[email protected]");
// Send the meeting request to all attendees and save a copy in the Sent Items folder.
appointment.Save(SendInvitationsMode.SendToAllAndSaveCopy);
回答by DrKoch
You can send meeting requests by mail to outlook using the iCal Standard (RFC 5545)
您可以使用iCal 标准 (RFC 5545)通过邮件将会议请求发送到 Outlook
You can't send todo items this way. You may send "Appointments" but these appear in outlook as .ics attachments which have to be accepted "blindly".
您不能以这种方式发送待办事项。您可以发送“约会”,但这些在 Outlook 中显示为 .ics 附件,必须“盲目”接受。
Meeting requests appear in outlook with a nice preview and can be accepted or rejeted. The sending program may modify or cancel the meeting after it was sent.
会议请求出现在 Outlook 中,预览效果很好,可以接受或拒绝。会议发送后,发送程序可以修改或取消会议。
It's easieset to create a valid iCal item with the DDay.iCal .Net Library
使用DDay.iCal .Net 库可以轻松创建有效的 iCal 项目
The code below is a complete working example. It builds a string with a valid iCal meeting request and sends it by mail.
下面的代码是一个完整的工作示例。它使用有效的 iCal 会议请求构建一个字符串并通过邮件发送。
The code creates a mail with:
该代码创建了一封邮件:
- plain text body for simple mail clients
- HTML body for diplay in modern mail clients
- iCal meeting request as AlternateView (will display in Outlook)
- iCal meeting request as Attachment (usable in mail clients other than outlook)
- 简单邮件客户端的纯文本正文
- 现代邮件客户端中显示的 HTML 正文
- iCal 会议请求作为 AlternateView(将显示在 Outlook 中)
- iCal 会议请求作为附件(可用于 Outlook 以外的邮件客户端)
The code shows how to add:
代码显示了如何添加:
- description text as HTML, looks nicer in outlook
- Priority, visibility (public/private/confidential)
- optional organizer (will show in outlook instead of the mail sender)
- optional attendees
- optional alarm
- optional attachments to the meeting. will show up in outlook's calendar
- 描述文本为 HTML,在 Outlook 中看起来更好
- 优先级、可见性(公共/私人/机密)
- 可选的组织者(将显示在 Outlook 中而不是邮件发件人中)
- 可选参加者
- 可选报警
- 会议的可选附件。将显示在 Outlook 的日历中
Some important details:
一些重要的细节:
- mail sender (or optional organizer) and mail receiver must be different to make this work in outlook
- METHOD in .ics and METHOD in Mime.ContentType must match
- The meeting must lie in the future to make this work in outlook
- the .ics part must be the last alternateView part in the MIME mail
- 邮件发件人(或可选的组织者)和邮件收件人必须不同才能在 Outlook 中工作
- .ics 中的 METHOD 和 Mime.ContentType 中的 METHOD 必须匹配
- 会议必须在将来才能使这项工作具有前景
- .ics 部分必须是 MIME 邮件中的最后一个替代视图部分
The exact details about the way outlook interprets .ics files are detailed in [MS-OXCICAL]: iCalendar to Appointment Object Conversion Algorithm
[MS-OXCICAL]: iCalendar to Appointment Object Conversion Algorithm 中详细介绍了 Outlook 解释 .ics 文件方式的确切细节
We'll use these assemblies:
我们将使用这些程序集:
using System;
using System.IO;
using System.Net.Mail;
using DDay.iCal;
using DDay.iCal.Serialization.iCalendar;
For DDay.iCal its enough to download the DDay.iCal binary Files. If you want to add some features it's best to look at the DDay.iCal sources because the documentation is outdated and the sources contain pretty complete tests which excercise all its features.
对于 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 = "[email protected]";
string bodyPlainText = "This is the simple iCal plain text msg";
string bodyHtml = "This is the simple <b>iCal HTML message</b>";
string location = "Meeting room 101";
// 1: High
// 5: Normal
// 9: low
int priority = 1;
//=====================================
MailMessage message = new MailMessage();
message.From = new MailAddress("[email protected]");
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<Event>();
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("[email protected]");
//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:[email protected]");
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);
Here the ReadBinary() function:
这里的 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;
}
Its easiest to configure the SmtpClient in the config file like this:
在配置文件中配置 SmtpClient 最简单,如下所示:
<configuration>
...
<system.net>
<mailSettings>
<smtp>
<network host="mysmtp.server.com" port="25" userName="mySmtpUserName" password="myPassword" />
</smtp>
</mailSettings>
</system.net>
...