使用 Exchange 模拟添加约会

了解如何使用 EWS 托管 API 或 Exchange 中的 EWS 将约会添加至用户日历中。

可以使用启用了 ApplicationImpersonation 角色的服务帐户创建将约会直接插入 Exchange 日历的服务应用程序中。 使用模拟时,应用程序将充当用户,就像用户使用客户端(如 Outlook)将约会添加到日历中一样。

使用模拟时,请记住以下事项:

  • ExchangeService对象必须绑定到服务帐户。可以使用相同的 ExchangeService 对象来模拟多个帐户,方法是更改要模拟的每个帐户的 ImpersonatedUserId属性。
  • 保存到模拟帐户的任何项只能使用一次。 例如,如果要在多个帐户中保存同一约会,必须为每个帐户创建 一个 Appointment 对象。

先决条件

应用程序需要一个用于连接到 Exchange 服务器的帐户,然后才能使用模拟。 建议为应用程序使用一个服务帐户,该帐户已被授予将要访问的帐户的应用程序模拟角色。 有关详细信息,请参阅配置模拟

通过使用 EWS 托管 API 添加约会

以下示例将约会或会议添加到一个或多个 Exchange 帐户的日历中。该方法采用三个参数。

  • service— 绑定到 Exchange 服务器上服务应用程序帐户的 ExchangeService 对象。
  • emailAddresses — 包含 SMTP 电子邮件地址字符串列表的 System.List 对象。
  • factory — 实现 IAppointmentFactory 接口的对象。 此接口有一个方法, GetAppointment ,该方法将 ExchangeService 对象作为参数,并返回 Appointment 对象。 IAppointmentFactory 接口是定义的 IAppointmentFactory 接口
private static void CreateAppointments(ExchangeService service, List<string> emailAddresses, IAppointmentFactory factory)
{
  // Loop through the list of email addresses to add the appointment.
  foreach (var emailAddress in emailAddresses)
  {
    Console.WriteLine(string.Format("  Placing appointment in calendar for {0}.", emailAddress));
    // Set the email address of the account to get the appointment.
    service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, emailAddress);
    // Get the appointment to add.
    Appointment appointment = factory.GetAppointment(service);
    // Save the appointment.
    try
    {
      if (appointment.RequiredAttendees.Count > 0)
      {
        // The appointment has attendees so send them the meeting request.
        appointment.Save(SendInvitationsMode.SendToAllAndSaveCopy);
      }
      else
      {
        // The appointment does not have attendees, so just save to calendar.
        appointment.Save(SendInvitationsMode.SendToNone);
      }
    }
    catch (ServiceResponseException ex)
    {
      Console.WriteLine(string.Format("Could not create appointment for {0}", emailAddress));
      Console.WriteLine(ex.Message);
    }
  }
}

保存约会时,代码将检查以确定是否已将任何与会者添加到 RequiredAttendees 属性。如果有,则 Appointment.Save方法使用 SendToAllAndSaveCopy 枚举值调用,以便与会者接收会议请求;否则,Appointment.Save 方法使用 SendToNone 枚举值调用,以便约会为 已保存到模拟用户的日历中,Appointment.IsMeeting 属性设置为 false

IAppointmentFactory 接口

由于每次要在模拟用户的日历上保存约会时都需要一个新的 Appointment 对象,因此 IAppointmentFactory 接口会提取用于填充每个 Appointment 对象的对象。 此版本是一个简单的接口,只包含一个方法,即 GetAppointment,该方法将 ExchangeService 对象作为参数,并返回绑定到该 ExchangeService 对象的新 Appointment 对象。

interface IAppointmentFactory
{
  Appointment GetAppointment(ExchangeService service);
}

以下 AppointmentFactory 类示例演示 IAppointmentFactory 接口的实现,该接口返回自现在起三天内发生的简单约会。 如果取消注释 appointment.RequiredAttendees.Add 行, GetAppointment 方法将返回会议,并且该行中指定的电子邮件地址将收到会议请求,其中模拟用户被列为组织者。

class AppointmentFactory : IAppointmentFactory
{
  public Appointment GetAppointment(ExchangeService service)
  {
    // First create the appointment to add.
    Appointment appointment = new Appointment(service);
    // Set the properties on the appointment.
    appointment.Subject = "Tennis lesson";
    appointment.Body = "Focus on backhand this week.";
    appointment.Start = DateTime.Now.AddDays(3);
    appointment.End = appointment.Start.AddHours(1);
    appointment.Location = "Tennis club";
    // appointment.RequiredAttendees.Add(new Attendee("sonyaf@contoso1000.onmicrosoft.com"));
    return appointment;
  }
}

使用模拟及 EWS 添加约会

EWS 使应用程序可使用模拟代表日历的所有者将项目添加到日历中。 此示例演示如何使用 CreateItem 操作将约会添加到模拟帐户的日历中。

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" 
       xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types" 
       xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2013" />
    <t:TimeZoneContext>
      <t:TimeZoneDefinition Id="Pacific Standard Time" />
    </t:TimeZoneContext>
    <t:ExchangeImpersonation>
      <t:ConnectingSID>
        <t:SmtpAddress>alfred@contoso.com</t:SmtpAddress>
      </t:ConnectingSID>
    </t:ExchangeImpersonation>
  </soap:Header>
  <soap:Body>
    <m:CreateItem SendMeetingInvitations="SendToNone">
      <m:Items>
        <t:CalendarItem>
          <t:Subject>Tennis lesson</t:Subject>
          <t:Body BodyType="HTML">Focus on backhand this week.</t:Body>
          <t:ReminderDueBy>2013-09-19T14:37:10.732-07:00</t:ReminderDueBy>
          <t:Start>2013-09-21T19:00:00.000Z</t:Start>
          <t:End>2013-09-21T20:00:00.000Z</t:End>
          <t:Location>Tennis club</t:Location>
          <t:MeetingTimeZone TimeZoneName="Pacific Standard Time" />
        </t:CalendarItem>
      </m:Items>
    </m:CreateItem>
  </soap:Body>
</soap:Envelope>

请注意,除在 SOAP 标头中添加 ExchangeImpersonation 元素来指定正在模拟的帐户之外,这是用于创建约会而不使用模拟的相同 XML 请求。

下面的示例演示由 CreateItem 操作返回的响应 XML。

备注

ItemIdChangeKey 属性会缩短,以实现可读性。

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo MajorVersion="15" MinorVersion="0" MajorBuildNumber="775" MinorBuildNumber="7" Version="V2_4" 
 xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types" 
 xmlns="https://schemas.microsoft.com/exchange/services/2006/types" 
 xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <m:CreateItemResponse xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" 
  xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:CreateItemResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:Items>
            <t:CalendarItem>
              <t:ItemId Id="AAMkA" ChangeKey="DwAAA" />
            </t:CalendarItem>
          </m:Items>
        </m:CreateItemResponseMessage>
      </m:ResponseMessages>
    </m:CreateItemResponse>
  </s:Body>
</s:Envelope>

同样,这是在不使用模拟的情况下使用 CreateItem 操作时返回的相同 XML。

另请参阅