4 用SMTP 发送会议邀请
public ServiceWrapper SendInvitation(MMeetingInvitation model) { Log.WriteMsg($" OldModel:{new JavaScriptSerializer().Serialize(model)}"); var sw = new ServiceWrapper("SendMeetingInvitation"); InvitationMail im = new InvitationMail(); try { if (!string.IsNullOrEmpty(model.content)) model.content = model.content.Replace("\\n", "\n"); if (!string.IsNullOrEmpty(model.attendees)) model.attendees = model.attendees.Replace(",", ";"); string attendees; attendees = string.Join(";", (model.organizer + ";" + model.attendees).Split(';').Where(s => { return s.TrimEnd().TrimStart().Contains("@"); }).Distinct().ToArray()); if (string.IsNullOrEmpty(model.NoticeType)) { model.NoticeType = "invite"; } if (String.IsNullOrEmpty(model.MeetingGuid)) { model.MeetingGuid = Guid.NewGuid().ToString(); } im.Subject = model.subject; im.Content = model.content; im.StartTime = model.beginTime; im.EndTime = model.endTime; im.GUID = model.MeetingGuid; im.Location = model.location; im.MailRequiredAttendees = attendees; im.MailFrom = model.CreatedBy; im.Organizer = model.organizer; im.NoticeType = model.NoticeType; im.EmailTimeZone = model.TimeZone; MailMessage ms = im.GetMailMessageWithType(); sw = SendEmail(ms); sw.Data = model.MeetingGuid.ToString(); Log.WriteMsg($"Successful Model:{new JavaScriptSerializer().Serialize(im)}"); } catch (Exception e) { Log.WriteMsg(" /r/n SendInvitation catch Error Model Error Message:" + e.HResult + "|||||| Model:" + new JavaScriptSerializer().Serialize(model)); sw.ReturnCode = -1; sw.Message = "Error Message:" + e.Message; } return sw; }
InvitationMail
public class InvitationMail
{ private MailMessage Message { get; set; }public string Subject { get; set; }
public string Content { get; set; }
public string MailFrom { get; set; }
public string Organizer { get; set; }
/// <summary>
/// Mail-To split by ";" or "," /// </summary> public string MailRequiredAttendees { get; set; }/// <summary>
/// Mail-CC split by ";" or "," /// </summary> public string MailOptionalAttendees { get; set; }/// <summary>
/// Mail-BCC split by ";" or "," /// </summary> public string MailFYI { get; set; }/// <summary>
/// Time Zone GMT+8 /// </summary> public DateTime StartTime { get; set; } /// <summary> /// Time Zone GMT+8 /// </summary> public DateTime EndTime { get; set; } /// <summary> /// GUID for relation meetings /// </summary> public string GUID { get; set; } public string Location { get; set; }// add by joey 2015 -10-10 RESCHEDULE Cancel, INVITE,CONFIRM
public string NoticeType { get; set; }public double EmailTimeZone { get; set; }
public void AddAttachment(Attachment a)
{ Message.Attachments.Add(a); }public void RemoveAttachment(Attachment a)
{ Message.Attachments.Remove(a); } /// <summary> /// Init MailMessage object, init appcode organization etc. /// </summary> public InvitationMail() { Message = new MailMessage();string appCodeToSkipDisclaimer = "PCD";
string appCodeToSkipDisclaimerTagName = "Request-To-Skip-Disclaimer"; System.Collections.Generic.List<string> appCodeToSkipDisclaimerArray;string[] disclaimerArray = appCodeToSkipDisclaimer.ToLower().Split(new char[] { ';' });
appCodeToSkipDisclaimerArray = new System.Collections.Generic.List<string>(disclaimerArray);//Header
string headerValue = "PWCHK-0000000000-PWCHK"; string appcode = "MyRiskMonitor20"; if (appCodeToSkipDisclaimerArray.Count > 0 && appCodeToSkipDisclaimerArray.Contains(appcode)) Message.Headers.Add(appCodeToSkipDisclaimerTagName, headerValue);Message.Headers.Add("Organization", "PricewaterhouseCoopers");
} /// <summary> /// Get generated MailMessage object /// </summary> /// <returns></returns> public MailMessage GetMailMessage() { //Subject Message.Subject = Subject; Message.SubjectEncoding = System.Text.Encoding.UTF8; // Add by Sam Wang 2011-06-27, resolve subject display in iPhone. Version: 1.0.1.110627.0 Message.Body = Content; Message.BodyEncoding = System.Text.Encoding.UTF8;//Format HTML or Text
if (Content != null && Content.ToLower().IndexOf("<html>") >= 0) Message.IsBodyHtml = true; else Message.IsBodyHtml = false;Message.From = EmailAddressFormatterWithString(MailFrom);
EmailAddressFormatter(Message.To, MailRequiredAttendees); if (MailOptionalAttendees != null) EmailAddressFormatter(Message.CC, MailOptionalAttendees); if (MailFYI != null) EmailAddressFormatter(Message.Bcc, MailFYI);string meetingInfo;
InvitationBuilder m = new InvitationBuilder(
StartTime, EndTime, MailRequiredAttendees.Split(';'), (MailOptionalAttendees != null) ? MailOptionalAttendees.Split(';') : null, EmailAddressFormatterWithString(MailFrom).ToString(), Subject, Content, GUID, Location);meetingInfo = m.ToString();
#if DEBUG
Console.WriteLine("----------------Building ics file---------------------"); Console.WriteLine(meetingInfo);#endif//create AlternateView
AlternateView icsView = AlternateView.CreateAlternateViewFromString( meetingInfo, new System.Net.Mime.ContentType("text/calendar; method=REQUEST") );Message.AlternateViews.Add(icsView);
return Message;
}/// <summary>
/// add by joey 2015-10-10 /// </summary> /// <returns></returns> public MailMessage GetMailMessageWithType() { //Subject Message.Subject = Subject; Message.SubjectEncoding = System.Text.Encoding.UTF8; Message.Body = Content; Message.IsBodyHtml = true; Message.BodyEncoding = System.Text.Encoding.UTF8; Message.From = EmailAddressFormatterWithString(MailFrom); EmailAddressFormatter(Message.To, MailRequiredAttendees); if (MailOptionalAttendees != null) EmailAddressFormatter(Message.CC, MailOptionalAttendees); if (MailFYI != null) EmailAddressFormatter(Message.Bcc, MailFYI);string meetingInfo;
InvitationBuilder m = new InvitationBuilder(
StartTime, EndTime, MailRequiredAttendees.Split(';'), (MailOptionalAttendees != null) ? MailOptionalAttendees.Split(';') : null, Message.From.ToString(), Subject, Content, GUID, Location, NoticeType, EmailTimeZone ); meetingInfo = m.ToStringWithType();
System.Net.Mime.ContentType contypehtml = new System.Net.Mime.ContentType("text/html");
contypehtml.Parameters.Add("charset", "UTF-8"); System.Net.Mail.AlternateView avCalhtml = System.Net.Mail.AlternateView.CreateAlternateViewFromString(Content, contypehtml);Message.AlternateViews.Add(avCalhtml);
System.Net.Mime.ContentType calendarType = new System.Net.Mime.ContentType("text/calendar");
calendarType.Parameters.Add("method", "REQUEST"); calendarType.Parameters.Add("name", "meeting.ics");AlternateView icsView = AlternateView.CreateAlternateViewFromString(meetingInfo, calendarType);
Message.AlternateViews.Add(icsView); return Message; }/// <summary>
/// return MailAddressCollection type of object to add to related field /// </summary> /// <param name="emailAddr"></param> /// <returns></returns> private MailAddress EmailAddressFormatterWithString(string emailAddr) { emailAddr = emailAddr.Replace(" ", "_"); string[] arr_email = emailAddr.Split(";,".ToCharArray());for (int i = 0; i < arr_email.Length; i++)
{if (arr_email[i].IndexOf("@") < 0)
return new MailAddress(arr_email[i] + "@Asia"); else return new MailAddress(arr_email[i]); } return null; } /// <summary> /// new method to return MailAddressCollection type of object to add to related field /// </summary> /// <param name="emailAddr"></param> /// <returns></returns> private void EmailAddressFormatter(MailAddressCollection target, string emailAddr) { emailAddr = emailAddr.Replace(" ", "_"); string[] arr_email = emailAddr.Split(";,".ToCharArray());for (int i = 0; i < arr_email.Length; i++)
{if (arr_email[i].IndexOf("@") < 0)
target.Add(new MailAddress(arr_email[i] + "@Asia")); else target.Add(new MailAddress(arr_email[i]));}
} }InvitationBuilder
public class InvitationBuilder { ////// Current Time Zone /// public DateTime StartTime { get; set; } ////// Current Time Zone /// public DateTime EndTime { get; set; } public string[] Attendees { get; set; } public string[] OptionalAttendees { get; set; } public string Organizer { get; set; } public string Subject { get; set; } public string Description { get; set; } ////// GUID for relation meetings /// public string Guid { get; set; } public string Location { get; set; } // add by joey 2015 -10-10 RESCHEDULE Cancel, INVITE,CONFIRM public string NoticeType { get; set; } public double EmailTimezone { get; set; } public string TZID { get; set; } ////// Disabled default structrue method /// private InvitationBuilder() { } ////// Structure of Invitation /// /// Current Time Zone /// Current Time Zone /// /// /// /// /// GUID for relation meetings /// public InvitationBuilder(DateTime startTime, DateTime endTime, string[] attendees, string organizer, string subject, string description, string guid, string location) { StartTime = startTime; EndTime = endTime; Attendees = attendees; Organizer = organizer; Subject = subject; Description = description; Guid = guid; Location = location; } ////// Structure of Invitation With OptionalAtendees /// /// Current Time Zone /// Current Time Zone /// /// /// /// /// GUID for relation meetings /// public InvitationBuilder(DateTime startTime, DateTime endTime, string[] attendees, string[] optionalAttendees, string organizer, string subject, string description, string guid, string location) { StartTime = startTime; EndTime = endTime; Attendees = attendees; Organizer = organizer; OptionalAttendees = optionalAttendees; Subject = subject; Description = description; Guid = guid; Location = location; } ////// Structure of Invitation With OptionalAtendees and with Noticetype /// /// Current Time Zone /// Current Time Zone /// /// /// /// /// GUID for relation meetings /// public InvitationBuilder(DateTime startTime, DateTime endTime, string[] attendees, string[] optionalAttendees, string organizer, string subject, string description, string guid, string location, string noticeType,double emailtimezone) { StartTime = startTime; EndTime = endTime; Attendees = attendees; Organizer = organizer; OptionalAttendees = optionalAttendees; Subject = subject; Description = description; Guid = guid; Location = location; NoticeType = noticeType; EmailTimezone = emailtimezone; } public virtual bool SaveToFile(string path) { try { FileStream fs = new FileStream(path, FileMode.Create); byte[] data = System.Text.Encoding.Default.GetBytes(ToString()); fs.Write(data, 0, data.Length); fs.Flush(); fs.Close(); return true; } catch { return false; } } private string GenerateCalendarICS( string calendarid, DateTime starttime, DateTime endtime, string location, MailAddressCollection mto, MailAddressCollection mcc, string subject, string content, string mfrom, int sequence, string noticeType) { StringBuilder sw = new StringBuilder(); sw.AppendLine("BEGIN:VCALENDAR"); sw.AppendLine("VERSION:2.0"); if (noticeType.ToUpper() != "CANCEL") { sw.AppendLine("METHOD:REQUEST"); } else { sw.AppendLine("METHOD:CANCEL"); } //time zone GMT+8 sw.AppendLine("BEGIN:VTIMEZONE"); sw.AppendLine("TZID:China"); sw.AppendLine("BEGIN:STANDARD"); sw.AppendLine("DTSTART:19500101T020000"); sw.AppendLine("TZOFFSETFROM:+0800"); sw.AppendLine("TZOFFSETTO:+0800"); sw.AppendLine("END:STANDARD"); sw.AppendLine("END:VTIMEZONE"); //end time zone sw.AppendLine("BEGIN:VEVENT"); //To foreach (MailAddress item in mto) { sw.AppendLine("ATTENDEE;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:" + item.Address.Trim()); } //CC foreach (MailAddress item in mcc) { sw.AppendLine("ATTENDEE;ROLE=OPT-PARTICIPANT;RSVP=TRUE:mailto:" + item.Address.Trim()); } sw.AppendLine("CLASS:PUBLIC"); sw.AppendLine(string.Format("CREATED:{0:yyyyMMddTHHmmssZ}", DateTime.UtcNow)); sw.AppendLine("DESCRIPTION:" + content); sw.AppendLine(string.Format("DTEND;TZID=\"China\":{0:yyyyMMddTHHmmss}", endtime));//attention: NO "Z" in the end of String sw.AppendLine(string.Format("DTSTAMP:{0:yyyyMMddTHHmmssZ}", DateTime.UtcNow)); sw.AppendLine(string.Format("DTSTART;TZID=\"China\":{0:yyyyMMddTHHmmss}", starttime));//attention: NO "Z" in the end of String //sw.AppendLine("ORGANIZER;CN=\"NAME\":mailto:" + mfrom); sw.AppendLine("SEQUENCE:" + sequence); sw.AppendLine("UID:" + calendarid.ToString()); sw.AppendLine("LOCATION:" + location); sw.AppendLine("SUMMARY;LANGUAGE=en-us:" + subject); sw.AppendLine("BEGIN:VALARM"); sw.AppendLine("TRIGGER:-PT15M"); sw.AppendLine("ACTION:DISPLAY"); sw.AppendLine("DESCRIPTION:Reminder"); sw.AppendLine("END:VALARM"); sw.AppendLine("X-LOTUS-BROADCAST:FALSE"); sw.AppendLine("X-LOTUS-UPDATE-SEQ:" + (sequence + 1).ToString()); sw.AppendLine("X-LOTUS-NOTESVERSION:2"); switch (noticeType.ToUpper()) { case "RESCHEDULE": sw.AppendLine("X-LOTUS-NOTICETYPE:U"); break; case "CONFIRM": sw.AppendLine("X-LOTUS-NOTICETYPE:N"); sw.AppendLine("X-LOTUS-CONFIRM:TRUE"); break; case "CANCEL": sw.AppendLine("STATUS:CANCELLED"); sw.AppendLine("X-LOTUS-NOTICETYPE:C"); break; default://include "INVITE" and others sw.AppendLine("X-LOTUS-NOTICETYPE:I"); break; } sw.AppendLine("X-LOTUS-APPTTYPE:3"); sw.AppendLine("X-LOTUS-CHILD-UID:" + calendarid.ToString()); //sw.AppendLine("X-LOTUS-UPDATE-WISL:$S:1;$L:1;$B:1;$R:1;$E:1;$W:1;$O:1;$M:1;RequiredAttendees:1;INetRequiredNames:1;AltRequiredNames:1;StorageRequiredNames:1;OptionalAttendees:1;INetOptionalNames:1;AltOptionalNames:1;StorageOptionalNames:1"); sw.AppendLine("END:VEVENT"); sw.AppendLine("END:VCALENDAR"); return sw.ToString(); } ////// add by joey 2015-10-10 /// /// /// /// /// /// /// /// /// /// /// /// ///public string ToStringWithType() { StringBuilder sw = new StringBuilder(); sw.AppendLine("BEGIN:VCALENDAR"); sw.AppendLine("VERSION:2.0"); if (NoticeType.ToUpper() != "CANCEL") { sw.AppendLine("METHOD:REQUEST"); } else { sw.AppendLine("METHOD:CANCEL"); } //time zone GMT+8 sw.AppendLine("BEGIN:VTIMEZONE"); sw.AppendLine("TZID:"+ SendMeetingHelp.TZIDHelp(EmailTimezone)); sw.AppendLine("BEGIN:STANDARD"); sw.AppendLine("DTSTART:19500101T020000"); TZID = SendMeetingHelp.TimeZoneHelp(EmailTimezone); sw.AppendLine("TZOFFSETFROM:"+ TZID);// + SendMeetingHelp.TimeZoneHelp(EmailTimezone) ); sw.AppendLine("TZOFFSETTO:"+ TZID);// + SendMeetingHelp.TimeZoneHelp(EmailTimezone)); sw.AppendLine("END:STANDARD"); sw.AppendLine("END:VTIMEZONE"); //end time zone sw.AppendLine("BEGIN:VEVENT"); //To if (Attendees != null) { foreach (string attendee in Attendees) { sw.AppendLine("ATTENDEE;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:" + attendee); } } //CC if (OptionalAttendees != null) { foreach (string optAttendee in OptionalAttendees) { sw.AppendLine("ATTENDEE;ROLE=OPT-PARTICIPANT;RSVP=TRUE:mailto:" + optAttendee); } } sw.AppendLine("CLASS:PUBLIC"); sw.AppendLine(string.Format("CREATED:{0:yyyyMMddTHHmmssZ}", DateTime.UtcNow)); if(!string.IsNullOrEmpty(Description)) sw.AppendLine("DESCRIPTION:" + Description.Replace("\n","\\n")); else sw.AppendLine("DESCRIPTION:"); sw.AppendLine(string.Format("DTEND;TZID=\"{0}\":{1:yyyyMMddTHHmmss}", SendMeetingHelp.TZIDHelp(EmailTimezone), EndTime));//attention: NO "Z" in the end of String sw.AppendLine(string.Format("DTSTAMP:{0:yyyyMMddTHHmmssZ}", DateTime.UtcNow)); sw.AppendLine(string.Format("DTSTART;TZID=\"{0}\":{1:yyyyMMddTHHmmss}",SendMeetingHelp.TZIDHelp(EmailTimezone), StartTime));//attention: NO "Z" in the end of String //sw.AppendLine("ORGANIZER;CN=\"NAME\":mailto:" + mfrom); sw.AppendLine("SEQUENCE:0"); sw.AppendLine("UID:" + Guid); sw.AppendLine("LOCATION:" + Location); sw.AppendLine("SUMMARY;LANGUAGE=en-us:" + Subject); sw.AppendLine("BEGIN:VALARM"); sw.AppendLine("TRIGGER:-PT15M"); sw.AppendLine("ACTION:DISPLAY"); sw.AppendLine("DESCRIPTION:Reminder"); sw.AppendLine("END:VALARM"); sw.AppendLine("X-LOTUS-BROADCAST:FALSE"); //sw.AppendLine("X-LOTUS-UPDATE-SEQ:" + (2).ToString()); sw.AppendLine("X-LOTUS-NOTESVERSION:2"); switch (NoticeType.ToUpper()) { case "RESCHEDULE": sw.AppendLine("X-LOTUS-NOTICETYPE:U"); break; case "CONFIRM": sw.AppendLine("X-LOTUS-NOTICETYPE:N"); sw.AppendLine("X-LOTUS-CONFIRM:TRUE"); break; case "CANCEL": sw.AppendLine("STATUS:CANCELLED"); sw.AppendLine("X-LOTUS-NOTICETYPE:C"); break; case "UPDATE": sw.AppendLine("X-LOTUS-NOTICETYPE:E"); break; default://include "INVITE" and others sw.AppendLine("X-LOTUS-NOTICETYPE:I"); break; } sw.AppendLine("X-LOTUS-APPTTYPE:3"); sw.AppendLine("X-LOTUS-CHILD-UID:" + Guid.ToString()); //sw.AppendLine("X-LOTUS-UPDATE-WISL:$S:1;$L:1;$B:1;$R:1;$E:1;$W:1;$O:1;$M:1;RequiredAttendees:1;INetRequiredNames:1;AltRequiredNames:1;StorageRequiredNames:1;OptionalAttendees:1;INetOptionalNames:1;AltOptionalNames:1;StorageOptionalNames:1"); sw.AppendLine("END:VEVENT"); sw.AppendLine("END:VCALENDAR"); return sw.ToString(); } public override string ToString() { StringBuilder sw = new StringBuilder(); sw.AppendLine("BEGIN:VCALENDAR"); sw.AppendLine("VERSION:2.0"); //sw.AppendLine("METHOD:CANCEL"); sw.AppendLine("METHOD:REQUEST"); //time zone GMT+8 sw.AppendLine("BEGIN:VTIMEZONE"); sw.AppendLine("TZID:China"); sw.AppendLine("BEGIN:STANDARD"); sw.AppendLine("DTSTART:19500101T020000"); sw.AppendLine("TZOFFSETFROM:+0800"); sw.AppendLine("TZOFFSETTO:+0800"); sw.AppendLine("END:STANDARD"); sw.AppendLine("END:VTIMEZONE"); //end time zone sw.AppendLine("BEGIN:VEVENT"); //To if (Attendees != null) { foreach (string attendee in Attendees) { sw.AppendLine("ATTENDEE;ROLE=REQ-PARTICIPANT;RSVP=TRUE:mailto:" + attendee); } } //CC if (OptionalAttendees != null) { foreach (string optAttendee in OptionalAttendees) { sw.AppendLine("ATTENDEE;ROLE=OPT-PARTICIPANT;RSVP=TRUE:mailto:" + optAttendee); } } sw.AppendLine("CLASS:PUBLIC"); sw.AppendLine(string.Format("CREATED:{0:yyyyMMddTHHmmssZ}", DateTime.UtcNow)); sw.AppendLine("DESCRIPTION:" + Description); sw.AppendLine(string.Format("DTEND;TZID=\"China\":{0:yyyyMMddTHHmmss}", EndTime));//attention: NO "Z" in the end of String sw.AppendLine(string.Format("DTSTAMP:{0:yyyyMMddTHHmmssZ}", DateTime.UtcNow)); sw.AppendLine(string.Format("DTSTART;TZID=\"China\":{0:yyyyMMddTHHmmss}", StartTime));//attention: NO "Z" in the end of String //sw.AppendLine("ORGANIZER;CN=\"NAME\":mailto:" + Organizer); sw.AppendLine("SEQUENCE:0"); sw.AppendLine("UID:" + Guid); sw.AppendLine("LOCATION:" + Location); sw.AppendLine("SUMMARY;LANGUAGE=en-us:" + Subject); sw.AppendLine("BEGIN:VALARM"); sw.AppendLine("TRIGGER:-PT15M"); sw.AppendLine("ACTION:DISPLAY"); sw.AppendLine("DESCRIPTION:Reminder"); sw.AppendLine("END:VALARM"); //sw.AppendLine("STATUS:CANCELLED"); sw.AppendLine("END:VEVENT"); sw.AppendLine("X-LOTUS-BROADCAST:FALSE"); sw.AppendLine("X-LOTUS-UPDATE-SEQ:1"); sw.AppendLine("X-LOTUS-NOTESVERSION:2"); sw.AppendLine("X-LOTUS-NOTICETYPE:I"); sw.AppendLine("X-LOTUS-APPTTYPE:3"); sw.AppendLine("X-LOTUS-CHILD-UID:" + Guid); //sw.AppendLine("X-LOTUS-UPDATE-WISL:$S:1;$L:1;$B:1;$R:1;$E:1;$W:1;$O:1;$M:1;RequiredAttendees:1;INetRequiredNames:1;AltRequiredNames:1;StorageRequiredNames:1;OptionalAttendees:1;INetOptionalNames:1;AltOptionalNames:1;StorageOptionalNames:1"); sw.AppendLine("END:VCALENDAR"); return sw.ToString(); } }