public static async Task SendNewCourseParticipantNotificationsAsync(IEnumerable <CourseParticipant> courseParticipants, MedSimDbContext repo, IPrincipal principal) { //logic: //get all courses hapening after now where the currentUser is not an organiser, and group by each organiser var currentUser = repo.Users.Include("Department").Include("ProfessionalRole").Single(u => u.UserName == principal.Identity.Name); var courseIds = courseParticipants.ToHashSet(cp => cp.CourseId); var organisers = repo.CourseParticipants.Include("Course.CourseFormat.CourseType") .Include("Participant.Department.Institution") .Include("Course.Department.Institution.Culture") .Where(cp => courseIds.Contains(cp.CourseId) && cp.IsOrganiser && !cp.Course.CourseParticipants.Any(ap => ap.IsOrganiser && ap.ParticipantId == currentUser.Id)) .ToLookup(cp => cp.Participant); using (var client = new ParallelSmtpEmails()) { foreach (var o in organisers) { var n = new MultiCourseInviteResonse { Courses = o.Select(cp => cp.Course), PersonResponding = currentUser }; var mail = new MailMessage(); mail.To.AddParticipants(o.Key); mail.CreateHtmlBody(n); client.Send(mail); } await client.SendingComplete(); } }
/// <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() }); }
public static async Task <EmailResult <CourseFacultyInvite> > SendMultiInvites(ICollection <Guid> courseIds, ICollection <Guid> participantIds, IPrincipal currentPrincipal, MedSimDbContext repo) { var existing = await repo.CourseFacultyInvites.Where(cfi => courseIds.Contains(cfi.CourseId) && participantIds.Contains(cfi.ParticipantId)) .ToHashSetAsync(cfi => Tuple.Create(cfi.CourseId, cfi.ParticipantId)); existing.UnionWith((await repo.CourseParticipants .Where(cp => courseIds.Contains(cp.CourseId) && participantIds.Contains(cp.ParticipantId)).ToListAsync()) .Select(cfi => Tuple.Create(cfi.CourseId, cfi.ParticipantId))); var allInvites = new List <CourseFacultyInvite>(courseIds.Count * participantIds.Count - existing.Count); foreach (var c in courseIds) { foreach (var p in participantIds) { if (!existing.Contains(Tuple.Create(c, p))) { allInvites.Add(new CourseFacultyInvite { CourseId = c, ParticipantId = p }); } } } var success = new ConcurrentBag <CourseFacultyInvite>(); var fail = new ConcurrentBag <CourseFacultyInvite>(); var allCourseIds = allInvites.ToHashSet(i => i.CourseId); var courses = await repo.Courses.Include("CourseFormat.CourseType").Where(c => allCourseIds.Contains(c.Id)).ToDictionaryAsync(u => u.Id); var allInvitees = allInvites.ToLookup(i => i.ParticipantId); var allInviteeIds = allInvitees.Select(i => i.Key); var userRepo = (DbSet <Participant>)repo.Users; var users = await userRepo.Include("Department.Institution.Culture").Where(p => allInviteeIds.Contains(p.Id)).ToDictionaryAsync(u => u.Id); var currentUser = await userRepo.Include("Department").Include("ProfessionalRole") .SingleAsync(u => u.UserName == currentPrincipal.Identity.Name); using (var parallelEmails = new ParallelSmtpEmails()) { foreach (var g in allInvitees) { var mail = new MailMessage(); var recipient = users[g.Key]; mail.To.AddParticipants(recipient); var requestEmail = new MultiCourseInvite { PersonRequesting = currentUser, Courses = g.Select(c => courses[c.CourseId]), Recipient = recipient }; mail.CreateHtmlBody(requestEmail); parallelEmails.Send(mail, s => { if (s == null) { foreach (var ci in g) { success.Add(ci); } } else { foreach (var ci in g) { fail.Add(ci); } } }); } await parallelEmails.SendingComplete(); } return(new EmailResult <CourseFacultyInvite> { SuccessRecipients = success.ToArray(), FailRecipients = fail.ToArray() }); }