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 { /// <summary> /// Current Time Zone /// </summary> public DateTime StartTime { get; set; } /// <summary> /// Current Time Zone /// </summary> 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; } /// <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 string TZID { get; set; } /// <summary> /// Disabled default structrue method /// </summary> private InvitationBuilder() { } /// <summary> /// Structure of Invitation /// </summary> /// <param name="startTime">Current Time Zone</param> /// <param name="endTime">Current Time Zone</param> /// <param name="attendees"></param> /// <param name="organizer"></param> /// <param name="subject"></param> /// <param name="description"></param> /// <param name="guid">GUID for relation meetings</param> /// <param name="location"></param> 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; } /// <summary> /// Structure of Invitation With OptionalAtendees /// </summary> /// <param name="startTime">Current Time Zone</param> /// <param name="endTime">Current Time Zone</param> /// <param name="attendees"></param> /// <param name="organizer"></param> /// <param name="subject"></param> /// <param name="description"></param> /// <param name="guid">GUID for relation meetings</param> /// <param name="location"></param> 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; } /// <summary> /// Structure of Invitation With OptionalAtendees and with Noticetype /// </summary> /// <param name="startTime">Current Time Zone</param> /// <param name="endTime">Current Time Zone</param> /// <param name="attendees"></param> /// <param name="organizer"></param> /// <param name="subject"></param> /// <param name="description"></param> /// <param name="guid">GUID for relation meetings</param> /// <param name="location"></param> 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(); } /// <summary> /// add by joey 2015-10-10 /// </summary> /// <param name="calendarid"></param> /// <param name="starttime"></param> /// <param name="endtime"></param> /// <param name="location"></param> /// <param name="mto"></param> /// <param name="mcc"></param> /// <param name="subject"></param> /// <param name="content"></param> /// <param name="mfrom"></param> /// <param name="sequence"></param> /// <param name="noticeType"></param> /// <returns></returns> 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(); } }