/// <summary> /// /// </summary> /// <param name="course"></param> /// <param name="user"></param> /// <returns>a lookup true = successfully emailed, false = email failed</returns> public static async Task<ILookup<bool, CourseParticipant>> SendEmail(Course course, IPrincipal user) { using (var cal = Appointment.CreateCourseAppointment(course, user.Identity)) { using (var appt = new AppointmentStream(cal)) { var map = ((Expression<Func<CourseParticipant, CourseParticipantDto>>)new CourseParticipantMaps().MapToDto).Compile(); var faculty = course.CourseParticipants.Where(cp => !map(cp).IsEmailed) .ToLookup(cp => cp.IsFaculty); IEnumerable<Attachment> attachments = new Attachment[0]; using (var client = new SmtpClient()) { var mailMessages = new List<ParticipantMail>(); var sendMail = new Action<CourseParticipant>(cp => { var mail = new MailMessage(); mail.To.AddParticipants(cp.Participant); var confirmEmail = new CourseInvite { CourseParticipant = cp }; mail.CreateHtmlBody(confirmEmail); appt.AddAppointmentsTo(mail); foreach (var a in attachments) { a.ContentStream.Position = 0; mail.Attachments.Add(a); } mailMessages.Add(new ParticipantMail { Message = mail, SendTask = client.SendMailAsync(mail), CourseParticipant = cp }); }); foreach (var cp in faculty[false]) { sendMail(cp); } if (faculty[true].Any()) { if (course.FacultyMeetingUtc.HasValue) { using (var fm = Appointment.CreateFacultyCalendar(course)) { appt.Add(fm); } } attachments = GetFilePaths(course).Select(fp => new Attachment(fp.Value, System.Net.Mime.MediaTypeNames.Application.Zip) { Name = fp.Key }) .Concat(new[] { new Attachment(CreateDocxTimetable.CreateTimetableDocx(course, WebApiConfig.DefaultTimetableTemplatePath), OpenXmlDocxExtensions.DocxMimeType) { Name = CreateDocxTimetable.TimetableName(course)} }); foreach (var cp in faculty[true]) { sendMail(cp); } } await Task.WhenAll(mailMessages.Select(mm => mm.SendTask)); mailMessages.ForEach(mm => mm.Message.Dispose()); return mailMessages.ToLookup(k => k.SendTask.Status == TaskStatus.RanToCompletion, v => v.CourseParticipant); } } } }
/// <summary> /// /// </summary> /// <param name="course"></param> /// <returns>a lookup true = successfully emailed, false = email failed</returns> public static async Task <EmailResult <CourseParticipant> > SendCourseEmail(Course course, ApplicationUserManager userManager, DateTime?originalDate = null) { var map = ((Expression <Func <CourseParticipant, CourseParticipantDto> >) new CourseParticipantMaps().MapToDto).Compile(); var faculty = course.CourseParticipants.Where(cp => map(cp).IsEmailed == originalDate.HasValue) .ToLookup(cp => cp.IsFaculty); var attachments = new List <Attachment>(); string timetableName = CreateDocxTimetable.TimetableName(course); var participantTimetable = CreateDocxTimetable.CreateTimetableDocx(course, WebApiConfig.DefaultTimetableTemplatePath, false); if (course.CourseFormat.CourseType.SendCandidateTimetable) { attachments.Add(new Attachment(Stream.Synchronized(participantTimetable), OpenXmlDocxExtensions.DocxMimeType) { Name = timetableName }); } attachments.AddRange(GetInviteReadings(course)); var success = new ConcurrentBag <CourseParticipant>(); var fail = new ConcurrentBag <CourseParticipant>(); using (var parallelEmails = new ParallelSmtpEmails(disposeMsgOnComplete: false)) { List <MailMessage> messages = new List <MailMessage>(course.CourseParticipants.Count); var sendMail = new Func <CourseParticipant, Task>(async cp => { var mail = new MailMessage(); messages.Add(mail); mail.To.AddParticipants(cp.Participant); string token = await userManager.GenerateUserTokenAsync(InvitePurpose(cp.CourseId), cp.ParticipantId); var confirmEmail = new CourseInvite { CourseParticipant = cp, OldStart = originalDate, Token = token }; mail.CreateHtmlBody(confirmEmail); foreach (var a in attachments) { //a.ContentStream.Position = 0; mail.Attachments.Add(a); } parallelEmails.Send(mail, s => { if (s == null) { success.Add(cp); } else { fail.Add(cp); } }); }); foreach (var f in faculty[false]) { await sendMail(f); } MemoryStream facultyTimetable = null; if (faculty[true].Any()) { attachments = new List <Attachment>(); facultyTimetable = CreateDocxTimetable.CreateTimetableDocx(course, WebApiConfig.DefaultTimetableTemplatePath, true); attachments.Add(new Attachment(Stream.Synchronized(facultyTimetable), OpenXmlDocxExtensions.DocxMimeType) { Name = timetableName }); attachments.AddRange(GetFilePaths(course) .Select(fp => new Attachment(Stream.Synchronized(fp.Value.ToStream()), System.Net.Mime.MediaTypeNames.Application.Zip) { Name = fp.Key })); foreach (var f in faculty[true]) { await sendMail(f); } } await parallelEmails.SendingComplete(); messages.ForEach(m => m.Dispose()); participantTimetable.Dispose(); facultyTimetable?.Dispose(); } return(new EmailResult <CourseParticipant> { SuccessRecipients = success.ToArray(), FailRecipients = fail.ToArray() }); }