实现发送Outlook appointment/Meeting

本秂侑毒 提交于 2019-11-28 18:03:36

1.直接编码方式

遵循rfc5545x协议标准开发,参考链接  https://tools.ietf.org/html/rfc5545,正常遵循此标准开发的Calendar都是兼容的,比如Gmail。

优点:不依赖第三方组件

缺点:实现相对复杂些

 

2.可以实现功能

发送 修改 取消(取消之后,支持修改,修改之后,状态是未取消状态) 支持添加附件 内容支持html格式 循环功能,支持Daily、Weekly、Monthly、Yearly

 

3.与Outlook发送的区别:

Organizer暂时在Calendar看不到自己的Appointment,所以本文所介绍的方案比较适合作为系统发送的Appointment的场景。

4.实现代码

  1         public static void SendMeeting(ref string appointmentID, MailAddress from, MailAddressCollection to, MailAddressCollection cc, MailAddressCollection bcc, string subject, string body, DateTimeOffset dtStart, DateTimeOffset dtEnd, string location, Collection<Attachment> attachments, MailAddress sender, string smtp, int port, string account, string password, bool async, METHOD method, int utcOffset, RecurType recurType, DateTimeOffset recurEndByDate,bool isRecurEndbyDate,int recurEndAfterOccurences, RecurDaily recurDaily, RecurWeekly recurWeekly,RecurMonthly recurMonthly,RecurYearly recurYearly, string originalSenderAuto = "", string originalMessageAutoID = "", bool isLocalTimeZone = true,bool isAllDay=false)
  2         {
  3             //     CIPPlanner.CIPAce.Configuration.Configuration syscfg = new CIPPlanner.CIPAce.Configuration.Configuration();
  4             if (from == null) from = new MailAddress(ApplicationSetting.SmtpFrom);
  5             if (smtp == null) smtp = ApplicationSetting.SmtpServer;
  6             if (port <= 0) port = ApplicationSetting.SmtpPort;
  7             if (sender == null) sender = new MailAddress(ApplicationSetting.SmtpSender);
  8             if (account == null) account = ApplicationSetting.SmtpAccount;
  9             if (password == null) password = ApplicationSetting.SmtpPassword;
 10 
 11             MailMessage mm = new MailMessage();
 12             mm.IsBodyHtml = true;
 13             mm.Subject = (method==METHOD.Cancel? "Canceled: ":"")+subject;
 14             mm.Sender = sender;
 15             mm.From = from;
 16             // 邮件标头 
 17             mm.Headers.Add("Content-class", "urn:content-classes:calendarmessage");
 18 
 19             //add hidden info in mailmessage
 20             string hiddenInfo = "";
 21             if (originalSenderAuto != "" && originalMessageAutoID != "")
 22             {
 23                 hiddenInfo = HiddenInfoConsts.KEY + HiddenInfoConsts.SPLIT_FLAG.ToString() + originalSenderAuto + HiddenInfoConsts.SPLIT_FLAG.ToString() + originalMessageAutoID + HiddenInfoConsts.SPLIT_FLAG.ToString() + HiddenInfoConsts.KEY;// HiddenInfoConsts.KEY与HiddenInfoKey.Second为拼接格式,便于后续解析;
 24                 body += string.Format("<!-- {0} -->", hiddenInfo);
 25                 mm.Headers.Add(HiddenInfoConsts.KEY, hiddenInfo);
 26                 mm.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(hiddenInfo, null, "text/plain"));
 27             }
 28             else
 29             {
 30                 mm.Body = body;
 31             }
 32             ContentType typeHtml = new ContentType("text/html");
 33             typeHtml.Parameters.Add("charset", "utf-8");
 34             AlternateView viewHtml = AlternateView.CreateAlternateViewFromString(body, typeHtml);
 35             mm.AlternateViews.Add(viewHtml);
 36             foreach (var item in attachments)
 37             {
 38                 LinkedResource resource = new LinkedResource(item.ContentStream);
 39                 resource.ContentId = Guid.NewGuid().ToString().Replace("-", "") + DateTime.Now.Ticks.ToString();
 40                 resource.ContentType.Name = item.Name;//Name of file              
 41                 resource.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;
 42                 viewHtml.LinkedResources.Add(resource);
 43             }
 44 
 45             ContentType typeCalendar = new ContentType("text/calendar");
 46             //向calendar header添加参数        
 47             typeCalendar.Parameters.Add("method", method == METHOD.Cancel ? "CANCEL" : "REQUEST");//REQUEST
 48             typeCalendar.Parameters.Add("charset", "utf-8");
 49            // typeCalendar.Parameters.Add("name", "meeting.ics");
 50             // 使用vcalendar格式创建邮件的body部分     
 51             //获取 reccuringParam部分
 52             string reccuringParam = "";
 53             if(recurType!=RecurType.NoRecurrence)
 54             {
 55                 reccuringParam = GetRecurringParam(recurType, isRecurEndbyDate, recurEndByDate, recurEndAfterOccurences, recurDaily, recurWeekly, recurMonthly, recurYearly);
 56             }
 57             if (string.IsNullOrEmpty(ApplicationSetting.emailParam))
 58             {
 59                 AlternateView viewCalendar = AlternateView.CreateAlternateViewFromString(CalendarGenerate(ref appointmentID, from, to, cc, bcc, subject, body, dtStart, dtEnd, location, method, reccuringParam, isAllDay), typeCalendar);
 60                 viewCalendar.TransferEncoding = TransferEncoding.SevenBit;
 61                 mm.AlternateViews.Add(viewCalendar);
 62 
 63             }
 64             else
 65             {
 66                 AlternateView viewCalendar = AlternateView.CreateAlternateViewFromString(ApplicationSetting.emailParam, typeCalendar);
 67                 viewCalendar.TransferEncoding = TransferEncoding.SevenBit;
 68                 mm.AlternateViews.Add(viewCalendar);
 69             }
 70           
 71 
 72             if (to != null)
 73             {
 74                 foreach (MailAddress ma in to)
 75                 {
 76                     mm.To.Add(ma);
 77                 }
 78             }
 79             if (cc != null)
 80             {
 81                 foreach (MailAddress ma in cc)
 82                 {
 83                     mm.CC.Add(ma);
 84                 }
 85             }
 86             if (bcc != null)
 87             {
 88                 foreach (MailAddress ma in bcc)
 89                 {
 90                     mm.Bcc.Add(ma);
 91                 }
 92             }
 93             //if (attachments != null)
 94             //{
 95             //    foreach (Attachment a in attachments)
 96             //    {
 97             //        mm.Attachments.Add(a);
 98             //    }
 99             //}
