public static void CreateTestDataForAnmeldung(ApplicationDbContext context, DateTime now) { context.Anmeldung.RemoveRange(context.Anmeldung); context.Schulung.RemoveRange(context.Schulung); context.SaveChanges(); // Kann sich anmelden context.Add(HelpCreateSchulung("Test 0", "00000000-0000-0000-0000-000000000000", now.AddDays(1))); // Kann sich nicht anmelden, da schon angemeldet context.Add(HelpCreateSchulung("Test 1", "00000000-0000-0000-0000-000000000001", now.AddDays(1))); context.Add(new Anmeldung { Email = "*****@*****.**", Nachname = "something", Vorname = "completely", Nummer = "different", SchulungGuid = "00000000-0000-0000-0000-000000000001", Status = "Mitglied" }); // nicht angezeigt, kann nicht anmelden da anmeldefrist abgelaufen context.Add(HelpCreateSchulung("Test 2", "00000000-0000-0000-0000-000000000002", now.AddDays(-1))); // nicht angezeigt, kann nicht anmelden, da abgesagt Schulung abgesagt = HelpCreateSchulung("Test 3", "00000000-0000-0000-0000-000000000003", now.AddDays(1)); abgesagt.IsAbgesagt = true; context.Add(abgesagt); // Kann sich anmelden context.Add(HelpCreateSchulung("Test 4", "00000000-0000-0000-0000-000000000004", now.AddDays(1))); // Kann sich anmelden context.Add(HelpCreateSchulung("Test 5", "00000000-0000-0000-0000-000000000005", now.AddDays(1))); context.SaveChanges(); }
public async Task <ActionResult> Geprueft(string schulungGuid) { // TODO: test try { if (schulungGuid == null) { return(new StatusCodeResult(400)); } Schulung schulung = await _schulungRepository.GetByIdAsync(schulungGuid); if (schulung == null) { return(NotFound("Schulung mit angegebener ID nicht gefunden!")); } if (schulung.IsAbgesagt) { return(RedirectToAction("Uebersicht")); } if (schulung.IsGeprüft) { return(RedirectToAction("Uebersicht")); } return(View("Geprueft", schulung)); } catch (Exception e) { logger.Error(e); string code = "#213"; e = new Exception("Fehler beim Erstellen der View " + code, e); return(View("Error", e)); } }
public async Task <ActionResult> Nachtragen(string schulungGuid) { // TODO: test, valid id, invalid id try { if (schulungGuid == null) { return(StatusCode(400)); } Schulung schulung = await _schulungRepository.GetByIdAsync(schulungGuid); if (schulung == null) { return(StatusCode(404, "Schulung mit angegebener ID nicht gefunden!")); } AnmeldungNachtragenViewModel anmeldung = new AnmeldungNachtragenViewModel(); anmeldung.SchulungGuid = schulungGuid; anmeldung.SchulungTitel = schulung.Titel; return(View("Nachtragen", anmeldung)); } catch (Exception e) { logger.Error(e); string code = "#305"; e = new Exception("Fehler beim Erstellen der View " + code, e); return(View("Error", e)); } }
public async Task <ActionResult> AbsagenBestaetigt(Schulung schulung, string schulungGuid) { // TODO: test try { schulung = await _schulungRepository.GetByIdAsync(schulung.SchulungGUID); if (schulung == null) { return(NotFound("Schulung mit angegebener ID nicht gefunden!")); } schulung.IsAbgesagt = true; await _schulungRepository.UpdateAsync(schulung); IEnumerable <Anmeldung> Anmeldungen = _anmeldungRepository.GetBySchulungGuid(schulung.SchulungGUID); string vorstand = Util.getVorstand(_context); foreach (Anmeldung anmeldung in Anmeldungen) { mailingHelper.GenerateAndSendAbsageMailAsync(anmeldung, schulung, vorstand); } return(RedirectToAction("Uebersicht")); } catch (Exception e) { logger.Error(e); string code = "#210"; e = new Exception("Fehler beim Verarbeiten des Inputs " + code, e); return(View("Error", e)); } }
public async Task <ActionResult> Details(string schulungGuid) { // TODO: test try { if (schulungGuid == null) { return(new StatusCodeResult(400)); } Schulung schulung = await _schulungRepository.GetByIdAsync(schulungGuid); if (schulung == null) { return(NotFound("Schulung mit angegebener ID nicht gefunden!")); } else { return(View("Details", schulung)); } } catch (Exception e) { logger.Error(e); string code = "#205"; e = new Exception("Fehler beim Erstellen der View " + code, e); return(View("Error", e)); } }
/// <summary> /// Diese Methode wird aufgerufen, wenn eine Schulung angelegt wurde und generiert und schickt eine Mail an den Dozenten der Schulung. /// </summary> /// <param name="schulung">Die Schulung, die angelegt wurde</param> public async Task GenerateAndSendAnlegeMailAsync(Schulung schulung, string rootUrl, string vorstand) { try { MimeMessage message = new MimeMessage(); message.From.Add(new MailboxAddress("Schulungsportal", emailSender.GetAbsendeAdresse())); //Absender foreach (var dozent in schulung.Dozenten) { message.To.Add(GetSafeMailboxAddress(dozent.Name, dozent.EMail)); // Empfaenger } message.Subject = "[INFO/noreply] Schulung angelegt"; //Betreff var teilnehmerListeUrl = rootUrl + "/Schulung/Teilnehmer/" + schulung.AccessToken; var dozentenEmails = schulung.Dozenten.Select(d => d.EMail); var attachments = GetAppointment(schulung, dozentenEmails, emailSender.GetAbsendeAdresse(), istAbsage: false); MailViewModel mvm = new MailViewModel { //CCLogoFile = "cclogo.png@"+Guid.NewGuid().ToString(), //FacebookLogoFile = "fblogo.png@" + Guid.NewGuid().ToString(), //InstaLogoFile = "instalogo.png@" + Guid.NewGuid().ToString(), Schulung = schulung, Vorstand = vorstand, TeilnehmerListeUrl = teilnehmerListeUrl, }; var body = new TextPart("html") //Inhalt { Text = await RunCompileAsync("AnlegeMail", mvm), ContentTransferEncoding = ContentEncoding.Base64, }; var outmultipart = new Multipart("mixed"); outmultipart.Add(body); //inmultipart.Add(attachments.First()); // Bilder für Corporate Design, funktioniert leider nicht //outmultipart.Add(inmultipart); //outmultipart.Add(LoadInlinePicture("CCLogo.png", mvm.CCLogoFile)); //outmultipart.Add(LoadInlinePicture("FBLogo.png", mvm.FacebookLogoFile)); //outmultipart.Add(LoadInlinePicture("InstaLogo.png", mvm.InstaLogoFile)); foreach (var attachment in attachments) { outmultipart.Add(attachment); } message.Body = outmultipart; await emailSender.SendEmailAsync(message); } catch (Exception e) { logger.Error(e); string code = "#601"; e = new Exception("Fehler beim Versenden der Anlegemail (" + e.Message + ") " + code, e); throw e; } }
/// <summary> /// Diese Methode gibt den Inhalt des SchulungViewModel-Objekts konvertiert in ein Schulung-Objekt zurück. /// </summary> /// <returns> Schulung-Objekt mit Inhalt des SchulungViewModel-Objekts </returns> public Schulung ToSchulung() { Schulung result = mapper.Map <Schulung>(this); result.Termine = TermineVM.ConvertAll(x => x.ToTermin(SchulungGUID)); result.Anmeldefrist = AnmeldefristDate.Add(AnmeldefristTime); result.StartAnmeldefrist = StartAnmeldefristDate.Add(StartAnmeldefristTime); return(result); }
/// <summary> /// Diese Methode generiert und schickt eine Bestaetigungsmail an einen Nutzer, der sich zu einer Schulung angemeldet hat. /// </summary> /// <param name="anmeldung">Die Anmeldung, die beim anmelden erstellt wird.</param> /// <param name="schulung">Die Schulung, zu der sich der Nutzer angemeldet hat.</param> public async Task GenerateAndSendBestätigungsMailAsync(Anmeldung anmeldung, Schulung schulung, string vorstand, string rootUrl) { try { MimeMessage message = new MimeMessage(); message.From.Add(new MailboxAddress(emailSender.GetAbsendeAdresse())); //Absender message.To.Add(GetSafeMailboxAddress(anmeldung.Vorname + " " + anmeldung.Nachname, anmeldung.Email)); // Empfaenger message.Subject = "[INFO/noreply] Schulungsanmeldung " + schulung.Titel; //Betreff var selbstmanagementUrl = rootUrl + "/Anmeldung/Selbstmanagement/" + anmeldung.AccessToken; var attachments = GetAppointment(schulung, new [] { anmeldung.Email }, emailSender.GetAbsendeAdresse(), istAbsage: false); MailViewModel mvm = new MailViewModel { //CCLogoFile = "cclogo.png@"+Guid.NewGuid().ToString(), //FacebookLogoFile = "fblogo.png@" + Guid.NewGuid().ToString(), //InstaLogoFile = "instalogo.png@" + Guid.NewGuid().ToString(), SelbstmanagementUrl = selbstmanagementUrl, Schulung = schulung, Vorstand = vorstand, }; var body = new TextPart("html") //Inhalt { Text = await RunCompileAsync("BestaetigungsMail", mvm), ContentTransferEncoding = ContentEncoding.Base64, }; var outmultipart = new Multipart("mixed"); outmultipart.Add(body); //inmultipart.Add(attachments.First()); // Bilder für Corporate Design, funktioniert leider nicht //outmultipart.Add(inmultipart); //outmultipart.Add(LoadInlinePicture("CCLogo.png", mvm.CCLogoFile)); //outmultipart.Add(LoadInlinePicture("FBLogo.png", mvm.FacebookLogoFile)); //outmultipart.Add(LoadInlinePicture("InstaLogo.png", mvm.InstaLogoFile)); foreach (var attachment in attachments) { outmultipart.Add(attachment); } message.Body = outmultipart; await emailSender.SendEmailAsync(message); } catch (Exception e) { logger.Error(e); string code = "#601"; e = new Exception("Fehler beim Versenden der Bestätigungsmail (" + e.Message + ") " + code, e); throw e; } }
public async Task <ActionResult> Anlegen(SchulungCreateViewModel newSchulung) { // TODO: test try { if (ModelState.IsValid) { Schulung schulung = await _schulungRepository.AddAsync(newSchulung.ToSchulung()); // stellt für alle Termine sicher, dass die Reihenfolge Anmeldefrist<Start<Ende eingehalten ist // auch Start der Anmeldefrist vor dem Ende der Anmeldefrist if (schulung.Termine.Count > 0 && schulung.Termine.All(x => x.Start > schulung.Anmeldefrist && x.End > x.Start) && schulung.StartAnmeldefrist < schulung.Anmeldefrist) { await mailingHelper.GenerateAndSendAnlegeMailAsync(schulung, Util.getRootUrl(Request), Util.getVorstand(_context)); return(RedirectToAction("Uebersicht")); } if (schulung.StartAnmeldefrist < schulung.Anmeldefrist) { ViewBag.errorMessage = "Start der Anmeldefrist muss vor dem Ende sein!"; } else if (schulung.Termine.Count > 0) { ViewBag.errorMessage = "Anmeldefrist vor Starttermin vor Endtermin bitte!"; } else { ViewBag.errorMessage = "Mindestens ein Termin muss vorhanden sein!"; } } ViewBag.OrganisatorenDatalist = await _schulungRepository.GetPreviousOrganizersAsync(); return(View("Anlegen", newSchulung)); } catch (Exception e) { logger.Error(e); string code = "#203"; e = new Exception("Fehler beim Verarbeiten des Inputs " + code, e); return(View("Error", e)); } }
public async Task <ActionResult> BearbeitenBestaetigt(SchulungCreateViewModel schulungVM, string SchulungGuid) { // TODO: test try { if (ModelState.IsValid) { Schulung schulung = schulungVM.ToSchulung(); // check ob zeiten passen if (schulung.Termine.Count > 0 && schulung.Termine.All(x => x.Start > schulung.Anmeldefrist && x.End > x.Start) && schulung.StartAnmeldefrist < schulung.Anmeldefrist) { await _schulungRepository.UpdateAsync(schulung); return(RedirectToAction("Uebersicht")); //Nach Abschluss der Aktion Weiterleitung zur Ubersicht-View } if (schulung.StartAnmeldefrist >= schulung.Anmeldefrist) { ViewBag.errorMessage = "Start der Anmeldefrist muss vor dem Ende sein!"; } else if (schulung.Termine.Count > 0) { ViewBag.errorMessage = "Anmeldefrist vor Starttermin vor Endtermin bitte!"; } else { ViewBag.errorMessage = "Mindestens ein Termin muss vorhanden sein!"; } } // Fehlermeldung und view bag wieder aufbereiten List <string> orgs = await _schulungRepository.GetPreviousOrganizersAsync(); ViewBag.OrganisatorenDatalist = orgs; return(View("Bearbeiten", schulungVM)); } catch (Exception e) { logger.Error(e); string code = "#212"; e = new Exception("Fehler beim Verarbeiten des Inputs " + code, e); return(View("Error", e)); } }
public static SchulungDTO toDTO(Schulung s) { var termine = s.Termine.Select(t => new TerminDTO { Start = t.Start, End = t.End, }); return(new SchulungDTO { Anmeldefrist = s.Anmeldefrist, Beschreibung = s.Beschreibung, IsAbgesagt = s.IsAbgesagt, OrganisatorInstitution = s.OrganisatorInstitution, Ort = s.Ort, SchulungGUID = s.SchulungGUID, StartAnmeldefrist = s.StartAnmeldefrist, Termine = termine, Titel = s.Titel, }); }
public async Task <ActionResult> Nachtragen(AnmeldungNachtragenViewModel anmeldungViewModel, String schulungGuid) { // TODO: test try { if (ModelState.IsValid) { Anmeldung anmeldung = anmeldungViewModel.ToAnmeldung(); if (anmeldung.SchulungGuid != schulungGuid) { throw new Exception("Guid missmatch"); } Schulung schulung = await _schulungRepository.GetByIdAsync(schulungGuid); if (schulung == null) { return(StatusCode(404, "Schulung mit angegebener ID nicht gefunden!")); } await _anmeldungRepository.AddAsync(anmeldung); // sende Mail falls mindestens ein Start Termin nach jetzt is, also noch was von der Schulung // in Zukunft kommt if (DateTime.Now < schulung.Termine.Min(x => x.Start)) { await mailingHelper.GenerateAndSendBestätigungsMailAsync(anmeldung, await _schulungRepository.GetByIdAsync(anmeldung.SchulungGuid), Util.getVorstand(_context), Util.getRootUrl(Request)); } return(Redirect("/Schulung/Teilnehmerliste/" + anmeldung.SchulungGuid)); } return(View("Nachtragen", anmeldungViewModel)); } catch (Exception e) { logger.Error(e); string code = "#306"; e = new Exception("Fehler beim Verarbeiten des Inputs " + code, e); return(View("Error", e)); } }
public async Task <ActionResult> Teilnehmerliste(string schulungGuid) { // TODO: test try { if (schulungGuid == null) { return(new StatusCodeResult(400)); } Schulung schulung = await _schulungRepository.GetByIdAsync(schulungGuid); if (schulung == null) { return(NotFound("Schulung mit angegebener ID nicht gefunden!")); } TeilnehmerlisteViewModel tl = new TeilnehmerlisteViewModel(); tl.Schulung = schulung; tl.Anmeldungen = _anmeldungRepository.GetBySchulungGuid(schulungGuid); tl.RundmailLink = "&subject=Informationen%20zur%20" + tl.Schulung.Titel + "&body=Hallo%20Teilnehmer%20der%20" + tl.Schulung.Titel + ",%0D%0A%0D%0Ahier%20steht%20die%20Nachricht."; var empfaenger = tl.Anmeldungen // filtert anonymisierte raus .Where(a => a.Email.Contains("@")) .Select(a => a.Email); // füge Dozenten zu Empfängern hinzu empfaenger = empfaenger.Concat(tl.Schulung.Dozenten.Select(d => d.EMail)); tl.RundmailLink = String.Join(";%20", empfaenger) + tl.RundmailLink; tl.RundmailLink = tl.RundmailLink.Insert(0, "mailto:?bcc="); return(View("Teilnehmerliste", tl)); } catch (Exception e) { logger.Error(e); string code = "#204"; e = new Exception("Fehler beim Erstellen der View " + code, e); return(View("Error", e)); } }
public new static InternalSchulungDTO toDTO(Schulung s) { var termine = s.Termine.Select(t => new TerminDTO { Start = t.Start, End = t.End, }); var dozenten = s.Dozenten.Select(d => DozentDTO.toDTO(d)).ToList(); return(new InternalSchulungDTO { Anmeldefrist = s.Anmeldefrist, Beschreibung = s.Beschreibung, Dozenten = dozenten, IsAbgesagt = s.IsAbgesagt, OrganisatorInstitution = s.OrganisatorInstitution, Ort = s.Ort, SchulungGUID = s.SchulungGUID, Termine = termine, Titel = s.Titel, IsGeprueft = s.IsGeprüft, }); }
public async Task <ActionResult> LoeschenBestaetigt(Schulung schulung, string schulungGuid) { // TODO: test try { schulung = await _schulungRepository.GetByIdAsync(schulung.SchulungGUID); if (schulung == null) { return(NotFound("Schulung mit angegebener ID nicht gefunden!")); } await _schulungRepository.DeleteAsync(schulung); return(RedirectToAction("Uebersicht")); } catch (Exception e) { logger.Error(e); string code = "#207"; e = new Exception("Fehler beim Verarbeiten des Inputs " + code, e); return(View("Error", e)); } }
/// <summary> /// Diese Methode generiert und schickt eine Mail an die Dozenten der Schulungen einen Tag nach dieser um zu erinnern, /// die Anwesenheitsliste an den Schulungsbeauftragten zu senden /// </summary> /// <param name="anmeldung">Die Anmeldung.</param> /// <param name="schulung">Die Schulung, zu die abgesagt wird.</param> public async Task GenerateAndSendGeprueftReminderMail(Schulung schulung, string vorstand) { MimeMessage message = new MimeMessage(); message.From.Add(new MailboxAddress("Schulungsportal", emailSender.GetAbsendeAdresse())); //Absender foreach (var dozent in schulung.Dozenten) { message.To.Add(GetSafeMailboxAddress(dozent.Name, dozent.EMail)); // Empfaenger } message.Subject = "[INFO/noreply] Reminder Teilnehmerliste " + schulung.Titel; //Betreff var multipart = new MultipartRelated(); MailViewModel mvm = new MailViewModel { CCLogoFile = "cclogo.png@" + Guid.NewGuid().ToString(), FacebookLogoFile = "fblogo.png@" + Guid.NewGuid().ToString(), InstaLogoFile = "instalogo.png@" + Guid.NewGuid().ToString(), Schulung = schulung, Vorstand = vorstand, }; var body = new TextPart("html") //Inhalt { Text = await RunCompileAsync("GeprueftReminder", mvm), ContentTransferEncoding = ContentEncoding.Base64, }; multipart.Add(body); // Bilder für Corporate Design multipart.Add(LoadInlinePicture("CCLogo.png", mvm.CCLogoFile)); multipart.Add(LoadInlinePicture("FBLogo.png", mvm.FacebookLogoFile)); multipart.Add(LoadInlinePicture("InstaLogo.png", mvm.InstaLogoFile)); message.Body = multipart; await emailSender.SendEmailAsync(message); }
public async Task <ActionResult> Anmeldung(AnmeldungViewModel newAnmeldung) { try { if (ModelState.IsValid) { // failsafe für den Status, wenn absichtlich falsch übergeben if (!AnmeldungViewModel.AllStati.Contains(newAnmeldung.Status)) { return(StatusCode(400, "invalid status")); } DateTime now = DateTime.Now; List <Schulung> angemeldeteSchulungen = new List <Schulung>(); var rootUrl = Util.getRootUrl(Request); var vorstand = Util.getVorstand(_context); foreach (SchulungsCheckBox checkbox in newAnmeldung.SchulungsCheckboxen) { if (checkbox.Checked) { Anmeldung anmeldung = newAnmeldung.ToAnmeldung(); anmeldung.SchulungGuid = checkbox.Guid; Schulung schulung = await _schulungRepository.GetByIdAsync(anmeldung.SchulungGuid); // nur erreicht, wenn absichtlich invalide Id übergeben if (schulung == null) { return(StatusCode(404, "Schulung existiert nicht")); } // Termine aus Datenbank laden if (schulung.Termine.Count == 0) { } // Check ob die Schulung immer noch offen ist, sonst ignorieren if (!schulung.IsAbgesagt && schulung.Anmeldefrist > now && schulung.StartAnmeldefrist < now) { if (await _anmeldungRepository.AnmeldungAlreadyExistAsync(anmeldung)) { schulung.Check = true; angemeldeteSchulungen.Add(schulung); } else { angemeldeteSchulungen.Add(schulung); await _anmeldungRepository.AddAsync(anmeldung); //logger.Info(anmeldung.AccessToken); mailingHelper.GenerateAndSendBestätigungsMailAsync(anmeldung, schulung, vorstand, rootUrl); } } } } return(View("Bestätigung", angemeldeteSchulungen)); //Weiterleitung auf Bestaetigungs-View } AnmeldungViewModel anmeldungViewModel = new AnmeldungViewModel((List <Schulung>)_schulungRepository.GetForRegSortByDate()); newAnmeldung.Schulungen = anmeldungViewModel.Schulungen; newAnmeldung.Stati = anmeldungViewModel.Stati; return(View("Anmeldung", newAnmeldung)); } catch (Exception e) { logger.Error(e); string code = "#302"; e = new Exception("Fehler beim Verarbeiten des Inputs " + code, e); return(View("Error", e)); } }
/// <summary> /// Generiert den Termin als Anhang (.ics-Datei) /// </summary> /// <param name="schulung"> Die Schulung für den Termin</param> /// <returns> Termin Anhang </returns> public static List <MimePart> GetAppointment(Schulung schulung, IEnumerable <string> empfaengerMails, string absender, Boolean istAbsage) { // Konstruieren der ics-Datei List <MimePart> parts = new List <MimePart>(schulung.Termine.Count); for (int i = 0; i < schulung.Termine.Count; i++) { MemoryStream stream = new MemoryStream(); StreamWriter writer = new StreamWriter(stream); writer.WriteLine("BEGIN:VCALENDAR"); writer.WriteLine("PRODID:-//Schedule a Meeting"); writer.WriteLine("VERSION:2.0"); writer.WriteLine("CALSCALE:GREGORIAN"); if (istAbsage) { writer.WriteLine("METHOD:CANCEL"); } else { writer.WriteLine("METHOD:REQUEST"); } writer.WriteLine("BEGIN:VEVENT"); writer.WriteLine(string.Format("DTSTART:{0:yyyyMMddTHHmmssZ}", schulung.Termine.ElementAt(i).Start.ToUniversalTime())); writer.WriteLine(string.Format("DTSTAMP:{0:yyyyMMddTHHmmssZ}", DateTime.UtcNow)); writer.WriteLine(string.Format("DTEND:{0:yyyyMMddTHHmmssZ}", schulung.Termine.ElementAt(i).End.ToUniversalTime())); writer.WriteLine("LOCATION: " + schulung.Ort); var uid = ""; if (i != 0) { uid = i.ToString(); } writer.WriteLine(string.Format("UID:{0}", schulung.SchulungGUID + uid)); writer.WriteLine(string.Format("DESCRIPTION:{0}", HttpUtility.JavaScriptStringEncode(schulung.Beschreibung))); writer.WriteLine(string.Format("X-ALT-DESC;FMTTYPE=text/html:{0}", HttpUtility.JavaScriptStringEncode(schulung.Beschreibung))); writer.WriteLine(string.Format("SUMMARY:{0}", schulung.Titel)); writer.WriteLine(string.Format("ORGANIZER:MAILTO:{0}", absender)); // Fun fact dieses Feld ist in der offiziellen Dokumentation // nicht als verpflichtend gekennzeichnet, lässt man es aber weg // ist office365 zu blöd, zu lesen an wen die Mail geht und erwartet das // dies hier steht. Ein sinnvoller Fehler wird auch nicht geworfen foreach (var empfaengerMail in empfaengerMails) { writer.WriteLine(string.Format("ATTENDEE:{0}", empfaengerMail)); } if (!istAbsage) { writer.WriteLine("BEGIN:VALARM"); writer.WriteLine("TRIGGER:-PT15M"); writer.WriteLine("ACTION:DISPLAY"); writer.WriteLine("DESCRIPTION:Reminder"); writer.WriteLine("END:VALARM"); } writer.WriteLine("END:VEVENT"); writer.WriteLine("END:VCALENDAR"); ContentType contype = new ContentType("text", "calendar"); if (istAbsage) { contype.Parameters.Add("method", "CANCEL"); } else { contype.Parameters.Add("method", "REQUEST"); } contype.Parameters.Add("name", "Schulung" + i + ".ics"); writer.Flush(); stream.Position = 0; var attachment = new MimePart(contype) { Content = new MimeContent(stream, ContentEncoding.Default), ContentDisposition = new ContentDisposition(ContentDisposition.Attachment), ContentTransferEncoding = ContentEncoding.Base64, FileName = "Schulung" + i + ".ics" }; parts.Add(attachment); } return(parts); }