2009-01-20 12 views
36

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

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

Il s'agit de C#/.net si cela compte.

+1

La quantité de temps que vous avez choisi d'attendre me fait pense que ma suggestion n'est pas exactement ce que tu avais en tête. Avez-vous au moins le faire fonctionner? – Tomalak

+1

Je n'ai tout simplement pas eu le temps de le tester plus tôt. Un test rapide a semblé fonctionner, et j'ai envoyé une invitation de réunion d'Outlook à un compte qui a permis à POP3 d'obtenir un "vidage brut".Ces deux bits sont assez bons pour que je puisse comprendre le reste, puisque j'ai seulement besoin d'envoyer des réunions mais je ne me soucie pas de répondre –

+1

En tout cas, votre réponse a été extrêmement utile, merci beaucoup! –

Répondre

47

Le moyen d'envoyer une demande de réunion à Outlook (et l'ont reconnu) va comme ceci:

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

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é, beaucoup mieux que de ronger votre chemin à travers RFC 2445. Mais encore une fois, peut-être une bibliothèque pratique existe pour .NET.

+0

Je n'ai tout simplement pas eu le temps de le tester plus tôt. Un test rapide a semblé fonctionner, et j'ai envoyé une invitation de réunion d'Outlook à un compte qui a permis à POP3 d'obtenir un "vidage brut". Ces deux bits sont assez bons pour que je puisse comprendre le reste, puisque je n'ai besoin que d'envoyer des réunions sans me soucier de la réponse –

+1

Enlever l'en-tête suivant de la partie 2 a fait l'affaire: Content-Disposition: attachment; filename = meeting.ics Tant que cet en-tête était dans le courrier, Outlook afficherait l'ICS en pièce jointe. – Bob

+0

C'est ce qui se passe lorsqu'un en-tête Content-Disposition: attachment est présent. ;-) – Tomalak

3

Le code ci-dessous envoie une demande de réunion de telle sorte que Outlook rendra 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, DERNIÈRE MODIFICATION. 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> 
5

iCalendar est une solution polyvalente et la bibliothèque DDay.iCal est une excellente façon de faire à partir de. NET, mais je crois 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, ce qui simplifie grandement le travail avec EWS.

De the docs, voici comment utiliser l'API SAP Managed 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); 
+1

Je suis d'accord, cette solution est beaucoup plus simple que les autres. Il convient également de noter que EWS ne nécessite pas l'interopérabilité Outlook COM. – JordanTDN

3

Vous pouvez envoyer des demandes de réunion par courrier à Outlook en utilisant le iCal Standard (RFC 5545)

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

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

Il est easieset pour créer un élément iCal valide avec le DDay.iCal .Net Library

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

Le code crée un mail avec:

    corps de texte brut
  • pour les clients de messagerie simples
  • corps HTML pour diplay dans les clients de messagerie modernes
  • iCal demande de réunion comme AlternateView (affiche dans Outlook)
  • demande de réunion iCal tant que pièce jointe (utilisable dans les clients de messagerie autres que outlook)

Le code montre comment ajouter:

  • texte de description HTML, semble plus agréable dans les perspectives
  • priorité, la visibilité (public/privé/confidentiel)
  • organisateur en option (montrera dans les perspectives au lieu de l'expéditeur du courrier)
  • participants facultatifs
  • alarme optionnelle
  • pièces jointes facultatives à la réunion. sera affiché dans le calendrier outlook

Quelques détails importants:

  • expéditeur de courrier (ou organisateur en option) et le récepteur de courrier doit être différent pour faire ce travail dans les perspectives
  • METHOD ics et méthode en Mime.ContentType doit correspondre
  • la réunion doit se trouver à l'avenir de faire ce travail dans les perspectives
  • la partie .ics doit être la dernière partie de AlternateView dans le courrier MIME

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

Nous allons utiliser ces ensembles:

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

Pour DDay.iCal son assez pour télécharger le DDay.iCal binary Files. Si vous voulez ajouter quelques fonctionnalités, il est préférable de regarder les sources de DDay.iCal car la documentation est obsolète et les sources contiennent des tests assez complets qui excercent 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); 

Ici, 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; 
} 

Son plus facile à configurer le 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> 
    ... 
+0

Merci pour cette réponse si complète! Enregistre beaucoup d'essais et d'erreurs –