web-dev-qa-db-fra.com

Envoi de demandes de réunion Outlook sans Outlook?

Je me demande simplement s'il est possible d'envoyer des demandes de réunion à des personnes sans avoir Outlook installé sur le serveur et en utilisant COM Interop (ce que je veux éviter à tout prix sur un serveur).

Nous avons Exchange 2003 dans un domaine Windows 2003 et tous les utilisateurs sont des utilisateurs de domaine. Je suppose que je peux envoyer des `` iCal/vCal '' ou quelque chose du genre, mais je me demande s'il existe un moyen standard approprié d'envoyer des demandes de réunion via Exchange sans Outlook?

C'est C # /. Net si c'est important.

38
Michael Stum

La façon d'envoyer une demande de réunion à Outlook (et de la faire reconnaître) se présente comme suit:

  • préparez un fichier iCalendar, assurez-vous de définir ces propriétés supplémentaires, car Outlook en a besoin:
  • préparer un multipart/alternative courrier:
    • Partie 1: text/html (ou ce que vous voulez) - il est affiché sur les lecteurs de courrier "ordinaires" ou en tant que solution de rechange et contient un résumé de l'événement sous une forme lisible par l'homme
    • Partie 2: text/calendar; method=REQUEST, contient le contenu du fichier ics (l'en-tête method paramètre doit correspondre à la méthode dans l'ics). Attention au codage de texte correct, déclarer un paramètre d'en-tête charset ne fera pas de mal.
    • Partie 3: facultativement, joignez le fichier .ics lui-même, afin que les lecteurs de courrier ordinaire puissent proposer à l'utilisateur un élément sur lequel cliquer. Outlook ne nécessite pas vraiment la pièce jointe car il lit simplement le text/calendar partie.
  • Envoyez le courrier à un utilisateur Outlook. Si tout est correct, le courrier apparaît comme une demande de réunion, avec des boutons de présence et une entrée automatique dans le calendrier des utilisateurs lors de l'acceptation.
  • Mettre en place quelque chose qui traite les réponses (elles vont à l'organisateur de la réunion). Je n'ai pas encore pu obtenir le suivi automatique des participants pour travailler avec une boîte aux lettres Exchange car l'événement n'existera pas dans le calendrier des organisateurs. Outlook a besoin des UID et des SEQUENCES pour correspondre à ses attentes, mais avec un UID que vous avez créé, cela ne fonctionnera guère.

Pour obtenir de l'aide sur les détails et les particularités du format de fichier ics, assurez-vous de visiter le iCalendar Specification Excerpts by Masahide Kanzaki . Ils sont une lumière dans l'obscurité, bien mieux que de se ronger RFC 2445 . Mais là encore, il existe peut-être une bibliothèque pratique pour .NET.

51
Tomalak
8
Stefan Steiger

Vous pouvez envoyer des demandes de réunion par courrier à Outlook à l'aide de la norme iCal (RFC 5545)

Vous ne pouvez pas envoyer des éléments todo de cette façon. Vous pouvez envoyer des "rendez-vous", mais ceux-ci apparaissent dans Outlook en tant que pièces jointes .ics qui doivent être acceptées "à l'aveugle".

Les demandes de réunion apparaissent dans Outlook avec un joli aperçu et peuvent être acceptées ou rejetées. Le programme d'envoi peut modifier ou annuler la réunion après son envoi.

Il est facile de créer un élément iCal valide avec la Bibliothèque DDay.iCal .Net

Le code ci-dessous est un exemple de travail complet. Il crée une chaîne avec une demande de réunion iCal valide et l'envoie par courrier.

Le code crée un mail avec:

  • corps en texte brut pour les clients de messagerie simples
  • Corps HTML pour l'affichage dans les clients de messagerie modernes
  • demande de réunion iCal en tant que AlternateView (s'affiche dans Outlook)
  • demande de réunion iCal en tant que pièce jointe (utilisable dans les clients de messagerie autres qu'Outlook)

Le code montre comment ajouter:

  • le texte de description au format HTML est plus joli dans Outlook
  • Priorité, visibilité (public/privé/confidentiel)
  • organisateur facultatif (s'affichera dans Outlook au lieu de l'expéditeur du courrier)
  • participants facultatifs
  • alarme en option
  • pièces jointes facultatives à la réunion. apparaîtra dans le calendrier d'Outlook

Quelques détails importants:

  • l'expéditeur (ou l'organisateur facultatif) et le destinataire du courrier doivent être différents pour que cela fonctionne dans Outlook
  • METHOD en .ics et METHOD en Mime.ContentType doivent correspondre
  • La réunion doit se situer à l'avenir pour que cela fonctionne dans Outlook
  • la partie .ics doit être la dernière partie AlternateView dans le courrier MIME

Les détails exacts sur la façon dont Outlook interprète les fichiers .ics sont détaillés dans [MS-OXCICAL]: iCalendar to Appointment Object Conversion Algorithm

Nous utiliserons ces assemblages:

using System;
using System.IO;
using System.Net.Mail;
using DDay.iCal;
using DDay.iCal.Serialization.iCalendar;

Pour DDay.iCal, il suffit de télécharger le fichiers binaires DDay.iCal . Si vous souhaitez ajouter des fonctionnalités, il est préférable de consulter les sources DDay.iCal car la documentation est obsolète et les sources contiennent des tests assez complets qui exercent toutes ses fonctionnalités.

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);

Voici la fonction 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;
}

Il est plus facile de configurer SmtpClient dans le fichier de configuration comme ceci:

<configuration>
  ...
  <system.net>  
    <mailSettings>
      <smtp>
        <network Host="mysmtp.server.com" port="25" userName="mySmtpUserName" password="myPassword" />
      </smtp>
    </mailSettings>
  </system.net>
  ...
5
DrKoch

iCalendar est une excellente solution à usage général, et la bibliothèque DDay.iCal est un excellent moyen de le faire à partir de .NET, mais je pense que Exchange Web Services (EWS) sont une meilleure solution dans le contexte de la question d'origine (Exchange, C # /. NET).

Et si vous utilisez un langage .NET tel que C #, vous devez utiliser le wrapper EWS Managed API qui simplifie considérablement le travail avec EWS.

À partir de les documents , voici comment utiliser l'API managée EWS pour créer une réunion et envoyer la demande aux invités:

// 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);
5
Oran Dennison

Le code ci-dessous enverra une demande de réunion de telle manière qu'Outlook affichera les boutons Accepter/Refuser.

Notez que l'UID doit être unique par réunion, j'ai utilisé un GUID.

Notez également que vous devez remplacer CREATED, DTSTART, DTEND, DTSTAMP, LAST-MODIFIED. Ce sont les dates/heures 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);
    }

Cela suppose que vous avez un serveur SMTP local configuré dans votre fichier de configuration:

  <system.net>
    <mailSettings>
      <smtp deliveryMethod="Network" from="[email protected]">
        <network defaultCredentials="true" Host="smtp.example.local" />
      </smtp>
    </mailSettings>
  </system.net>
4
saille