100 
101             SmtpClient sc = new SmtpClient(smtp, port);
102             sc.UseDefaultCredentials = false;
103             sc.Credentials = new NetworkCredential(account, password);
104             sc.DeliveryMethod = SmtpDeliveryMethod.Network;
105             sc.EnableSsl = ApplicationSetting.SmtpEnableSsl == "true" || ApplicationSetting.SmtpEnableSsl == "1";
106             if (!async)
107             {
108                 try
109                 {
110                     sc.Send(mm);
111                 }
112                 finally
113                 {
114                     mm.Dispose();
115                 }
116                 return;
117             }
118 
119             System.Threading.SynchronizationContext context = System.ComponentModel.AsyncOperationManager.SynchronizationContext;
120             try
121             {
122                 System.ComponentModel.AsyncOperationManager.SynchronizationContext = new System.Threading.SynchronizationContext();
123                 sc.SendCompleted += new SendCompletedEventHandler(sc_SendCompleted);
124                 sc.SendAsync(mm, mm);
125             }
126             finally
127             {
128                 System.ComponentModel.AsyncOperationManager.SynchronizationContext = context;
129                 //mm.Dispose();
130             }
131 
132         }
133         static   string calDateFormat = "yyyyMMddTHHmmssZ";
134         /// <summary>          
135         /// 生成ics文件(为以Outlook主要参考)         
136         /// </summary>          
137         /// <returns></returns>         
138         private static string CalendarGenerate(ref string appointmentID,MailAddress from, MailAddressCollection to, MailAddressCollection cc, MailAddressCollection bcc, string subject, string body, DateTimeOffset dtStart, DateTimeOffset dtEnd, string location, METHOD method,string reccurringParam,bool isAllDay=false)
139         {
140            
141             StringBuilder sb = new StringBuilder();
142             sb.Append("BEGIN:VCALENDAR").Append("\r\n");
143             //sb.Append("PRODID:").Append("-//Microsoft Corporation//Outlook 12.0 //EN").Append("\r\n");
144             sb.Append("PRODID:").Append("-//Microsoft Corporation//Outlook 12.0 MIMEDIR//EN").Append("\r\n");
145             sb.Append("VERSION:2.0").Append("\r\n");
146             if (method == METHOD.Create || method == METHOD.Update)
147                 sb.Append("METHOD:REQUEST").Append("\r\n");
148             else
149                 sb.Append("METHOD:CANCEL").Append("\r\n");
150             //sb.Append("X-MS-OLK-FORCEINSPECTOROPEN:TRUE").Append("\r\n");
151             sb.Append("BEGIN:VEVENT").Append("\r\n");
152 
153             if (!string.IsNullOrEmpty(from.Address))
154             {
155                 ///  ORGANIZER; CN = "John Smith":mailto: jsmith @example.com
156                 sb.Append("ORGANIZER;CN=\"").Append(from.DisplayName).Append("\":mailto" + ":").Append(from.Address).Append("\r\n");
157             }
158             foreach (var recipient in to)
159             {
160                 sb.Append("ATTENDEE;CN=\"" + recipient.DisplayName + "\";ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:" + recipient.Address).Append("\r\n");
161             }
162             foreach (var recipient in cc)
163             {
164                 sb.Append("ATTENDEE;CN=\"" + recipient.DisplayName + "\";ROLE=OPT-PARTICIPANT;RSVP=TRUE:mailto:" + recipient.Address).Append("\r\n");
165             }
166             foreach (var recipient in bcc)
167             {
168                 sb.Append("ATTENDEE;CN=\"" + recipient.DisplayName + "\";CUTYPE=RESOURCE;ROLE=NON-PARTICIPANT:mailto:" + recipient.Address).Append("\r\n");
169             }
170 
171             sb.Append("CLASS:PUBLIC").Append("\r\n");
172             sb.Append("CREATED:").Append(DateTime.Now.ToUniversalTime().ToString(calDateFormat)).Append("\r\n");
173             sb.Append("DESCRIPTION:").Append("DESCRIPTION").Append("\r\n");
174             // string timeZoneId = isLocalTimezone ? GetCurrentTimeZoneName() : GetTimezoneIdbyUTCOffset(utcOffset);
175             // sb.Append("DTEND;TZID="+ timeZoneId + ":").Append(dtEnd.ToString(calDateFormat)).Append("\r\n");
176             sb.Append("DTSTART:").Append(dtStart.ToUniversalTime().ToString(calDateFormat)).Append("\r\n");
177             sb.Append("DTEND:").Append(dtEnd.ToUniversalTime().ToString(calDateFormat)).Append("\r\n");
178             sb.Append("DTSTAMP:").Append(DateTime.Now.ToUniversalTime().ToString(calDateFormat)).Append("\r\n");
179             //sb.Append("DTSTART;TZID=" + timeZoneId + ":").Append(dtStart.ToString(calDateFormat)).Append("\r\n");
180             // if()
181             // sb.Append("RRULE:FREQ=DAILY;COUNT=10").Append("\r\n");//recurring         WKST=weekday 
182             if (!string.IsNullOrEmpty(reccurringParam))
183                 sb.Append(reccurringParam).Append("\r\n");
184             //  sb.Append("RRULE:FREQ=MONTHLY;UNTIL=20191209T020000Z;BYDAY=2MO").Append("\r\n");//recurring        BYMONTHDAY=3      不支持-2MO
185             // sb.Append("RRULE:FREQ=WEEKLY;UNTIL=20191209T020000Z;BYDAY=MO").Append("\r\n");
186             // sb.Append("RRULE:FREQ=MONTHLY;COUNT=10;BYDAY=2MO;BYMONTH=3").Append("\r\n");//recurring        BYMONTHDAY=3      不支持-2MO
187 
188             //  sb.Append("RECURRENCE-ID;VALUE=DATE:"+ DateTime.Now.ToString("yyyyMMdd")).Append("\r\n");
189             sb.Append("LAST-MODIFIED:").Append(DateTime.Now.ToUniversalTime().ToString(calDateFormat)).Append("\r\n");
190             sb.Append("LOCATION:").Append(NotNull(location)).Append("\r\n");
191             sb.Append("PRIORITY:1").Append("\r\n");
192             //sb.Append("SEQUENCE:0").Append("\r\n");
193             if(method==METHOD.Cancel)
194             {
195                 sb.Append("SUMMARY:").Append("Canceled: " + NotNull(subject)).Append("\r\n");
196             }
197             else
198             {
199                 sb.Append("SUMMARY:").Append(NotNull(subject)).Append("\r\n");
200             }
201             if (method == METHOD.Create)
202             {
203                 ApplicationSetting.Uid = Guid.NewGuid().ToString().Replace("-", "") + Guid.NewGuid().ToString().Replace("-", "");
204                 appointmentID = ApplicationSetting.Uid;
205             }
206             else
207             {
208                 ApplicationSetting.Uid = appointmentID;
209                 if(string.IsNullOrEmpty(ApplicationSetting.Uid))
210                 {
211                     throw new Exception("appointmentID can not be empty when update or cancel");
212                 }
213             }
214             sb.Append("SEQUENCE:0").Append("\r\n");
215             sb.Append("UID:").Append(ApplicationSetting.Uid).Append("\r\n");
216             sb.Append("X-ALT-DESC;FMTTYPE=text/html:").Append(body).Append("\r\n");
217             if (method == METHOD.Cancel)
218             { sb.Append("STATUS:CANCELLED").Append("\r\n"); }
219             else
220             { sb.Append("STATUS:CONFIRMED").Append("\r\n"); }
221             sb.Append("TRANSP:OPAQUE").Append("\r\n");
222             sb.Append("X-MICROSOFT-CDO-BUSYSTATUS:BUSY").Append("\r\n");
223             sb.Append("X-MICROSOFT-CDO-IMPORTANCE:1").Append("\r\n");
224             sb.Append("X-MICROSOFT-CDO-INSTTYPE:0").Append("\r\n");
225             sb.Append("X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY").Append("\r\n");
226             sb.Append("X-MICROSOFT-CDO-ALLDAYEVENT:"+ isAllDay.ToString().ToUpper()).Append("\r\n");
227             sb.Append("X-MICROSOFT-CDO-OWNERAPPTID:-611620904").Append("\r\n");
228             sb.Append("X-MICROSOFT-CDO-APPT-SEQUENCE:0").Append("\r\n");
229             //sb.Append("X-MICROSOFT-CDO-ATTENDEE-CRITICAL-CHANGE:").Append(DateTime.Now.ToUniversalTime().ToString(calDateFormat)).Append("\r\n");
230             //sb.Append("X-MICROSOFT-CDO-OWNER-CRITICAL-CHANGE:").Append(DateTime.Now.ToUniversalTime().ToString(calDateFormat)).Append("\r\n");
231             sb.Append("BEGIN:VALARM").Append("\r\n");
232             sb.Append("ACTION:DISPLAY").Append("\r\n");
233             sb.Append("DESCRIPTION:REMINDER").Append("\r\n");
234             sb.Append("TRIGGER;RELATED=START:-PT00H15M00S").Append("\r\n");
235             sb.Append("END:VALARM").Append("\r\n");
236 
237             sb.Append("END:VEVENT").Append("\r\n");
238             sb.Append("END:VCALENDAR").Append("\r\n");
239             return sb.ToString();
240         }
241 
242         static string GetRecurringParam(RecurType freq, bool isEndbyDate, DateTimeOffset endby, int endafterOccurences, RecurDaily dailyEntiy, RecurWeekly weeklyEntity, RecurMonthly monthlyEntiy, RecurYearly yearlyEntity)
243         {
244             if(freq!=RecurType.NoRecurrence)
245             {
246                 StringBuilder sb = new StringBuilder();
247                 if(freq==RecurType.DAILY)
248                 {
249                     sb.Append(GetDailyParam(dailyEntiy));
250                 }
251                 else if (freq == RecurType.WEEKLY)
252                 {
253                     sb.Append(GetWeeklyParam(weeklyEntity)); 
254                 }
255                 else if (freq == RecurType.MONTHLY)
256                 {
257                     sb.Append(GetMonthlyParam(monthlyEntiy)); 
258                 }
259                 else if (freq == RecurType.YEARLY)
260                 {
261                     sb.Append(GetYearlyParam(yearlyEntity));
262                 }
263 
264                 //end by datetime or count
265                 if(isEndbyDate)
266                 {
267                     string utcDateFormat = "yyyyMMddTHHmmssZ";
268                      sb.Append("UNTIL=").Append(endby.ToUniversalTime().ToString(utcDateFormat));// must be utc time
269                 }
270                 else
271                 {
272                     sb.Append("COUNT="+ endafterOccurences + ";");
273                 }
274                 if(sb[sb.Length-1]==';')
275                 {
276                     sb.Remove(sb.Length - 1, 1);
277                 }
278                return sb.ToString();
279             }
280             return "";
281 
282         }
283         static StringBuilder GetDailyParam(RecurDaily recurDaily)
284         {
285             StringBuilder sb = new StringBuilder();
286             sb.Append("RRULE:FREQ=DAILY;");
287             if (recurDaily.IsEveryWeekday == false)
288             {
289                 if (recurDaily.RecurIntervalDays <= 0)
290                 {
291                     throw new Exception("RecurIntervalDays must more than Zero");
292                 }
293                 sb.Append("INTERVAL=" + (recurDaily.RecurIntervalDays) + ";");
294             }
295             else
296             {
297                 sb.Append("BYDAY=MO,TU,WE,TH,FR;");
298             }
299             return sb;
300         }
301 
302         static StringBuilder GetWeeklyParam(RecurWeekly recurWeekly)
303         {
304             StringBuilder sb = new StringBuilder();
305             sb.Append("RRULE:FREQ=WEEKLY;");
306             if (recurWeekly.RecurIntervalWeeks > 0)
307                 sb.Append("INTERVAL=" + (recurWeekly.RecurIntervalWeeks) + ";");
308             sb.Append("BYDAY=");
309             List<string> listWeek = new List<string>();
310             if (recurWeekly.IsSunday)
311             {
312                 listWeek.Add("SU");
313             }
314             if (recurWeekly.IsMonday)
315             {
316                 listWeek.Add("MO");
317             }
318             if (recurWeekly.IsTuesday)
319             {
320                 listWeek.Add("TU");
321             }
322             if (recurWeekly.IsWednesday)
323             {
324                 listWeek.Add("WE");
325             }
326             if (recurWeekly.IsThursday)
327             {
328                 listWeek.Add("TH");
329             }
330             if (recurWeekly.IsFriday)
331             {
332                 listWeek.Add("FR");
333             }
334             if (recurWeekly.IsSaturday)
335             {
336                 listWeek.Add("SA");
337 
338             }
339             if (listWeek.Count == 0)
340             {
341                 throw new Exception("Must check one day of week");
342             }
343             sb.Append(string.Join(",", listWeek) + ";");
344             return sb;
345         }
346 
347         static StringBuilder GetMonthlyParam(RecurMonthly recurMonthly)
348         {
349             StringBuilder sb = new StringBuilder();
350             sb.Append("RRULE:FREQ=MONTHLY;");
351             if (recurMonthly.IsDayofEveryMonth)
352             {
353                 sb.Append("BYMONTHDAY=" + recurMonthly.DayOfMonth + ";");
354                 if (recurMonthly.RecurIntervalMonths > 1)
355                     sb.Append("INTERVAL=" + (recurMonthly.RecurIntervalMonths) + ";");
356             }
357             else
358             {
359                 if (recurMonthly.DayOfWeek == RecurDayOfWeek.Day || recurMonthly.DayOfWeek == RecurDayOfWeek.WeekDay || recurMonthly.DayOfWeek == RecurDayOfWeek.WeekEndDay)
360                 {
361                     sb.Append("BYDAY=" + GetDaysOfWeek(recurMonthly.DayOfWeek) + ";BYSETPOS=" + GetOrdinal(recurMonthly.RecurOrdinal) + ";");
362                 }
363                 else
364                 {
365                     string byday = GetOrdinal(recurMonthly.RecurOrdinal) + GetDaysOfWeek(recurMonthly.DayOfWeek);
366                     sb.Append("BYDAY=" + byday + ";");
367                 }
368 
369                 if (recurMonthly.RecurIntervalMonths > 0)
370                     sb.Append("INTERVAL=" + (recurMonthly.RecurIntervalMonths) + ";");
371 
372             }
373             return sb;
374         }
375 
376         static StringBuilder GetYearlyParam(RecurYearly recurYearly)
377         {
378             StringBuilder sb = new StringBuilder();
379             sb.Append("RRULE:FREQ=YEARLY;");
380             if (recurYearly.IsDayofMonth)
381             {
382                 sb.Append("BYMONTH=" + (int)recurYearly.RecurMonthDay + ";");
383                 sb.Append("BYMONTHDAY=" + recurYearly.DayOfMonth + ";");
384 
385             }
386             else
387             {
388                 if (recurYearly.DayOfWeek == RecurDayOfWeek.Day || recurYearly.DayOfWeek == RecurDayOfWeek.WeekDay || recurYearly.DayOfWeek == RecurDayOfWeek.WeekEndDay)
389                 {
390                     sb.Append("BYDAY=" + GetDaysOfWeek(recurYearly.DayOfWeek) + ";BYSETPOS=" + GetOrdinal(recurYearly.RecurOrdinal) + ";");
391                 }
392                 else
393                 {
394                     string byday = GetOrdinal(recurYearly.RecurOrdinal) + GetDaysOfWeek(recurYearly.DayOfWeek);
395                     sb.Append("BYDAY=" + byday + ";");
396                 }
397                 sb.Append("BYMONTH=" + (int)recurYearly.RecurMonthDay2 + ";");
398             }
399 
400             if (recurYearly.recurIntervalYears > 0)
401             {
402                 sb.Append("INTERVAL=" + (recurYearly.recurIntervalYears) + ";");
403             }
404             return sb;
405         }
406         static string GetOrdinal(RecurOrdinal ordinal)
407         {
408             string prexByday = "";
409             if (ordinal == RecurOrdinal.First)
410             {
411                 prexByday = "1";
412             }
413             else if (ordinal == RecurOrdinal.Second)
414             {
415                 prexByday = "2";
416             }
417             else if (ordinal == RecurOrdinal.Third)
418             {
419                 prexByday = "3";
420             }
421             else if (ordinal == RecurOrdinal.Fourth)
422             {
423                 prexByday = "4";
424             }
425             else if(ordinal==RecurOrdinal.Last)
426             {
427                 prexByday = "-1";
428             }
429             return prexByday;
430         }
431 
432         static string GetDaysOfWeek(RecurDayOfWeek dayofweek)
433         {
434             string suffixByday = "";
435             switch (dayofweek)
436             {
437                 case RecurDayOfWeek.Monday:
438                     suffixByday= "MO";
439                     break;
440                 case RecurDayOfWeek.Tuesday:
441                     suffixByday = "TU";
442                     break;
443                 case RecurDayOfWeek.Wednesday:
444                     suffixByday = "WE";
445                     break;
446                 case RecurDayOfWeek.Thursday:
447                     suffixByday = "TH";
448                     break;
449                 case RecurDayOfWeek.Friday:
450                     suffixByday = "FR";
451                     break;
452                 case RecurDayOfWeek.Saturday:
453                     suffixByday = "SA";
454                     break;
455                 case RecurDayOfWeek.Sunday:
456                     suffixByday = "SU";
457                     break;
458                 case RecurDayOfWeek.Day:
459                     suffixByday = "MO,TU,WE,TH,FR,SU,SA";
460                     break;
461                 case RecurDayOfWeek.WeekDay:
462                     suffixByday = "MO,TU,WE,TH,FR";
463                     break;
464                 case RecurDayOfWeek.WeekEndDay:
465                     suffixByday = "SA,SU";
466                     break;
467 
468             }
469             return suffixByday;
470         }
471 
472    private static string NotNull(string str)
473         {
474             return str ?? String.Empty;
475         }
476 
477 
478 
479     public class RecurDaily
480     {
481         public bool IsEveryWeekday { get; set; }
482         public int RecurIntervalDays { get; set; }
483         
484     }
485 
486     public class RecurWeekly
487     {
488         public int RecurIntervalWeeks { get; set; }
489         public bool IsSunday { get; set; }
490         public bool IsMonday { get; set; }
491         public bool IsTuesday { get; set; }
492         public bool IsWednesday { get; set; }
493         public bool IsThursday { get; set; }
494         public bool IsFriday { get; set; }
495         public bool IsSaturday { get; set; }
496 
497     }
498     public class RecurMonthly
499     {
500         public bool IsDayofEveryMonth { get; set; }
501         public int DayOfMonth { get; set; }
502         public int RecurIntervalMonths { get; set; }
503         public RecurOrdinal RecurOrdinal { get; set; }
504         public RecurDayOfWeek DayOfWeek { get; set; }
505 
506 
507     }
508     public class RecurYearly
509     {
510         public bool IsDayofMonth { get; set; }
511         public int recurIntervalYears { get; set; }
512         public RecurMonth RecurMonthDay { get; set; }
513         public int DayOfMonth{ get; set; }
514 
515         public RecurOrdinal RecurOrdinal { get; set; }
516         public RecurDayOfWeek DayOfWeek { get; set; }
517 
518         public RecurMonth RecurMonthDay2 { get; set; }
519 
520     }
521     public enum RecurOrdinal
522     {
523         First,
524         Second,
525         Third,
526         Fourth,
527         Last
528     }
529     public enum RecurDayOfWeek
530     {
531         //
532         // Summary:
533         //     Indicates Sunday.
534         Sunday = 0,
535         //
536         // Summary:
537         //     Indicates Monday.
538         Monday = 1,
539         //
540         // Summary:
541         //     Indicates Tuesday.
542         Tuesday = 2,
543         //
544         // Summary:
545         //     Indicates Wednesday.
546         Wednesday = 3,
547         //
548         // Summary:
549         //     Indicates Thursday.
550         Thursday = 4,
551         //
552         // Summary:
553         //     Indicates Friday.
554         Friday = 5,
555         //
556         // Summary:
557         //     Indicates Saturday.
558         Saturday = 6,
559 
560         Day=7,
561 
562         WeekDay=8,
563 
564         WeekEndDay=9
565     }
566     public enum RecurMonth
567     {
568 
569         January = 1,
570 
571         February = 2,
572 
573         March= 3,
574 
575         April= 4,
576 
577         May= 5,
578 
579         June= 6,
580 
581         July= 7,
582 
583         August= 8,
584 
585         September= 9,
586 
587         October= 10,
588 
589         November= 11,
590 
591         December= 12
592 
593     }
View Code

5.参考资料

Rfc5545规范

https://tools.ietf.org/html/rfc5545#ref-TZDB

 

Organizer在Outlook的Calendar看不到自己创建的event

https://stackoverflow.com/questions/15084236/icalendar-does-not-create-an-event-for-organizer/39535174#39535174

 

时区问题解决

https://stackoverflow.com/questions/7626114/ics-timezone-not-working

 

其它问题

https://stackoverflow.com/questions/461889/sending-outlook-meeting-requests-without-outlook/26194818#26194818

https://blog.csdn.net/hppgjx/article/details/77896101

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!