/// <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);
                    }
                }
            }
        }
Example #2
0
        /// <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()
            });
        }