Advertisement
LukasRiedel

Mail Agent 2017 23/4

Apr 23rd, 2017
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 74.13 KB | None | 0 0
  1. /// Soubor Program.cs
  2.  
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Threading.Tasks;
  7. using System.Windows.Forms;
  8.  
  9. namespace Mail_Agent_2017
  10. {
  11.     static class Program
  12.     {
  13.         /// <summary>
  14.         /// Hlavní vstupní bod aplikace.
  15.         /// </summary>
  16.         [STAThread]
  17.         static void Main()
  18.         {
  19.             Application.EnableVisualStyles();
  20.             Application.SetCompatibleTextRenderingDefault(false);
  21.             Application.Run(new MainForm());
  22.         }
  23.     }
  24. }
  25.  
  26.  
  27. /// Soubor MainForm.cs
  28.  
  29. using System;
  30. using System.Collections.Generic;
  31. using System.ComponentModel;
  32. using System.Data;
  33. using System.Drawing;
  34. using System.Linq;
  35. using System.Text;
  36. using System.Threading.Tasks;
  37. using System.Windows.Forms;
  38.  
  39. namespace Mail_Agent_2017
  40. {
  41.     /// <summary>
  42.     /// Hlavní okno celé aplikace.
  43.     /// </summary>
  44.     public partial class MainForm : Form
  45.     {
  46.         Prihlaseni aktualniPrihlaseni;
  47.  
  48.         /// <summary>
  49.         /// Konstruktor se stará o hlavní inicializaci, stahuje emaily, popř. spouští přihlašovací proces.
  50.         /// </summary>
  51.         public MainForm()
  52.         {            
  53.             this.aktualniPrihlaseni = new Prihlaseni();
  54.             PrihlaseniUtility.prihlasovaciProces(ref aktualniPrihlaseni);
  55.             InitializeComponent();
  56.         }
  57.  
  58.         /// <summary>
  59.         /// Odhlásí se a spustí nový přihlašovací proces.
  60.         /// </summary>
  61.         private void odhlásitSeToolStripMenuItem_Click(object sender, EventArgs e)
  62.         {
  63.             this.Hide();
  64.             aktualniPrihlaseni.OdhlasitSe();
  65.             PrihlaseniUtility.prihlasovaciProces(ref aktualniPrihlaseni);
  66.         }
  67.  
  68.         /// <summary>
  69.         /// Ukončí aplikaci.
  70.         /// </summary>
  71.         private void ukončitToolStripMenuItem_Click(object sender, EventArgs e)
  72.         {
  73.             Environment.Exit(0);
  74.         }
  75.  
  76.         /// <summary>
  77.         /// Otevře okno na odeslání emailu.
  78.         /// </summary>
  79.         private void novýEmailToolStripMenuItem_Click(object sender, EventArgs e)
  80.         {
  81.             new SendForm(aktualniPrihlaseni).ShowDialog();
  82.         }
  83.     }
  84. }
  85.  
  86.  
  87.  
  88. /// Soubor SendForm.cs
  89.  
  90. using System;
  91. using System.Collections.Generic;
  92. using System.Linq;
  93. using System.Net.Mail;
  94. using System.Windows.Forms;
  95.  
  96. namespace Mail_Agent_2017
  97. {
  98.     /// <summary>
  99.     /// Odesílání emailu.
  100.     /// </summary>
  101.     public partial class SendForm : Form
  102.     {
  103.  
  104.         // TO-DO: Opravdový HTML editor pro textové pole. Bohužel, s mými aktuálními znalostmi jazyka nejspíš neproveditelné.
  105.  
  106.         Prihlaseni aktualniPrihlaseni;
  107.         MailMessage emailovaZprava;
  108.         AttachmentForm prilohy;
  109.         Stack<string> undoZasobnik;
  110.         Stack<string> redoZasobnik;
  111.         public SendForm(Prihlaseni aktualniPrihlaseni)
  112.         {
  113.             InitializeComponent();
  114.             #region Inicializace Tooltipů k jednotlivým položkám
  115.             // Přijde mi jednodušší toto napsat "ručně", než to dělat pomocí designeru.
  116.             ToolTip ToToolTip = new ToolTip();
  117.             ToToolTip.UseFading = true;
  118.             ToToolTip.UseAnimation = true;
  119.             ToToolTip.ReshowDelay = 500;
  120.             ToToolTip.InitialDelay = 500;
  121.             ToToolTip.AutoPopDelay = 15000;
  122.             ToToolTip.ShowAlways = true;
  123.             ToToolTip.ToolTipIcon = ToolTipIcon.Info;
  124.             ToToolTip.SetToolTip(ToTextbox, "Více příjemců oddělujte středníkem.");
  125.  
  126.             ToolTip CcToolTip = new ToolTip();
  127.             CcToolTip.UseFading = true;
  128.             CcToolTip.UseAnimation = true;
  129.             CcToolTip.ReshowDelay = 500;
  130.             CcToolTip.InitialDelay = 500;
  131.             CcToolTip.AutoPopDelay = 15000;
  132.             CcToolTip.ShowAlways = true;
  133.             CcToolTip.ToolTipIcon = ToolTipIcon.Info;
  134.             CcToolTip.SetToolTip(CcTextbox, "Více příjemců oddělujte středníkem.");
  135.  
  136.             ToolTip BccToolTip = new ToolTip();
  137.             BccToolTip.UseFading = true;
  138.             BccToolTip.UseAnimation = true;
  139.             BccToolTip.ReshowDelay = 500;
  140.             BccToolTip.InitialDelay = 500;
  141.             BccToolTip.AutoPopDelay = 15000;
  142.             BccToolTip.ShowAlways = true;
  143.             BccToolTip.ToolTipIcon = ToolTipIcon.Info;
  144.             BccToolTip.SetToolTip(BccTextbox, "Více příjemců oddělujte středníkem.");
  145.  
  146.             ToolTip SubjectToolTip = new ToolTip();
  147.             SubjectToolTip.UseFading = true;
  148.             SubjectToolTip.UseAnimation = true;
  149.             SubjectToolTip.ReshowDelay = 500;
  150.             SubjectToolTip.InitialDelay = 500;
  151.             SubjectToolTip.AutoPopDelay = 15000;
  152.             SubjectToolTip.ShowAlways = true;
  153.             SubjectToolTip.ToolTipIcon = ToolTipIcon.Info;
  154.             SubjectToolTip.SetToolTip(SubjectTextbox, "Ačkoliv je toto pole nepovinné, neměli byste ho nechávat prázdné. Předmět by měl obsahovat nanejvýše několikaslovné shrnutí celého e-mailu.");
  155.  
  156.             // Poznámka autora: Za HTML v e-mailu by mě pan Forst zabil. Ještě, že už mám zkoušku ze sítí úspěšně za sebou.
  157.             ToolTip HtmlToolTip = new ToolTip();
  158.             HtmlToolTip.UseFading = true;
  159.             HtmlToolTip.UseAnimation = true;
  160.             HtmlToolTip.ReshowDelay = 500;
  161.             HtmlToolTip.InitialDelay = 500;
  162.             HtmlToolTip.AutoPopDelay = 15000;
  163.             HtmlToolTip.ShowAlways = true;
  164.             HtmlToolTip.ToolTipIcon = ToolTipIcon.Info;
  165.             HtmlToolTip.SetToolTip(HtmlCheckbox, "V případě zaškrnutí této možnosti můžete psát e-mail v jazyce HTML 5.");
  166.  
  167.             #region Tooltipy k editoru
  168.             ToolTip BoldToolTip = new ToolTip();
  169.             BoldToolTip.UseFading = true;
  170.             BoldToolTip.UseAnimation = true;
  171.             BoldToolTip.ReshowDelay = 500;
  172.             BoldToolTip.InitialDelay = 500;
  173.             BoldToolTip.AutoPopDelay = 15000;
  174.             BoldToolTip.ShowAlways = true;
  175.             BoldToolTip.ToolTipIcon = ToolTipIcon.Info;
  176.             BoldToolTip.SetToolTip(BoldButton, "Umožňuje psát tučně.");
  177.  
  178.             ToolTip ItalicToolTip = new ToolTip();
  179.             ItalicToolTip.UseFading = true;
  180.             ItalicToolTip.UseAnimation = true;
  181.             ItalicToolTip.ReshowDelay = 500;
  182.             ItalicToolTip.InitialDelay = 500;
  183.             ItalicToolTip.AutoPopDelay = 15000;
  184.             ItalicToolTip.ShowAlways = true;
  185.             ItalicToolTip.ToolTipIcon = ToolTipIcon.Info;
  186.             ItalicToolTip.SetToolTip(ItalicButton, "Umožňuje psát kurzívou.");
  187.  
  188.             ToolTip UnderlineToolTip = new ToolTip();
  189.             UnderlineToolTip.UseFading = true;
  190.             UnderlineToolTip.UseAnimation = true;
  191.             UnderlineToolTip.ReshowDelay = 500;
  192.             UnderlineToolTip.InitialDelay = 500;
  193.             UnderlineToolTip.AutoPopDelay = 15000;
  194.             UnderlineToolTip.ShowAlways = true;
  195.             UnderlineToolTip.ToolTipIcon = ToolTipIcon.Info;
  196.             UnderlineToolTip.SetToolTip(UnderlineButton, "Umožňuje podtrhnout text.");
  197.  
  198.             ToolTip FontToolTip = new ToolTip();
  199.             FontToolTip.UseFading = true;
  200.             FontToolTip.UseAnimation = true;
  201.             FontToolTip.ReshowDelay = 500;
  202.             FontToolTip.InitialDelay = 500;
  203.             FontToolTip.AutoPopDelay = 15000;
  204.             FontToolTip.ShowAlways = true;
  205.             FontToolTip.ToolTipIcon = ToolTipIcon.Info;
  206.             FontToolTip.SetToolTip(FontButton, "Otevře nabídkou se změnou písma.");
  207.  
  208.             ToolTip FontColorToolTip = new ToolTip();
  209.             FontColorToolTip.UseFading = true;
  210.             FontColorToolTip.UseAnimation = true;
  211.             FontColorToolTip.ReshowDelay = 500;
  212.             FontColorToolTip.InitialDelay = 500;
  213.             FontColorToolTip.AutoPopDelay = 15000;
  214.             FontColorToolTip.ShowAlways = true;
  215.             FontColorToolTip.ToolTipIcon = ToolTipIcon.Info;
  216.             FontColorToolTip.SetToolTip(FontColorButton, "Otevře nabídku se změnou barvy písma.");
  217.  
  218.             ToolTip LeftAlignmentToolTip = new ToolTip();
  219.             LeftAlignmentToolTip.UseFading = true;
  220.             LeftAlignmentToolTip.UseAnimation = true;
  221.             LeftAlignmentToolTip.ReshowDelay = 500;
  222.             LeftAlignmentToolTip.InitialDelay = 500;
  223.             LeftAlignmentToolTip.AutoPopDelay = 15000;
  224.             LeftAlignmentToolTip.ShowAlways = true;
  225.             LeftAlignmentToolTip.ToolTipIcon = ToolTipIcon.Info;
  226.             LeftAlignmentToolTip.SetToolTip(LeftAlignmentButton, "Zarovná text doleva.");
  227.  
  228.             ToolTip RightAlignmentToolTip = new ToolTip();
  229.             RightAlignmentToolTip.UseFading = true;
  230.             RightAlignmentToolTip.UseAnimation = true;
  231.             RightAlignmentToolTip.ReshowDelay = 500;
  232.             RightAlignmentToolTip.InitialDelay = 500;
  233.             RightAlignmentToolTip.AutoPopDelay = 15000;
  234.             RightAlignmentToolTip.ShowAlways = true;
  235.             RightAlignmentToolTip.ToolTipIcon = ToolTipIcon.Info;
  236.             RightAlignmentToolTip.SetToolTip(RightAlignmentButton, "Zarovná text doprava.");
  237.  
  238.             ToolTip CenterAlignmentToolTip = new ToolTip();
  239.             CenterAlignmentToolTip.UseFading = true;
  240.             CenterAlignmentToolTip.UseAnimation = true;
  241.             CenterAlignmentToolTip.ReshowDelay = 500;
  242.             CenterAlignmentToolTip.InitialDelay = 500;
  243.             CenterAlignmentToolTip.AutoPopDelay = 15000;
  244.             CenterAlignmentToolTip.ShowAlways = true;
  245.             CenterAlignmentToolTip.ToolTipIcon = ToolTipIcon.Info;
  246.             CenterAlignmentToolTip.SetToolTip(CenterAlignmentButton, "Zarovná text na střed.");
  247.  
  248.             ToolTip HyperlinkToolTip = new ToolTip();
  249.             HyperlinkToolTip.UseFading = true;
  250.             HyperlinkToolTip.UseAnimation = true;
  251.             HyperlinkToolTip.ReshowDelay = 500;
  252.             HyperlinkToolTip.InitialDelay = 500;
  253.             HyperlinkToolTip.AutoPopDelay = 15000;
  254.             HyperlinkToolTip.ShowAlways = true;
  255.             HyperlinkToolTip.ToolTipIcon = ToolTipIcon.Info;
  256.             HyperlinkToolTip.SetToolTip(HyperlinkButton, "Vloží hypertextový odkaz.");
  257.  
  258.             ToolTip ImageToolTip = new ToolTip();
  259.             ImageToolTip.UseFading = true;
  260.             ImageToolTip.UseAnimation = true;
  261.             ImageToolTip.ReshowDelay = 500;
  262.             ImageToolTip.InitialDelay = 500;
  263.             ImageToolTip.AutoPopDelay = 15000;
  264.             ImageToolTip.ShowAlways = true;
  265.             ImageToolTip.ToolTipIcon = ToolTipIcon.Info;
  266.             ImageToolTip.SetToolTip(ImageButton, "Vloží obrázek.");
  267.  
  268.             ToolTip CopyToolTip = new ToolTip();
  269.             CopyToolTip.UseFading = true;
  270.             CopyToolTip.UseAnimation = true;
  271.             CopyToolTip.ReshowDelay = 500;
  272.             CopyToolTip.InitialDelay = 500;
  273.             CopyToolTip.AutoPopDelay = 15000;
  274.             CopyToolTip.ShowAlways = true;
  275.             CopyToolTip.ToolTipIcon = ToolTipIcon.Info;
  276.             CopyToolTip.SetToolTip(CopyButton, "Zkopíruje vybraný text.");
  277.  
  278.             ToolTip PasteToolTip = new ToolTip();
  279.             PasteToolTip.UseFading = true;
  280.             PasteToolTip.UseAnimation = true;
  281.             PasteToolTip.ReshowDelay = 500;
  282.             PasteToolTip.InitialDelay = 500;
  283.             PasteToolTip.AutoPopDelay = 15000;
  284.             PasteToolTip.ShowAlways = true;
  285.             PasteToolTip.ToolTipIcon = ToolTipIcon.Info;
  286.             PasteToolTip.SetToolTip(PasteButton, "Vloží text ve schránce na aktuální pozici kurzoru.");
  287.  
  288.             ToolTip UndoToolTip = new ToolTip();
  289.             UndoToolTip.UseFading = true;
  290.             UndoToolTip.UseAnimation = true;
  291.             UndoToolTip.ReshowDelay = 500;
  292.             UndoToolTip.InitialDelay = 500;
  293.             UndoToolTip.AutoPopDelay = 15000;
  294.             UndoToolTip.ShowAlways = true;
  295.             UndoToolTip.ToolTipIcon = ToolTipIcon.Info;
  296.             UndoToolTip.SetToolTip(UndoButton, "Tlačítko zpět.");
  297.  
  298.             ToolTip RedoToolTip = new ToolTip();
  299.             RedoToolTip.UseFading = true;
  300.             RedoToolTip.UseAnimation = true;
  301.             RedoToolTip.ReshowDelay = 500;
  302.             RedoToolTip.InitialDelay = 500;
  303.             RedoToolTip.AutoPopDelay = 15000;
  304.             RedoToolTip.ShowAlways = true;
  305.             RedoToolTip.ToolTipIcon = ToolTipIcon.Info;
  306.             RedoToolTip.SetToolTip(RedoButton, "Tlačítko vpřed.");
  307.             #endregion
  308.             #endregion
  309.  
  310.             this.redoZasobnik = new Stack<string>();
  311.             this.undoZasobnik = new Stack<string>();
  312.             this.aktualniPrihlaseni = aktualniPrihlaseni;
  313.             this.emailovaZprava = new MailMessage();
  314.             this.prilohy = new AttachmentForm();
  315.         }
  316.  
  317.         /// <summary>
  318.         /// Tlačítko, které smaže obsah všech formulářů.
  319.         /// </summary>
  320.         private void DeleteButton_Click(object sender, EventArgs e)
  321.         {
  322.             ToTextbox.Text = "";
  323.             CcTextbox.Text = "";
  324.             BccTextbox.Text = "";
  325.             SubjectTextbox.Text = "";
  326.             TextTextarea.Text = "";
  327.         }
  328.  
  329.         /// <summary>
  330.         /// Tlačítko spravující veškeré dění ohledně příloh.
  331.         /// </summary>
  332.         private void PrilohyButton_Click(object sender, EventArgs e)
  333.         {
  334.             prilohy.ShowDialog();
  335.  
  336.             // Počet přiložených souborů musíme řešit takto "složitě", neboť v seznamu příloh je poslední příloha neinicializovaná.
  337.             // Je tam prázdné pole pro vložení nové přílohy, tedy až na případ, kdy je příloh 10. Pak je celý seznam obsazen přílohami.
  338.             var pocetSouboru = (prilohy.seznamPriloh.Last().label.Text != "...") ? prilohy.seznamPriloh.Count.ToString() : (prilohy.seznamPriloh.Count - 1).ToString();
  339.  
  340.             // Podmínku pro if vymyslíme podobně. V této části se zapisuje do labelu na odesílací obrazovce, aby byl uživatel "v obraze" ohledně počtu příloh.
  341.             if ((prilohy.seznamPriloh.Last().label.Text != "...") ? true : prilohy.seznamPriloh.Count - 1 > 0)
  342.                 // Čeština je "krásná" řeč.
  343.                 switch (pocetSouboru)
  344.                 {
  345.                     case "1": PrilohaLabel.Text = "K e-mailu je momentálně přiložen 1 soubor."; break;
  346.                     case "2": case "3": case "4": PrilohaLabel.Text = "K e-mailu jsou momentálně přiloženy " + pocetSouboru + " soubory."; break;
  347.                     default: PrilohaLabel.Text = "K e-mailu je momentálně přiloženo " + pocetSouboru + " souborů."; break;
  348.                 }
  349.             else
  350.                 PrilohaLabel.Text = "";
  351.         }
  352.  
  353.         /// <summary>
  354.         /// Umožní uživateli psát email v jazyce HTML 5. Poskytuje mu k tomu drobné utility, de facto usnadnění.
  355.         /// </summary>
  356.         private void HtmlCheckbox_CheckedChanged(object sender, EventArgs e)
  357.         {
  358.             if (HtmlCheckbox.Checked)
  359.                 MessageBox.Show("Zvažte použití této možnosti. E-mailový klient Vašeho adresáta nemusí tuto možnost podporovat.");
  360.  
  361.             this.undoZasobnik = new Stack<string>();
  362.             this.redoZasobnik = new Stack<string>();
  363.             UndoTimer.Enabled = HtmlCheckbox.Enabled;
  364.             this.undoZasobnik.Push("");
  365.  
  366.             emailovaZprava.IsBodyHtml = HtmlCheckbox.Checked;
  367.             NahledButton.Visible = HtmlCheckbox.Checked;
  368.             BoldButton.Visible = HtmlCheckbox.Checked;
  369.             ItalicButton.Visible = HtmlCheckbox.Checked;
  370.             UnderlineButton.Visible = HtmlCheckbox.Checked;
  371.             FontButton.Visible = HtmlCheckbox.Checked;
  372.             FontColorButton.Visible = HtmlCheckbox.Checked;
  373.             LeftAlignmentButton.Visible = HtmlCheckbox.Checked;
  374.             CenterAlignmentButton.Visible = HtmlCheckbox.Checked;
  375.             RightAlignmentButton.Visible = HtmlCheckbox.Checked;
  376.             HyperlinkButton.Visible = HtmlCheckbox.Checked;
  377.             ImageButton.Visible = HtmlCheckbox.Checked;
  378.         }
  379.  
  380.         /// <summary>
  381.         /// Zobrazí náhled HTML kódu.
  382.         /// </summary>
  383.         private void NahledButton_Click(object sender, EventArgs e)
  384.         {
  385.             new HtmlPreviewForm(TextTextarea.Text).ShowDialog();
  386.         }
  387.  
  388.         #region Implementace obsluh tlačítek usnadňující HTML zadávání.
  389.         // Není to optimální, ale kdybych to chtěl dělat přesně dle svých představ, programoval bych spíš HTML editor než e-mailového klienta.
  390.         // Třeba to někdy časem dotáhnu, momentálně není na takové "kraviny" čas.
  391.  
  392.         private void DekoraceButton_Click(object sender, EventArgs e)
  393.         {
  394.             int start = TextTextarea.SelectionStart;
  395.             switch (((Button)sender).Name)
  396.             {
  397.                 case "BoldButton": TextTextarea.Text = TextTextarea.Text.Insert(TextTextarea.SelectionStart, "<b></b>"); break;
  398.                 case "ItalicButton": TextTextarea.Text = TextTextarea.Text.Insert(TextTextarea.SelectionStart, "<i></i>"); break;
  399.                 case "UnderlineButton": TextTextarea.Text = TextTextarea.Text.Insert(TextTextarea.SelectionStart, "<u></u>"); break;
  400.             }
  401.            
  402.             TextTextarea.Focus();
  403.             TextTextarea.SelectionStart = start + 3;
  404.         }
  405.         private void FontButton_Click(object sender, EventArgs e)
  406.         {
  407.             // Na font se uživatele zeptáme pomocí font dialogu.
  408.             FontDialog font = new FontDialog();
  409.             font.ShowEffects = false;
  410.             if (font.ShowDialog() == DialogResult.OK)
  411.             {
  412.                 int start = TextTextarea.SelectionStart;
  413.                 string fontToHtml = "<span style = \"font-family: " + font.Font.ToString().Split('=')[1].Split(',')[0] + "; font-size: " + font.Font.ToString().Split('=')[2].Split(',')[0] + "px;\">";
  414.                 TextTextarea.Text = TextTextarea.Text.Insert(start, fontToHtml + "</span>");
  415.                 TextTextarea.Focus();
  416.                 TextTextarea.SelectionStart = start + fontToHtml.Length;
  417.             }
  418.         }
  419.  
  420.         private void FontColorButton_Click(object sender, EventArgs e)
  421.         {
  422.             // Na barvu se uživatele zeptáme pomocí color dialogu.
  423.             ColorDialog barva = new ColorDialog();
  424.             barva.AllowFullOpen = true;
  425.             if (barva.ShowDialog() == DialogResult.OK)
  426.             {
  427.                 int start = TextTextarea.SelectionStart;
  428.                 string barvaToHtml = "<span style = \"color: rgb(" + barva.Color.R + ", " + barva.Color.G + ", " + barva.Color.B + ");\">";
  429.                 TextTextarea.Text = TextTextarea.Text.Insert(start, barvaToHtml + "</span>");
  430.                 TextTextarea.Focus();
  431.                 TextTextarea.SelectionStart = start + barvaToHtml.Length;
  432.             }
  433.         }
  434.  
  435.         private void AlignmentButton_Click(object sender, EventArgs e)
  436.         {
  437.             int start = TextTextarea.SelectionStart;
  438.             switch (((Button)sender).Name)
  439.             {
  440.                 case "LeftAlignmentButton":
  441.                     TextTextarea.Text = TextTextarea.Text.Insert(start, "<div style=\"text-align: left;\"></div>");
  442.                     start += 31;
  443.                     break;
  444.                 case "RightAlignmentButton":
  445.                     TextTextarea.Text = TextTextarea.Text.Insert(start, "<div style=\"text-align: right;\"></div>");
  446.                     start += 32;
  447.                     break;
  448.                 case "CenterAlignmentButton":
  449.                     TextTextarea.Text = TextTextarea.Text.Insert(start, "<div style=\"text-align: center;\"></div>");
  450.                     start += 33;
  451.                     break;
  452.             }
  453.             TextTextarea.SelectionStart = start;
  454.             TextTextarea.Focus();
  455.         }
  456.  
  457.         private void HyperlinkButton_Click(object sender, EventArgs e)
  458.         {
  459.             string odkaz;
  460.             string popisek;
  461.  
  462.             try
  463.             {
  464.                 if ((odkaz = new Prompt().ShowDialog("Vložte odkaz", "Mail Agent 2017 - Vložit hypertextový odkaz")) == null)
  465.                     throw new ChybneZadaniException();
  466.  
  467.                 if ((popisek = new Prompt().ShowDialog("Vložte popisek odkazu", "Mail Agent 2017 - Vložit hypertextový odkaz")) == null)
  468.                     throw new ChybneZadaniException();
  469.             }
  470.  
  471.             catch
  472.                 { return; }
  473.  
  474.             int start = TextTextarea.SelectionStart;
  475.             string odkazToHtml = "<a href = \"" + odkaz + "\">" + popisek + "</a>";
  476.             TextTextarea.Text = TextTextarea.Text.Insert(start, odkazToHtml);
  477.             TextTextarea.Focus();
  478.             TextTextarea.SelectionStart = start + odkazToHtml.Length;
  479.         }
  480.  
  481.         private void ImageButton_Click(object sender, EventArgs e)
  482.         {
  483.             string odkaz;
  484.  
  485.             try
  486.             {
  487.                 if ((odkaz = new Prompt().ShowDialog("Vložte odkaz na obrázek", "Mail Agent 2017 - Vložit obrázek")) == null)
  488.                     throw new ChybneZadaniException();
  489.             }
  490.  
  491.             catch
  492.                 { return; }
  493.  
  494.             int start = TextTextarea.SelectionStart;
  495.             string obrazekToHtml = "<img src = \"" + odkaz + "\">";
  496.             TextTextarea.Text = TextTextarea.Text.Insert(start, obrazekToHtml);
  497.             TextTextarea.Focus();
  498.             TextTextarea.SelectionStart = start + obrazekToHtml.Length;
  499.         }
  500.  
  501.         private void CopyButton_Click(object sender, EventArgs e)
  502.         {
  503.             Clipboard.SetText(TextTextarea.Text.Substring(TextTextarea.SelectionStart, TextTextarea.SelectionLength));
  504.             TextTextarea.Focus();
  505.         }
  506.  
  507.         private void PasteButton_Click(object sender, EventArgs e)
  508.         {
  509.             int start = TextTextarea.SelectionStart;
  510.             TextTextarea.Text = TextTextarea.Text.Insert(start, Clipboard.GetText());
  511.             TextTextarea.Focus();
  512.             TextTextarea.SelectionStart = start + Clipboard.GetText().Length;
  513.         }
  514.         #endregion
  515.  
  516.         #region Implementace tlačítek zpět a vpřed.
  517.  
  518.         /*
  519.          * Tlačítka si implementujeme po svém, aby splňovaly to, co od nich chceme.
  520.          * Uděláme to tak, že každých 15 vteřin se uloží aktuální text na undo zásobník, pokud došlo ke změně.
  521.          * Pří stisknutí tlačítka zpět se vždy do textboxu popne poslední záznam na zásobníku a aktuální stav se uloží na redo zásobník.
  522.          * V případě provedení změny po undo se redo zásobník vymaže.
  523.          */
  524.  
  525.         private void UndoButton_Click(object sender, EventArgs e)
  526.         {
  527.             if (undoZasobnik.Count > 0)
  528.             {
  529.                 redoZasobnik.Push(TextTextarea.Text);
  530.                 TextTextarea.Text = undoZasobnik.Pop();
  531.             }
  532.             TextTextarea.Focus();
  533.         }
  534.  
  535.         private void RedoButton_Click(object sender, EventArgs e)
  536.         {
  537.             if (redoZasobnik.Count > 0)
  538.             {
  539.                 undoZasobnik.Push(TextTextarea.Text);
  540.                 TextTextarea.Text = redoZasobnik.Pop();
  541.             }
  542.             TextTextarea.Focus();
  543.         }
  544.  
  545.         private void UndoTimer_Tick(object sender, EventArgs e)
  546.         {
  547.             // Pokud nedošlo od posledního ticku ke změně, nemá smysl pushovat na zásobník stejnou hodnotu.
  548.             if ((TextTextarea.Text != null || undoZasobnik.Last() != TextTextarea.Text) && redoZasobnik.Count == 0)
  549.                 undoZasobnik.Push(TextTextarea.Text);            
  550.         }
  551.  
  552.         private void TextTextarea_KeyDown(object sender, KeyEventArgs e)
  553.         {
  554.             if (redoZasobnik.Count > 0)
  555.             {
  556.                 redoZasobnik = new Stack<string>(); // Preventivně smažeme redo zásobník, jelikož po kroku zpět a následné změně se už "vpřed vrátit nemůžeme".
  557.                 if (TextTextarea.Text != null || undoZasobnik.First() != TextTextarea.Text)
  558.                     undoZasobnik.Push(TextTextarea.Text);
  559.             }
  560.                
  561.         }
  562.         #endregion
  563.  
  564.         /// <summary>
  565.         /// Odešle e-mail na dané adresy z uživatelova e-mailu. Kontroluje chyby a nedostatky, které mohly vzniknout při psaní zprávy.
  566.         /// </summary>
  567.         private async void SendButton_Click(object sender, EventArgs e)
  568.         {
  569.             try
  570.             {
  571.                 // Nejdříve zkontrolujeme, jestli mají e-mailové adresy správný formát.
  572.                 if (string.IsNullOrEmpty(ToTextbox.Text))
  573.                     throw new SpatneVyplnenyAdresatException("Musíte vyplnit alespoň jednoho adresáta.");
  574.                 foreach (string adresa in ToTextbox.Text.Split(';'))
  575.                     if (PrihlaseniUtility.SpravnyFormatAdresy(adresa))
  576.                         emailovaZprava.To.Add(adresa);
  577.                     else
  578.                         throw new SpatneVyplnenyAdresatException("E-mailová adresa má nesprávný formát.");
  579.  
  580.                 if (!string.IsNullOrEmpty(CcTextbox.Text)) foreach (string adresa in CcTextbox.Text.Split(';'))
  581.                     if (PrihlaseniUtility.SpravnyFormatAdresy(adresa))
  582.                         emailovaZprava.CC.Add(adresa);
  583.                     else
  584.                         throw new SpatneVyplnenyAdresatException("E-mailová adresa má nesprávný formát.");
  585.  
  586.                 if(!string.IsNullOrEmpty(BccTextbox.Text)) foreach (string adresa in BccTextbox.Text.Split(';'))
  587.                     if (PrihlaseniUtility.SpravnyFormatAdresy(adresa))
  588.                         emailovaZprava.Bcc.Add(adresa);
  589.                     else
  590.                         throw new SpatneVyplnenyAdresatException("E-mailová adresa má nesprávný formát.");
  591.  
  592.                 // Optáme se uživatele, jestli chce opravdu odeslat email bez předmětu.
  593.                 if (string.IsNullOrEmpty(SubjectTextbox.Text) && MessageBox.Show("Opravdu chcete odeslat e-mail bez předmětu?", "Nebyl vyplněn předmět e-mailu.", MessageBoxButtons.YesNo) == DialogResult.No)
  594.                     throw new EmailBezPredmetuException();
  595.  
  596.                 emailovaZprava.Subject = SubjectTextbox.Text;
  597.  
  598.                 // Optáme se uživatele, jestli chce opravdu odeslat prázdný email.
  599.                 if (string.IsNullOrEmpty(TextTextarea.Text) && MessageBox.Show("Opravdu chcete odeslat prázdný e-mail?", "Nebyl vyplněn žádný text.", MessageBoxButtons.YesNo) == DialogResult.No)
  600.                     throw new EmailBezTextuException();
  601.  
  602.                 emailovaZprava.Body = TextTextarea.Text;
  603.             }
  604.  
  605.             catch (Exception ex)
  606.             {
  607.                 ChyboveOknoLabel.ForeColor = System.Drawing.Color.Red;
  608.                 if (ex is SpatneVyplnenyAdresatException)
  609.                 {
  610.                     ChyboveOknoLabel.Show();
  611.                     ChyboveOknoLabel.Text = ex.Message;
  612.                     ZobrazeniChybyTimer.Enabled = true;
  613.                     return;
  614.                 }
  615.  
  616.                 else if (ex is EmailBezPredmetuException || ex is EmailBezTextuException)
  617.                     { return; }
  618.  
  619.                 else throw; // Upřímně řečeno si momentálně nejsem vůbec jistý, jestli může nastat nějaká jiná výjimka.
  620.             }
  621.  
  622.             // Přidáme k e-mailu přílohy, pokud existují.
  623.             foreach (var priloha in (prilohy.seznamPriloh.Last().label.Text != "...") ? prilohy.seznamPriloh : prilohy.seznamPriloh.GetRange(0, prilohy.seznamPriloh.Count - 1))
  624.                 emailovaZprava.Attachments.Add(new Attachment(priloha.soubor.FileName));
  625.  
  626.             // Přidáme adresu odesílatele - tedy sebe.
  627.             emailovaZprava.From = new MailAddress(aktualniPrihlaseni.email, aktualniPrihlaseni.jmeno);
  628.  
  629.             try
  630.             {
  631.                 // Zapneme blikající tečky a pro jistotu vypneme timer na hlášení chyby, kdyby byl náhodou aktivní, tak ať to nedělá kraviny.
  632.                 NacitaniTimer.Enabled = true;
  633.                 ZobrazeniChybyTimer.Enabled = false;
  634.                 ChyboveOknoLabel.Text = ""; ChyboveOknoLabel.ForeColor = System.Drawing.Color.Black;
  635.  
  636.                 // Počkáme na pracovní vlákno, které za nás odešle e-mail, abychom zbytečně neblokovali UI.
  637.                 await aktualniPrihlaseni.SmtpPripojeni.SendMailAsync(emailovaZprava);
  638.             }
  639.            
  640.             // Nevím, jestli asynchronní odesílání e-mailu může vyvolat nějakou výjimku, ale pár řádek kódu navíc neuškodí.
  641.             catch
  642.             {                
  643.                 ChyboveOknoLabel.Show();
  644.                 ChyboveOknoLabel.Text = "Zprávu se nepodařilo odeslat.";
  645.                 ChyboveOknoLabel.ForeColor = System.Drawing.Color.Red;
  646.                 ZobrazeniChybyTimer.Enabled = true;
  647.                 return;
  648.             }
  649.  
  650.             finally
  651.             {
  652.                 NacitaniTimer.Enabled = false;
  653.             }
  654.  
  655.             MessageBox.Show("Zpráva byla úspěšně odeslána.");
  656.             ChyboveOknoLabel.Text = "Zpráva byla úspěšně odeslána.";
  657.         }
  658.  
  659.         /// <summary>
  660.         /// Skryje chybovou hlášku po uplynutí deseti sekund.
  661.         /// </summary>
  662.         private void ZobrazeniChybyTimer_Tick(object sender, EventArgs e)
  663.         {
  664.             ZobrazeniChybyTimer.Enabled = false;            
  665.             ChyboveOknoLabel.Hide();
  666.             ChyboveOknoLabel.ForeColor = System.Drawing.Color.Black;
  667.         }
  668.  
  669.         /// <summary>
  670.         /// Metoda pro efekt, zobrazuje efekt blikajících teček při přihlašování.
  671.         /// </summary>
  672.         private void NacitaniTimer_Tick(object sender, EventArgs e)
  673.         {            
  674.             if (ChyboveOknoLabel.Text.Length >= 71 || ChyboveOknoLabel.Text.Length == 0)
  675.                 ChyboveOknoLabel.Text = "Počkejte, prosím. Toto může chvíli trvat. Probíhá odesílání e-mailu ";
  676.             else
  677.                 ChyboveOknoLabel.Text += ".";
  678.         }
  679.     }
  680.  
  681.     /// <summary>
  682.     /// Vyrobíme si okno podobné příkazu prompt v Javascriptu.
  683.     /// Přišlo mi zbytečné na to vytvářet další soubor s designerem, když je na to potřeba pár řádek kódu.
  684.     /// </summary>
  685.     internal class Prompt
  686.     {
  687.         /// <summary>
  688.         /// Implementace metody ShowDialog. Podobná té klasické ShowDialog ze třídy Form.
  689.         /// </summary>
  690.         /// <param name="text">Text, který se zobrazí v labelu.</param>
  691.         /// <param name="popis">Název okna.</param>
  692.         /// <returns>V případě úspěchu bude okno vracet obsah textboxu.</returns>
  693.         public string ShowDialog(string text, string popis)
  694.         {
  695.             Form prompt = new Form()
  696.             {
  697.                 Width = 500,
  698.                 Height = 150,
  699.                 FormBorderStyle = FormBorderStyle.FixedDialog,
  700.                 Text = popis,
  701.                 StartPosition = FormStartPosition.CenterScreen,
  702.                 MaximizeBox = false,
  703.                 MinimizeBox = false
  704.             };
  705.  
  706.             Label label = new Label() { Left = 50, Top = 20, Text = text, Width = 400 };
  707.             TextBox textbox = new TextBox() { Left = 50, Top = 40, Width = 400 };
  708.             Button tlacitko = new Button() { Text = "Potvrdit", Left = 350, Width = 100, Top = 70, DialogResult = DialogResult.OK };
  709.             tlacitko.Click += (sender, e) => { prompt.Close(); };
  710.             prompt.Controls.Add(textbox);
  711.             prompt.Controls.Add(tlacitko);
  712.             prompt.Controls.Add(label);
  713.             prompt.AcceptButton = tlacitko;
  714.  
  715.             // V případě úspěchu bude okno vracet obsah textboxu.
  716.             return prompt.ShowDialog() == DialogResult.OK ? textbox.Text : null;
  717.         }
  718.     }
  719.  
  720.     #region Definice výjimek.
  721.     /// <summary>
  722.     /// Definice výjimky pro nevyplněný předmět.
  723.     /// </summary>
  724.     internal class EmailBezPredmetuException : Exception
  725.     {
  726.         public EmailBezPredmetuException() : base() { }
  727.     }
  728.  
  729.     /// <summary>
  730.     /// Definice výjimky pro prázdný text.
  731.     /// </summary>
  732.     internal class EmailBezTextuException : Exception
  733.     {
  734.         public EmailBezTextuException() : base() { }
  735.     }
  736.  
  737.     /// <summary>
  738.     /// Definice výjimky pro chybně vyplněné adresáty.
  739.     /// </summary>
  740.     internal class SpatneVyplnenyAdresatException : Exception
  741.     {
  742.         public SpatneVyplnenyAdresatException(string message) : base(message) { }
  743.     }
  744.     #endregion
  745. }
  746.  
  747.  
  748.  
  749. /// Soubor AttachmentForm.cs
  750.  
  751. using System;
  752. using System.Collections.Generic;
  753. using System.Linq;
  754. using System.Windows.Forms;
  755.  
  756. namespace Mail_Agent_2017
  757. {
  758.     /// <summary>
  759.     /// Toto okno se zobrazí, pokud chce uživatel přidat k e-mailu nějakou přílohu.
  760.     /// </summary>
  761.     public partial class AttachmentForm : Form
  762.     {
  763.         internal List<Priloha> seznamPriloh;
  764.         public AttachmentForm()
  765.         {
  766.             InitializeComponent();
  767.             seznamPriloh = new List<Priloha>();
  768.             InicializujNovouPrilohu(null);
  769.         }
  770.  
  771.         /// <summary>
  772.         /// Skryje toto okno.
  773.         /// </summary>
  774.         private void PridatButton_Click(object sender, EventArgs e)
  775.         {
  776.             this.Hide();
  777.         }
  778.  
  779.         /// <summary>
  780.         /// Inicializuje nové ovládací prvky, díky nim může uživatel přidat novou přílohu. Zároveň upravuje GUI.
  781.         /// </summary>
  782.         /// <param name="cesta">Cesta k souboru, v případě, že se jedná o již načtenou přílohu.</param>
  783.         private void InicializujNovouPrilohu(object cesta)
  784.         {
  785.             try
  786.             {
  787.                 // Není vhodné posílat příliš mnoho souborů emailem. Navíc, kdybychom přidávali přílohy do nekonečna, dostali bychom se s GUI mimo obrazovku.
  788.                 if (seznamPriloh.Count == 10)
  789.                     throw new PrilisMnohoPrilohException("Byl dosažen maximální počet příloh u jednoho emailu.");
  790.  
  791.                 // Posune celé GUI.
  792.                 if (seznamPriloh.Count > 5)
  793.                 {
  794.                     this.ClientSize = new System.Drawing.Size(384, this.ClientSize.Height + 36);
  795.                     this.PridatButton.Location = new System.Drawing.Point(90, this.PridatButton.Location.Y + 36);
  796.                 }                    
  797.  
  798.                 // Přidáme ovládací prvky dané přílohy do seznamu, abychom k nim mohli snadno přistupovat.
  799.  
  800.                 // Momentálně se vždy spustí if true větev, druhá větev byla implementována s jistým záměrem, který se nakonec neuskutečnil.
  801.                 // Nicméně, pokud by někdo chtěl kód měnit, může se mu to hodit.
  802.                 this.seznamPriloh.Add((cesta == null) ? new Priloha(this, seznamPriloh.Count) : new Priloha(this, seznamPriloh.Count, cesta));
  803.             }
  804.             catch (Exception ex)
  805.             {
  806.                 if (ex is PrilisMnohoPrilohException)
  807.                     MessageBox.Show(ex.Message);
  808.             }            
  809.         }
  810.  
  811.         /// <summary>
  812.         /// Odstraní existující přílohu a to tak, že danou přílohu odebere ze seznamu příloh a celý seznam posune, také upravuje GUI.
  813.         /// </summary>
  814.         /// <param name="kolikataPriloha">Index přílohy, která se má odstranit.</param>
  815.         private void OdstranExistujiciPrilohu(int kolikataPriloha)
  816.         {
  817.             // V každém případě danou přílohu odstraníme ze seznamu a všechny přílohy posuneme o jedno políčko směrem nahoru.
  818.             seznamPriloh.GetRange(kolikataPriloha + 1, seznamPriloh.Count - kolikataPriloha - 1).ForEach(priloha =>
  819.             {
  820.                 priloha.label.Location = new System.Drawing.Point(152, priloha.label.Location.Y - 36);
  821.                 priloha.tlacitko.Location = new System.Drawing.Point(16, priloha.tlacitko.Location.Y - 36);                
  822.             });
  823.            
  824.             // A pokud jsme kvůli přílohám zvětšovali okno, tak ho zase zmenšíme.
  825.             if (seznamPriloh.Count > 5)
  826.             {
  827.                 this.PridatButton.Location = new System.Drawing.Point(90, this.PridatButton.Location.Y - 36);
  828.                 this.ClientSize = new System.Drawing.Size(384, this.ClientSize.Height - 36);
  829.             }
  830.  
  831.             // Uvolnění resourců, aby prvky smazané přílohy nezůstaly na pozadí a nezabíraly tak zbytečně paměť.
  832.             seznamPriloh[kolikataPriloha].Dispose();
  833.             seznamPriloh.RemoveAt(kolikataPriloha);
  834.  
  835.             // Pokud jsme odebrali poslední přílohu, musíme přidat tlačítko na přidání nové.
  836.             if (seznamPriloh.Count == 9 && seznamPriloh.Last().label.Text != "...")
  837.                 InicializujNovouPrilohu(null);
  838.         }
  839.  
  840.         /// <summary>
  841.         /// Definice třídy příloh, každá příloha se skládá z trojice - tlačítko, label a OpenFileDialog objekt.
  842.         /// </summary>
  843.         internal class Priloha : IDisposable
  844.         {
  845.             public Button tlacitko;
  846.             public Label label;
  847.             public OpenFileDialog soubor;
  848.             private AttachmentForm okno;
  849.  
  850.             /// <summary>
  851.             /// Zde probíhá inicializace ovládacích prvků.
  852.             /// </summary>
  853.             /// <param name="okno">Vzhledem k tomu, že se jedná o interní třídu ve třídě, tak nemůžeme použít this na vnější třídu. Vlastnosti okna musíme třídě předat jako parametr.</param>
  854.             /// <param name="kolikataPriloha">Určuje, o kolikátou přílohu se jedná a dle toho umisťuje ovládací prvky.</param>
  855.             public Priloha(AttachmentForm okno, int kolikataPriloha)
  856.             {
  857.                 this.okno = okno;
  858.                 this.tlacitko = new System.Windows.Forms.Button();
  859.                 this.label = new System.Windows.Forms.Label();
  860.                 this.soubor = new System.Windows.Forms.OpenFileDialog();
  861.  
  862.                 #region Inicializace ovládacích prvků
  863.                 okno.SuspendLayout();
  864.                
  865.                 // Inicializuje tlačítko
  866.                 this.tlacitko.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(28)))), ((int)(((byte)(139)))), ((int)(((byte)(196)))));
  867.                 this.tlacitko.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
  868.                 this.tlacitko.Font = new System.Drawing.Font("Calibri", 11F, System.Drawing.FontStyle.Bold);
  869.                 this.tlacitko.ForeColor = System.Drawing.Color.White;
  870.                 this.tlacitko.Location = new System.Drawing.Point(16, 100 + kolikataPriloha * 36);
  871.                 this.tlacitko.Size = new System.Drawing.Size(130, 28);
  872.                 this.tlacitko.TabIndex = kolikataPriloha;
  873.                 this.tlacitko.Text = "Vybrat ze souboru";
  874.                 this.tlacitko.UseVisualStyleBackColor = false;
  875.                 this.tlacitko.Click += new EventHandler(this.OtevriSoubor);
  876.  
  877.                 // Inicializuje label
  878.                 this.label.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
  879.                 this.label.Font = new System.Drawing.Font("Calibri", 12F);
  880.                 this.label.Location = new System.Drawing.Point(152, 100 + kolikataPriloha * 36);
  881.                 this.label.Size = new System.Drawing.Size(220, 28);
  882.                 this.label.Text = "...";
  883.                 this.label.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
  884.                 okno.ResumeLayout();
  885.                 #endregion
  886.  
  887.                 okno.Controls.Add(this.tlacitko);
  888.                 okno.Controls.Add(this.label);
  889.             }
  890.  
  891.             /// <summary>
  892.             /// Rozšířený konstruktor, pokud již příloha existuje a známe k ní cestu.
  893.             /// </summary>
  894.             /// <param name="okno">Vzhledem k tomu, že se jedná o interní třídu ve třídě, tak nemůžeme použít this na vnější třídu. Vlastnosti okna musíme třídě předat jako parametr.</param>
  895.             /// <param name="kolikataPriloha">Určuje, o kolikátou přílohu se jedná a dle toho umisťuje ovládací prvky.</param>
  896.             /// <param name="cesta">Cesta ve filesystému k dané příloze.</param>
  897.             public Priloha(AttachmentForm okno, int kolikataPriloha, object cesta) : this(okno, kolikataPriloha)
  898.             {
  899.                 this.tlacitko.Text = "Odstranit";
  900.                 this.tlacitko.Click += new EventHandler(this.OdstranPrilohu);
  901.                 this.label.Text = "..\u005c" + cesta.ToString().Split('\u005c').ToList().Last(); // V labelu zobrazíme pouze název souboru.
  902.             }
  903.  
  904.             /// <summary>
  905.             /// Obsluha tlačítka, které přidává přílohu.
  906.             /// </summary>
  907.             private void OtevriSoubor(object sender, EventArgs e)
  908.             {
  909.                 if (this.soubor.ShowDialog() == DialogResult.OK)
  910.                 {
  911.                     this.tlacitko.Text = "Odstranit";
  912.                     this.label.Text = "..\u005c" + this.soubor.FileName.ToString().Split('\u005c').ToList().Last(); // V labelu zobrazíme pouze název souboru.
  913.  
  914.                     // Tlačítko přidat měníme na tlačítko odstranit, musíme upravit obsluhy daného tlačítka.
  915.                     this.tlacitko.Click -= new EventHandler(this.OtevriSoubor);
  916.                     this.tlacitko.Click += new EventHandler(this.OdstranPrilohu);
  917.  
  918.                     // Přidáme možnost přidání nové přílohy.
  919.                     okno.InicializujNovouPrilohu(null);
  920.                 }
  921.             }
  922.  
  923.             /// <summary>
  924.             /// Obsluha tlačítka, které odebírá přílohu.
  925.             /// </summary>
  926.             private void OdstranPrilohu(object sender, EventArgs e)
  927.             {
  928.                 if (MessageBox.Show("Opravdu chcete odstranit tuto přílohu?", "Odstranit", MessageBoxButtons.YesNo) == DialogResult.Yes)
  929.                 {
  930.                     this.tlacitko.Text = "Vybrat ze souboru";
  931.                     this.label.Text = "...";
  932.                     this.soubor = new System.Windows.Forms.OpenFileDialog();
  933.  
  934.                     // Tlačítko odstranit měníme na tlačítko přidat, musíme upravit obsluhy daného tlačítka.
  935.                     this.tlacitko.Click -= new EventHandler(this.OdstranPrilohu);
  936.                     this.tlacitko.Click += new EventHandler(this.OtevriSoubor);
  937.  
  938.                     okno.OdstranExistujiciPrilohu((this.label.Location.Y - 100) / 36); // O kolikátou přílohu se jedná, poznáme podle její pozice.
  939.                 }
  940.             }
  941.  
  942.             public void Dispose()
  943.             {
  944.                 this.tlacitko.Dispose();
  945.                 this.label.Dispose();
  946.                 this.soubor.Dispose();
  947.             }
  948.         }
  949.  
  950.         /// <summary>
  951.         /// Definice výjimky potřebné pro toto okno.
  952.         /// </summary>
  953.         internal class PrilisMnohoPrilohException : Exception
  954.         {
  955.             public PrilisMnohoPrilohException(string message) : base(message) { }
  956.         }
  957.     }
  958. }
  959.  
  960.  
  961. /// Soubor HtmlPreviewForm.Cs
  962.  
  963. using System;
  964. using System.Windows.Forms;
  965.  
  966. namespace Mail_Agent_2017
  967. {
  968.     /// <summary>
  969.     /// Zobrazí náhled HTML kódu.
  970.     /// </summary>
  971.     public partial class HtmlPreviewForm : Form
  972.     {
  973.         public HtmlPreviewForm(string kod)
  974.         {
  975.             InitializeComponent();
  976.             HtmlPreviewWebbrowser.DocumentText = "<!DOCTYPE html><html><body style=\"font-family: Calibri;\">" + kod + "</body></html>";
  977.         }
  978.  
  979.         /// <summary>
  980.         /// Zavře okno s náhledem.
  981.         /// </summary>
  982.         private void ZavritButton_Click(object sender, EventArgs e)
  983.         {
  984.             this.Close();
  985.         }
  986.     }
  987. }
  988.  
  989.  
  990.  
  991. /// Soubor ESP.cs
  992.  
  993. using System;
  994. using System.Collections.Generic;
  995. using System.IO;
  996.  
  997. namespace Mail_Agent_2017
  998. {
  999.     /// <summary>
  1000.     /// Třída seskupující informace o jednotlivých e-mail service providerech.
  1001.     /// Umožňuje uživateli jednodušší přihlášení ke své e-mailové schránce.
  1002.     /// V případě, že uživatel využívá ESP, který není v seznamu, tak se po prvním úspěšném přihlášení do tohoto seznamu zapíše.
  1003.     /// </summary>
  1004.     class ESP
  1005.     {
  1006.         private List<ESP_Zaznam> seznam;  
  1007.        
  1008.         /// <summary>
  1009.         /// Konstruktor načte údaje o všech ESP z tabulky, která je uložena v souboru.
  1010.         /// </summary>
  1011.         public ESP()
  1012.         {
  1013.             this.seznam = new List<ESP_Zaznam>();
  1014.             StreamReader esp_seznam = new StreamReader("esp_info");
  1015.  
  1016.             while (!esp_seznam.EndOfStream)
  1017.             {
  1018.                 string[] zaznam = esp_seznam.ReadLine().Split(';');
  1019.                 seznam.Add(new ESP_Zaznam(zaznam[0], zaznam[1], int.Parse(zaznam[2]), bool.Parse(zaznam[3]),
  1020.                                           zaznam[4], int.Parse(zaznam[5]), bool.Parse(zaznam[6]), bool.Parse(zaznam[7])));
  1021.             }
  1022.  
  1023.             esp_seznam.Close();
  1024.         }
  1025.  
  1026.         /// <summary>
  1027.         /// Třída zahrnující informace o e-mail service providerovi.
  1028.         /// </summary>
  1029.         internal class ESP_Zaznam : IEquatable<ESP_Zaznam>
  1030.         {
  1031.             public string nazev;
  1032.             public string ImapServer;
  1033.             public int ImapPort;
  1034.             public bool ImapSsl;
  1035.             public string SmtpServer;
  1036.             public int SmtpPort;
  1037.             public bool SmtpSsl;
  1038.             public bool SmtpAuth;
  1039.             public ESP_Zaznam(string nazev, string ImapServer, int ImapPort, bool ImapSsl, string SmtpServer, int SmtpPort, bool SmtpSsl, bool SmtpAuth)
  1040.             {
  1041.                 this.nazev = nazev;
  1042.                 this.ImapServer = ImapServer;
  1043.                 this.ImapPort = ImapPort;
  1044.                 this.ImapSsl = ImapSsl;
  1045.                 this.SmtpServer = SmtpServer;
  1046.                 this.SmtpPort = SmtpPort;
  1047.                 this.SmtpSsl = SmtpSsl;
  1048.                 this.SmtpAuth = SmtpAuth;
  1049.  
  1050.             }
  1051.             public bool Equals(ESP_Zaznam zaznam)
  1052.             {
  1053.                 return this.nazev == zaznam.nazev;
  1054.             }
  1055.         }
  1056.  
  1057.         /// <summary>
  1058.         /// Metoda, která hledá ESP uživatele v tabulce známých ESP.
  1059.         /// </summary>
  1060.         /// <param name="nazev">E-mail service provider uživatele</param>
  1061.         /// <returns>E-mail service provider uživatele</returns>
  1062.         public ESP_Zaznam NajdiVhodnehoESP(string nazev)
  1063.         {
  1064.             foreach (ESP_Zaznam esp in seznam) if (esp.nazev == nazev)
  1065.                     return esp;
  1066.             return null;
  1067.         }
  1068.  
  1069.         /// <summary>
  1070.         /// Metoda, která přidává nový záznam o ESP do tabulky známých ESP.
  1071.         /// </summary>
  1072.         public void PridejZaznamOESP(string nazev, string ImapServer, int ImapPort, bool ImapSsl, string SmtpServer, int SmtpPort, bool SmtpSsl, bool SmtpAuth)
  1073.         {
  1074.             seznam.Add(new ESP_Zaznam(nazev, ImapServer, ImapPort, ImapSsl, SmtpServer, SmtpPort, SmtpSsl, SmtpAuth));
  1075.             TextWriter esp_seznam = new StreamWriter("esp_info", true);
  1076.             esp_seznam.WriteLine("{0};{1};{2};{3};{4};{5};{6};{7}", nazev, ImapServer, ImapPort,
  1077.                                  ImapSsl, SmtpServer, SmtpPort, SmtpSsl, SmtpAuth);
  1078.             esp_seznam.Close();
  1079.         }
  1080.     }    
  1081. }
  1082.  
  1083.  
  1084.  
  1085. /// Soubor Prihlasit.cs
  1086.  
  1087. using System;
  1088. using System.Text;
  1089. using System.Security.Cryptography;
  1090. using ImapX;
  1091. using System.Net.Mail;
  1092. using System.Net;
  1093. using System.IO;
  1094. using System.Windows.Forms;
  1095. using System.Collections.Generic;
  1096.  
  1097. namespace Mail_Agent_2017
  1098. {
  1099.     /// <summary>
  1100.     /// Třída sdružující informace o aktuálním přihlášení.
  1101.     /// </summary>
  1102.     public class Prihlaseni
  1103.     {
  1104.         private string _email;
  1105.         private string _heslo;
  1106.         private string _jmeno;
  1107.         public ImapClient ImapPripojeni;
  1108.         public SmtpClient SmtpPripojeni;
  1109.  
  1110.         /// <summary>
  1111.         /// Symetrické šifirování e-mailové adresy podle AES standardu, aby se mohla uložit do souboru.
  1112.         /// </summary>
  1113.         public string email
  1114.         {
  1115.             get { return _email == null ? null : Sifrovani.Decrypt(_email); }
  1116.             set { _email = Sifrovani.Encrypt(value); }
  1117.         }
  1118.  
  1119.         /// <summary>
  1120.         /// Symetrické šifirování hesla podle AES standardu, aby se mohlo uložit do souboru.
  1121.         /// </summary>
  1122.         public string heslo
  1123.         {
  1124.             get { return _heslo == null ? null : Sifrovani.Decrypt(_heslo); }
  1125.             set { _heslo = Sifrovani.Encrypt(value); }
  1126.         }
  1127.  
  1128.         /// <summary>
  1129.         /// Symetrické šifirování jména podle AES standardu, aby se mohlo uložit do souboru.
  1130.         /// </summary>
  1131.         public string jmeno
  1132.         {
  1133.             get { return _jmeno == null ? null : Sifrovani.Decrypt(_jmeno); }
  1134.             set { _jmeno = Sifrovani.Encrypt(value); }
  1135.         }
  1136.  
  1137.         /// <summary>
  1138.         /// Uloží aktuální přihlášení do souboru, aby při příštím přihlášení uživatel nemusel znovu podstupovat přihlašovací proces.
  1139.         /// </summary>
  1140.         public void UlozPrihlaseniDoSouboru()
  1141.         {
  1142.             try
  1143.             {
  1144.                 if (_email == null || _heslo == null || _jmeno == null || ImapPripojeni == null || SmtpPripojeni == null)
  1145.                     throw new ChybneZadaniException("Nepodařilo se uložit aktuální relaci. Při příštím spuštění aplikace se budete muset znovu přihlásit.");
  1146.             }
  1147.  
  1148.             catch (ChybneZadaniException ex)
  1149.                 { MessageBox.Show(ex.Message); return; }
  1150.  
  1151.             StreamWriter prihlaseniSoubor = new StreamWriter("login_info");
  1152.  
  1153.             prihlaseniSoubor.WriteLine("{0} {1} {2}", _email, _heslo, _jmeno);
  1154.             prihlaseniSoubor.WriteLine("{0} {1} {2}", ImapPripojeni.Host, ImapPripojeni.Port, ImapPripojeni.UseSsl);
  1155.             prihlaseniSoubor.WriteLine("{0} {1} {2} {3}", SmtpPripojeni.Host, SmtpPripojeni.Port, SmtpPripojeni.EnableSsl, !SmtpPripojeni.UseDefaultCredentials);
  1156.  
  1157.             prihlaseniSoubor.Close();
  1158.         }
  1159.  
  1160.         /// <summary>
  1161.         /// Načte poslední přihlášení ze souboru, pokud existuje.
  1162.         /// </summary>
  1163.         public bool NactiPrihlaseniZeSouboru()
  1164.         {
  1165.             try
  1166.             {
  1167.                 StreamReader prihlaseniSoubor = new StreamReader("login_info");
  1168.  
  1169.                 string[] prihlaseni = prihlaseniSoubor.ReadLine().Split(' ');
  1170.                 string[] IMAP = prihlaseniSoubor.ReadLine().Split(' ');
  1171.                 string[] SMTP = prihlaseniSoubor.ReadLine().Split(' ');
  1172.  
  1173.                 this._email = prihlaseni[0];
  1174.                 this._heslo = prihlaseni[1];
  1175.                 this._jmeno = prihlaseni[2];
  1176.  
  1177.                 this.ImapPripojeni = new ImapClient(IMAP[0], int.Parse(IMAP[1]), bool.Parse(IMAP[2]));
  1178.  
  1179.                 this.SmtpPripojeni = new SmtpClient(SMTP[0], int.Parse(SMTP[1]));
  1180.                 this.SmtpPripojeni.EnableSsl = bool.Parse(SMTP[2]);
  1181.                 if (bool.Parse(SMTP[3]))
  1182.                 {
  1183.                     this.SmtpPripojeni.UseDefaultCredentials = false;
  1184.                     this.SmtpPripojeni.Credentials = new NetworkCredential(email, heslo);                
  1185.                 }
  1186.  
  1187.                 // Pokud se nepovede přihlášení k IMAP serveru, bude uživatel vyzván, aby se přihlásil znovu.
  1188.                 if (!ImapPripojeni.Connect() || !ImapPripojeni.Login(email, heslo))
  1189.                     throw new ImapConnectFailException("Přihlášení bylo neúspěšné. Přihlašte se, prosím, znovu.");
  1190.  
  1191.                 prihlaseniSoubor.Close();
  1192.             }
  1193.  
  1194.             catch (Exception ex)
  1195.             {
  1196.                 if (ex is ImapConnectFailException)
  1197.                     MessageBox.Show(ex.Message);
  1198.  
  1199.                 // Pokud dojde k jiné výjimce, například chybný nebo prázdný vstup, uživatele s tím ani obeznamovat nebudeme. Nemusí vědět všechno.
  1200.                 return false;
  1201.             }    
  1202.  
  1203.             return true;
  1204.         }
  1205.  
  1206.         /// <summary>
  1207.         /// Odhlásí se a odstraní soubor s přihlášením.
  1208.         /// </summary>
  1209.         public void OdhlasitSe()
  1210.         {  
  1211.             File.Delete("login_info");
  1212.             SmtpPripojeni.Dispose();
  1213.             ImapPripojeni.Dispose();
  1214.             _email = null;
  1215.             _heslo = null;
  1216.             _jmeno = null;
  1217.         }
  1218.     }
  1219.     /// <summary>
  1220.     /// Třída poskytující drobné utility, jež se hodí u přihlašování.
  1221.     /// </summary>
  1222.     static class PrihlaseniUtility
  1223.     {
  1224.         /// <summary>
  1225.         /// Metoda rozhoduje, zdali má zadaná adresa správný formát.
  1226.         /// </summary>
  1227.         /// <param name="email">E-mailová adresa, která má být zkontrolována.</param>
  1228.         /// <returns>Úspěch v případě správného formátu adresy, neúspěch v opačném případě.</returns>
  1229.         public static bool SpravnyFormatAdresy(string email)
  1230.         {
  1231.             // Využijeme třídu .NET pro emailové adresy a pokusíme se vytvořit novou emailovou adresu.
  1232.             // V případě neúspěchu vyvolá výjimku - tedy v případě, že adresa má nesprávný formát.
  1233.             try { return new System.Net.Mail.MailAddress(email).Address == email; }
  1234.             catch { return false; }
  1235.         }
  1236.  
  1237.         /// <summary>
  1238.         /// Metoda se pokusí připojit k SMTP serveru podle údajů, které zadal uživatel.
  1239.         /// Také se pokusí poslat testovací zprávu, jakožto indikátor úspěšného připojení,
  1240.         /// </summary>
  1241.         /// <returns>V případě úspěšného připojení odkaz na objekt SmtpClient, v opačném případě null.</returns>
  1242.         public static SmtpClient SmtpConnect(string SmtpServer, int SmtpPort, bool SmtpSsl, bool SmtpAuth, string email, string heslo)
  1243.         {
  1244.             // Zde nemusíme ověřovat (v případě zaškrtnutého checkboxu Auth), zdali se e-mailová adresa shoduje s heslem, vlastně ani nemáme jak.
  1245.             // Proč nemusíme? Ověří to za nás připojení k IMAP serveru, které předchází připojení k SMTP serveru.
  1246.  
  1247.             SmtpClient SmtpPripojeni = new SmtpClient(SmtpServer, SmtpPort);
  1248.             SmtpPripojeni.EnableSsl = SmtpSsl;
  1249.             if (SmtpAuth)
  1250.             {
  1251.                 SmtpPripojeni.UseDefaultCredentials = false;
  1252.                 SmtpPripojeni.Credentials = new NetworkCredential(email, heslo);
  1253.             }
  1254.                
  1255.  
  1256.             // Metoda vyvolá výjimku, když se nepodaří odeslat zprávu.
  1257.             try
  1258.             {
  1259.                 SmtpPripojeni.Send(email , email, "Mail Agent 2017 - Testovací zpráva", @"Přihlášení do aplikace proběhlo úspěšně.");
  1260.                 return SmtpPripojeni;
  1261.             }
  1262.             catch
  1263.                 { return null; }
  1264.  
  1265.         }
  1266.  
  1267.         /// <summary>
  1268.         /// Spustí přihlašovací proces.
  1269.         /// </summary>
  1270.         /// <param name="aktualniPrihlaseni">Relace přihlášení, která má být inicializována.</param>
  1271.         public static void prihlasovaciProces(ref Prihlaseni aktualniPrihlaseni)
  1272.         {
  1273.             Stack<Form> prihlasovaciProces = new Stack<Form>();
  1274.             if (!aktualniPrihlaseni.NactiPrihlaseniZeSouboru())
  1275.             {
  1276.                 /*
  1277.                  * Přihlašovací proces je řešený pomocí zásobníku oken.
  1278.                  * Při kliknutí na tlačítko "Zpět" se do zásobníku pushne předchozí okno, aby uživatel mohl provést změny.
  1279.                  * Přihlašovací proces končí, když je zásobník prázdný.
  1280.                  */
  1281.  
  1282.                 prihlasovaciProces.Push(new LoginForm1(aktualniPrihlaseni, prihlasovaciProces));
  1283.  
  1284.                 while (prihlasovaciProces.Count > 0)
  1285.                     prihlasovaciProces.Pop().ShowDialog();
  1286.  
  1287.                 // Pokud neprobělo přihlášení, dojde k ukončení celé aplikace.
  1288.                 if (aktualniPrihlaseni.ImapPripojeni == null || aktualniPrihlaseni.SmtpPripojeni == null || aktualniPrihlaseni.email == null || aktualniPrihlaseni.heslo == null)
  1289.                     Environment.Exit(0);
  1290.  
  1291.                 // Uložíme aktuální relaci do souboru, abychom ji při příštím spuštění aplikace mohli snadno načíst.
  1292.                 aktualniPrihlaseni.UlozPrihlaseniDoSouboru();
  1293.             }
  1294.         }
  1295.     }
  1296.  
  1297.  
  1298.     #region Definice výjimek
  1299.  
  1300.     /// <summary>
  1301.     /// Výjimka, která je vyvolaná při chybě při navazování spojení se SMTP serverem.
  1302.     /// </summary>
  1303.     class SmtpConnectFailException : Exception
  1304.     {
  1305.         public SmtpConnectFailException(string message) : base(message) { }
  1306.     }
  1307.  
  1308.     /// <summary>
  1309.     /// Výjimka, která je vyvolaná, když uživatel zadá chybné heslo.
  1310.     /// </summary>
  1311.     class SpatneHesloException : Exception
  1312.     {
  1313.         public SpatneHesloException(string message) : base(message) { }
  1314.     }
  1315.  
  1316.     /// <summary>
  1317.     /// Výjimka, která je vyvolaná při chybě při navazování spojení s IMAP serverem.
  1318.     /// </summary>
  1319.     class ImapConnectFailException : Exception
  1320.     {
  1321.         public ImapConnectFailException(string message) : base(message) { }
  1322.     }
  1323.  
  1324.     /// <summary>
  1325.     /// Výjimka, která je vyvolána při chybném vyplnění formuláře.
  1326.     /// </summary>
  1327.     class ChybneZadaniException : Exception
  1328.     {
  1329.         public ChybneZadaniException(string message) : base(message) { }
  1330.         public ChybneZadaniException() : base() { }
  1331.     }
  1332.  
  1333. #endregion
  1334.  
  1335.     /// <summary>
  1336.     /// Následující třída poskytuje šifrovací a dešifrovací funkce.
  1337.     /// Autorem metod NEJSEM já, byly použity šifrovací funkce nalezené na internetu.
  1338.     /// </summary>
  1339.     static class Sifrovani
  1340.     {
  1341.         static readonly string PasswordHash = "h€$$łö";
  1342.         static readonly string SaltKey = "M@iL&g€n†2oI7";
  1343.         static readonly string VIKey = "@1B2c3D4e5F6g7H8";
  1344.  
  1345.         /// <summary>
  1346.         /// Metoda šifrující daný text.
  1347.         /// </summary>
  1348.         /// <param name="plainText">Text, který se má zašifrovat.</param>
  1349.         /// <returns>Zašifrovaný text.</returns>
  1350.         public static string Encrypt(string plainText)
  1351.         {
  1352.             byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
  1353.  
  1354.             byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
  1355.             var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros };
  1356.             var encryptor = symmetricKey.CreateEncryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey));
  1357.  
  1358.             byte[] cipherTextBytes;
  1359.  
  1360.             using (var memoryStream = new MemoryStream())
  1361.             {
  1362.                 using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
  1363.                 {
  1364.                     cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
  1365.                     cryptoStream.FlushFinalBlock();
  1366.                     cipherTextBytes = memoryStream.ToArray();
  1367.                     cryptoStream.Close();
  1368.                 }
  1369.                 memoryStream.Close();
  1370.             }
  1371.             return Convert.ToBase64String(cipherTextBytes);
  1372.         }
  1373.  
  1374.         /// <summary>
  1375.         /// Metoda dešifrující daný text.
  1376.         /// </summary>
  1377.         /// <param name="encryptedText">Text, který se má dešifrovat.</param>
  1378.         /// <returns>Dešifrovaný text.</returns>
  1379.         public static string Decrypt(string encryptedText)
  1380.         {
  1381.             byte[] cipherTextBytes = Convert.FromBase64String(encryptedText);
  1382.             byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
  1383.             var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.None };
  1384.  
  1385.             var decryptor = symmetricKey.CreateDecryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey));
  1386.             var memoryStream = new MemoryStream(cipherTextBytes);
  1387.             var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
  1388.             byte[] plainTextBytes = new byte[cipherTextBytes.Length];
  1389.  
  1390.             int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
  1391.             memoryStream.Close();
  1392.             cryptoStream.Close();
  1393.             return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount).TrimEnd("\0".ToCharArray());
  1394.         }
  1395.     }
  1396. }
  1397.  
  1398.  
  1399.  
  1400. /// Soubor LoginForm1.cs
  1401.  
  1402. using System;
  1403. using System.Collections.Generic;
  1404. using System.Windows.Forms;
  1405.  
  1406. namespace Mail_Agent_2017
  1407. {
  1408.     // TO-DO: Fade-in efekty u všech součásti formuláře, fade-out efekt pro chybovou hlášku.
  1409.  
  1410.     /// <summary>
  1411.     /// První přihlašovací okno.
  1412.     /// </summary>
  1413.     public partial class LoginForm1 : Form
  1414.     {
  1415.         Prihlaseni aktualniPrihlaseni;
  1416.         Stack<Form> prihlasovaciProces;
  1417.         public LoginForm1(Prihlaseni aktualniPrihlaseni, Stack<Form> prihlasovaciProces)
  1418.         {            
  1419.             InitializeComponent();
  1420.             this.aktualniPrihlaseni = aktualniPrihlaseni;
  1421.             this.prihlasovaciProces = prihlasovaciProces;
  1422.             AdresaTextbox.Text = aktualniPrihlaseni.email; // Toto je zde pro případ, kdyby se uživatel vracel do tohoto okna.
  1423.         }
  1424.  
  1425.         /// <summary>
  1426.         /// Metoda, která se spustí po kliknutí na tlačítko "Dále" na první přihlašovací obrazovce.
  1427.         /// Kotroluje, zdali má zadaná e-mailová adresa správný formát a v případě úspěchu odkáže uživatele na další přihlašovací obrazovku.
  1428.         /// </summary>
  1429.         private void DaleButton_Click(object sender, EventArgs e)
  1430.         {
  1431.            
  1432.             try
  1433.             {
  1434.                 if (!PrihlaseniUtility.SpravnyFormatAdresy(AdresaTextbox.Text))
  1435.                     throw new ChybneZadaniException("E-mailová adresa má chybný formát.");
  1436.             }
  1437.  
  1438.             catch (Exception ex)
  1439.             {
  1440.                 ChyboveOknoLabel.Show();
  1441.                 ChyboveOknoLabel.Text = ex.Message;
  1442.                 ZobrazeniChybyTimer.Enabled = true;
  1443.                 return;
  1444.             }
  1445.  
  1446.             aktualniPrihlaseni.email = AdresaTextbox.Text;
  1447.             prihlasovaciProces.Push(new LoginForm2(aktualniPrihlaseni, prihlasovaciProces));
  1448.             this.Close();
  1449.         }
  1450.  
  1451.         /// <summary>
  1452.         /// Skryje chybovou hlášku po uplynutí deseti sekund.
  1453.         /// </summary>
  1454.         private void ZobrazeniChybyTimer_Tick(object sender, EventArgs e)
  1455.         {
  1456.             ZobrazeniChybyTimer.Enabled = false;
  1457.             ChyboveOknoLabel.Hide();
  1458.         }
  1459.     }
  1460. }
  1461.  
  1462.  
  1463.  
  1464.  
  1465. /// Soubor LoginForm2.cs
  1466.  
  1467. using System;
  1468. using System.Collections.Generic;
  1469. using System.Drawing;
  1470. using System.Threading.Tasks;
  1471. using System.Windows.Forms;
  1472. using ImapX;
  1473. using System.Threading;
  1474.  
  1475. namespace Mail_Agent_2017
  1476. {
  1477.     /// <summary>
  1478.     /// Druhé přihlašovací okno.
  1479.     /// </summary>
  1480.     public partial class LoginForm2 : Form
  1481.     {
  1482.         Prihlaseni aktualniPrihlaseni;
  1483.         Stack<Form> prihlasovaciProces;
  1484.         ESP seznamESP;
  1485.  
  1486.         /// <summary>
  1487.         /// Konstruktor se stará zejména o vyplnění údajů o známých ESP, upravuje dle toho UI.
  1488.         /// </summary>
  1489.         public LoginForm2(Prihlaseni aktualniPrihlaseni, Stack<Form> prihlasovaciProces)
  1490.         {
  1491.             InitializeComponent();
  1492.             this.aktualniPrihlaseni = aktualniPrihlaseni;
  1493.             this.prihlasovaciProces = prihlasovaciProces;
  1494.             this.EmailAddressTextbox.Text = aktualniPrihlaseni.email;
  1495.             this.HesloTextbox.Text = aktualniPrihlaseni.heslo;
  1496.             this.JmenoTextbox.Text = aktualniPrihlaseni.jmeno;
  1497.             this.seznamESP = new ESP(); // Načtení tabulky známých ESP.
  1498.  
  1499.             // Aplikace zkontroluje, zdali se uživatelův ESP nenachází v tabulce známých ESP.
  1500.             if (seznamESP.NajdiVhodnehoESP(aktualniPrihlaseni.email.Split('@')[1]) != null)
  1501.             {
  1502.                 OznameniLabel.Text = "Váš poskytovatel e-mailových služeb je nám známý. Některé údaje budou automaticky předvyplněny.";
  1503.  
  1504.                 UpravyCheckbox.Checked = false;
  1505.  
  1506.                 // Musíme řešit pomocí var, protože třída ESP_Zaznam je interní.
  1507.                 var aktualniESP = seznamESP.NajdiVhodnehoESP(aktualniPrihlaseni.email.Split('@')[1]);
  1508.  
  1509.                 ImapServerTextbox.Text = aktualniESP.ImapServer;
  1510.                 ImapServerTextbox.Enabled = UpravyCheckbox.Checked;
  1511.  
  1512.                 ImapPortTextbox.Text = aktualniESP.ImapPort.ToString();
  1513.                 ImapPortTextbox.Enabled = UpravyCheckbox.Checked;
  1514.  
  1515.                 SmtpServerTextbox.Text = aktualniESP.SmtpServer;
  1516.                 SmtpServerTextbox.Enabled = UpravyCheckbox.Checked;
  1517.  
  1518.                 SmtpPortTextbox.Text = aktualniESP.SmtpPort.ToString();
  1519.                 SmtpPortTextbox.Enabled = UpravyCheckbox.Checked;
  1520.  
  1521.                 ImapSslCheckbox.Checked = aktualniESP.ImapSsl;
  1522.                 ImapSslCheckbox.Enabled = UpravyCheckbox.Checked;
  1523.  
  1524.                 SmtpSslCheckbox.Checked = aktualniESP.SmtpSsl;
  1525.                 SmtpSslCheckbox.Enabled = UpravyCheckbox.Checked;
  1526.  
  1527.                 SmtpAuthCheckbox.Checked = aktualniESP.SmtpAuth;
  1528.                 SmtpAuthCheckbox.Enabled = UpravyCheckbox.Checked;
  1529.             }
  1530.             else
  1531.             {
  1532.                 OznameniLabel.Text = "V případě nesnází se obraťte na Vašeho poskytovatele e-mailových služeb.";
  1533.                 UpravyCheckbox.Visible = false;
  1534.                 ZmenaLabel.Visible = false;
  1535.             }
  1536.         }
  1537.  
  1538.         /// <summary>
  1539.         /// Implementace tlačítka zpět - po stisknutí tlačítka se vrátí na předchozí přihlašovací okno.
  1540.         /// </summary>
  1541.         private void ZpetButton_Click(object sender, EventArgs e)
  1542.         {
  1543.             prihlasovaciProces.Push(new LoginForm1(aktualniPrihlaseni, prihlasovaciProces));
  1544.             this.Close();
  1545.         }
  1546.  
  1547.         /// <summary>
  1548.         /// Metoda starající se o navazování spojení se SMTP a IMAP servery.
  1549.         /// Rovněž hledá a kontroluje chyby, obeznamuje o nich uživatele.
  1550.         /// </summary>
  1551.         private async void DaleButton_Click(object sender, EventArgs e)
  1552.         {
  1553.             ZobrazeniChybyTimer.Enabled = false;
  1554.  
  1555.             aktualniPrihlaseni.heslo = HesloTextbox.Text;
  1556.             aktualniPrihlaseni.jmeno = JmenoTextbox.Text;
  1557.  
  1558.             // Zatímco budeme čekat na navázání spojení, uživateli se bude zobrazovat efekt blikajících teček při přihlašování.
  1559.             ChyboveOknoLabel.Text = "";
  1560.             NacitaniTimer.Enabled = true;
  1561.             ChyboveOknoLabel.ForeColor = Color.Black;
  1562.             ChyboveOknoLabel.Show();
  1563.  
  1564.             // Navazování spojení rozběhneme na novém pracovním vlákně jako asynchronní metodu.
  1565.             await Task.Run(() =>
  1566.             {
  1567.                 try
  1568.                 {
  1569.                     // Chyba: Nebyly vyplněny všechny údaje.
  1570.                     if (string.IsNullOrWhiteSpace(HesloTextbox.Text) || string.IsNullOrWhiteSpace(JmenoTextbox.Text) || string.IsNullOrWhiteSpace(ImapServerTextbox.Text) ||
  1571.                         string.IsNullOrWhiteSpace(ImapPortTextbox.Text) || string.IsNullOrWhiteSpace(SmtpServerTextbox.Text) || string.IsNullOrWhiteSpace(SmtpPortTextbox.Text))
  1572.                         throw new ChybneZadaniException("Nebyly vyplněny všechny údaje.");
  1573.  
  1574.                     // Chyba: Porty neobsahují číselné hodnoty.
  1575.                     if (!int.TryParse(ImapPortTextbox.Text, out int imap) || !int.TryParse(SmtpPortTextbox.Text, out int smtp))
  1576.                         throw new ChybneZadaniException("Porty byly vyplněny chybně.");
  1577.  
  1578.                     // Inicializace SMTP a IMAP spojení.
  1579.                     aktualniPrihlaseni.ImapPripojeni = new ImapClient(ImapServerTextbox.Text, int.Parse(ImapPortTextbox.Text), ImapSslCheckbox.Checked, ImapSslCheckbox.Checked);
  1580.                     aktualniPrihlaseni.SmtpPripojeni = PrihlaseniUtility.SmtpConnect(SmtpServerTextbox.Text, int.Parse(SmtpPortTextbox.Text), SmtpSslCheckbox.Checked,
  1581.                                                                                      SmtpAuthCheckbox.Checked, aktualniPrihlaseni.email, HesloTextbox.Text);
  1582.  
  1583.                     // Chyba: Nepodařilo se navázat spojení s IMAP serverem.
  1584.                     if (!aktualniPrihlaseni.ImapPripojeni.Connect())
  1585.                         throw new ImapConnectFailException("Chyba při navazování spojení s IMAP serverem.");
  1586.  
  1587.                     // Chyba: Špatná e-mailová adresa nebo heslo.
  1588.                     else if (!aktualniPrihlaseni.ImapPripojeni.Login(aktualniPrihlaseni.email, aktualniPrihlaseni.heslo))
  1589.                         throw new SpatneHesloException("Heslo a e-mailová adresa se neshodují.");
  1590.  
  1591.                     // Chyba: Nepodařilo se navázat spojení se SMTP serverem. Pro otestování spojení se SMTP serverem pošle testovací zprávu.
  1592.                     else if (aktualniPrihlaseni.SmtpPripojeni == null)
  1593.                         throw new SmtpConnectFailException("Chyba při navazování spojení se SMTP serverem.");
  1594.                 }
  1595.  
  1596.                 catch (Exception ex)
  1597.                 {
  1598.                     // Zkontrolujeme, jestli se jedná o výjimku vyvolanou námi.
  1599.                     if (ex is ChybneZadaniException || ex is SmtpConnectFailException || ex is ImapConnectFailException || ex is SpatneHesloException)
  1600.  
  1601.                         // Zobrazení chybové hlášky. Texty labelů (a všeobecně celé GUI) se můžou měnit pouze z UI vlákna, proto je to řešeno pomocí MethodInvokeru.                        
  1602.                         this.BeginInvoke(new MethodInvoker(delegate ()
  1603.                         {
  1604.                             // Zastavení blikajích teček
  1605.                             NacitaniTimer.Enabled = false;
  1606.                             ChyboveOknoLabel.Text = ex.Message; ChyboveOknoLabel.ForeColor = Color.Red;
  1607.                             ZobrazeniChybyTimer.Enabled = true;
  1608.                         }));
  1609.  
  1610.                     // Pokud se jedná o jinou výjimku, tak prostě nebudeme uživateli nic tajit a řekneme mu tím, jak neumíme programovat.
  1611.                     else throw;
  1612.                 }
  1613.  
  1614.                 finally
  1615.                 {
  1616.                     // Toto je zde pro efekt.
  1617.                     // Poznámka autora: Když už jsem si dal tu práci s programováním blikajících teček, tak ať jsou alespoň vidět i v případě, že je spojení navázáno rychle.
  1618.                     Thread.Sleep(2500);
  1619.                 }
  1620.             });
  1621.  
  1622.             // Výsledek z pracovního vlákna poznáme snadno, a to tak, že pouze v případě chyby se rozběhne tento timer.
  1623.             if (ZobrazeniChybyTimer.Enabled)
  1624.                 return;
  1625.  
  1626.             // Po úspěšném navázání spojení přidá záznam do tabulky známých ESP, pokud tam již není.
  1627.             if (seznamESP.NajdiVhodnehoESP(aktualniPrihlaseni.email.Split('@')[1]) == null)
  1628.                 seznamESP.PridejZaznamOESP(aktualniPrihlaseni.email.Split('@')[1], ImapServerTextbox.Text, int.Parse(ImapPortTextbox.Text), ImapSslCheckbox.Checked,
  1629.                                            SmtpServerTextbox.Text, int.Parse(SmtpPortTextbox.Text), SmtpSslCheckbox.Checked, SmtpAuthCheckbox.Checked);
  1630.  
  1631.             prihlasovaciProces.Push(new LoginForm3(aktualniPrihlaseni, prihlasovaciProces));
  1632.             this.Close();
  1633.         }
  1634.  
  1635.         /// <summary>
  1636.         /// Skryje chybovou hlášku po uplynutí deseti sekund.
  1637.         /// </summary>
  1638.         private void ZobrazeniChybyTimer_Tick(object sender, EventArgs e)
  1639.         {
  1640.             ZobrazeniChybyTimer.Enabled = false;
  1641.             ChyboveOknoLabel.Hide();
  1642.         }
  1643.        
  1644.         /// <summary>
  1645.         /// Metoda, která obsluhuje tlačítko, které povoluje změny předvyplněných údajů.
  1646.         /// </summary>
  1647.         private void ZmenaCB_CheckedChanged(object sender, EventArgs e)
  1648.         {
  1649.             ImapServerTextbox.Enabled = UpravyCheckbox.Checked;
  1650.             ImapPortTextbox.Enabled = UpravyCheckbox.Checked;
  1651.             SmtpServerTextbox.Enabled = UpravyCheckbox.Checked;
  1652.             SmtpPortTextbox.Enabled = UpravyCheckbox.Checked;
  1653.             ImapSslCheckbox.Enabled = UpravyCheckbox.Checked;
  1654.             SmtpSslCheckbox.Enabled = UpravyCheckbox.Checked;
  1655.             SmtpAuthCheckbox.Enabled = UpravyCheckbox.Checked;
  1656.         }
  1657.  
  1658.         /// <summary>
  1659.         /// Metoda pro efekt, zobrazuje efekt blikajících teček při přihlašování.
  1660.         /// </summary>
  1661.         private void NacitaniTimer_Tick(object sender, EventArgs e)
  1662.         {
  1663.             if (ChyboveOknoLabel.Text.Length >= 75 || ChyboveOknoLabel.Text.Length == 0)
  1664.                 ChyboveOknoLabel.Text = "Počkejte, prosím. Toto může chvíli trvat. Probíhá navazování komunikace ";
  1665.             else
  1666.                 ChyboveOknoLabel.Text += ".";
  1667.         }
  1668.     }
  1669. }
  1670.  
  1671.  
  1672.  
  1673. /// Soubor LoginForm3.cs
  1674.  
  1675. using System;
  1676. using System.Collections.Generic;
  1677. using System.Windows.Forms;
  1678.  
  1679. namespace Mail_Agent_2017
  1680. {
  1681.     /// <summary>
  1682.     /// Třetí přihlašovací okno.
  1683.     /// </summary>
  1684.     public partial class LoginForm3 : Form
  1685.     {
  1686.         Prihlaseni aktualniPrihlaseni;
  1687.         Stack<Form> prihlasovaciProces;
  1688.         public LoginForm3(Prihlaseni aktualniPrihlaseni, Stack<Form> prihlasovaciProces)
  1689.         {
  1690.             InitializeComponent();
  1691.             this.aktualniPrihlaseni = aktualniPrihlaseni;
  1692.             this.prihlasovaciProces = prihlasovaciProces;
  1693.  
  1694.             PopisLabel.Text = "Při této příležitosti Vám byla zaslána testovací zpráva.\n" +
  1695.                               "Nyní můžete vstoupit do aplikace a využívat všechny její funkce.\n\n" +
  1696.                               "Děkujeme Vám, " + aktualniPrihlaseni.jmeno.Split(' ')[0] + ", že jste si vybral Mail Agent 2017.";
  1697.         }
  1698.  
  1699.         /// <summary>
  1700.         /// Implementace tlačítka zpět - po stisknutí tlačítka se vrátí na předchozí přihlašovací okno.
  1701.         /// </summary>
  1702.         private void ZpetButton_Click(object sender, EventArgs e)
  1703.         {
  1704.             prihlasovaciProces.Push(new LoginForm2(aktualniPrihlaseni, prihlasovaciProces));
  1705.             this.Close();
  1706.         }        
  1707.  
  1708.         /// <summary>
  1709.         /// Přesměruje uživatele do aplikace.
  1710.         /// </summary>
  1711.         private void DaleButton_Click(object sender, EventArgs e)
  1712.         {
  1713.             this.Close();
  1714.         }
  1715.     }
  1716. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement