Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// Soubor Program.cs
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- namespace Mail_Agent_2017
- {
- static class Program
- {
- /// <summary>
- /// Hlavní vstupní bod aplikace.
- /// </summary>
- [STAThread]
- static void Main()
- {
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run(new MainForm());
- }
- }
- }
- /// Soubor MainForm.cs
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- namespace Mail_Agent_2017
- {
- /// <summary>
- /// Hlavní okno celé aplikace.
- /// </summary>
- public partial class MainForm : Form
- {
- Prihlaseni aktualniPrihlaseni;
- /// <summary>
- /// Konstruktor se stará o hlavní inicializaci, stahuje emaily, popř. spouští přihlašovací proces.
- /// </summary>
- public MainForm()
- {
- this.aktualniPrihlaseni = new Prihlaseni();
- PrihlaseniUtility.prihlasovaciProces(ref aktualniPrihlaseni);
- InitializeComponent();
- }
- /// <summary>
- /// Odhlásí se a spustí nový přihlašovací proces.
- /// </summary>
- private void odhlásitSeToolStripMenuItem_Click(object sender, EventArgs e)
- {
- this.Hide();
- aktualniPrihlaseni.OdhlasitSe();
- PrihlaseniUtility.prihlasovaciProces(ref aktualniPrihlaseni);
- }
- /// <summary>
- /// Ukončí aplikaci.
- /// </summary>
- private void ukončitToolStripMenuItem_Click(object sender, EventArgs e)
- {
- Environment.Exit(0);
- }
- /// <summary>
- /// Otevře okno na odeslání emailu.
- /// </summary>
- private void novýEmailToolStripMenuItem_Click(object sender, EventArgs e)
- {
- new SendForm(aktualniPrihlaseni).ShowDialog();
- }
- }
- }
- /// Soubor SendForm.cs
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net.Mail;
- using System.Windows.Forms;
- namespace Mail_Agent_2017
- {
- /// <summary>
- /// Odesílání emailu.
- /// </summary>
- public partial class SendForm : Form
- {
- // TO-DO: Opravdový HTML editor pro textové pole. Bohužel, s mými aktuálními znalostmi jazyka nejspíš neproveditelné.
- Prihlaseni aktualniPrihlaseni;
- MailMessage emailovaZprava;
- AttachmentForm prilohy;
- Stack<string> undoZasobnik;
- Stack<string> redoZasobnik;
- public SendForm(Prihlaseni aktualniPrihlaseni)
- {
- InitializeComponent();
- #region Inicializace Tooltipů k jednotlivým položkám
- // Přijde mi jednodušší toto napsat "ručně", než to dělat pomocí designeru.
- ToolTip ToToolTip = new ToolTip();
- ToToolTip.UseFading = true;
- ToToolTip.UseAnimation = true;
- ToToolTip.ReshowDelay = 500;
- ToToolTip.InitialDelay = 500;
- ToToolTip.AutoPopDelay = 15000;
- ToToolTip.ShowAlways = true;
- ToToolTip.ToolTipIcon = ToolTipIcon.Info;
- ToToolTip.SetToolTip(ToTextbox, "Více příjemců oddělujte středníkem.");
- ToolTip CcToolTip = new ToolTip();
- CcToolTip.UseFading = true;
- CcToolTip.UseAnimation = true;
- CcToolTip.ReshowDelay = 500;
- CcToolTip.InitialDelay = 500;
- CcToolTip.AutoPopDelay = 15000;
- CcToolTip.ShowAlways = true;
- CcToolTip.ToolTipIcon = ToolTipIcon.Info;
- CcToolTip.SetToolTip(CcTextbox, "Více příjemců oddělujte středníkem.");
- ToolTip BccToolTip = new ToolTip();
- BccToolTip.UseFading = true;
- BccToolTip.UseAnimation = true;
- BccToolTip.ReshowDelay = 500;
- BccToolTip.InitialDelay = 500;
- BccToolTip.AutoPopDelay = 15000;
- BccToolTip.ShowAlways = true;
- BccToolTip.ToolTipIcon = ToolTipIcon.Info;
- BccToolTip.SetToolTip(BccTextbox, "Více příjemců oddělujte středníkem.");
- ToolTip SubjectToolTip = new ToolTip();
- SubjectToolTip.UseFading = true;
- SubjectToolTip.UseAnimation = true;
- SubjectToolTip.ReshowDelay = 500;
- SubjectToolTip.InitialDelay = 500;
- SubjectToolTip.AutoPopDelay = 15000;
- SubjectToolTip.ShowAlways = true;
- SubjectToolTip.ToolTipIcon = ToolTipIcon.Info;
- 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.");
- // 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.
- ToolTip HtmlToolTip = new ToolTip();
- HtmlToolTip.UseFading = true;
- HtmlToolTip.UseAnimation = true;
- HtmlToolTip.ReshowDelay = 500;
- HtmlToolTip.InitialDelay = 500;
- HtmlToolTip.AutoPopDelay = 15000;
- HtmlToolTip.ShowAlways = true;
- HtmlToolTip.ToolTipIcon = ToolTipIcon.Info;
- HtmlToolTip.SetToolTip(HtmlCheckbox, "V případě zaškrnutí této možnosti můžete psát e-mail v jazyce HTML 5.");
- #region Tooltipy k editoru
- ToolTip BoldToolTip = new ToolTip();
- BoldToolTip.UseFading = true;
- BoldToolTip.UseAnimation = true;
- BoldToolTip.ReshowDelay = 500;
- BoldToolTip.InitialDelay = 500;
- BoldToolTip.AutoPopDelay = 15000;
- BoldToolTip.ShowAlways = true;
- BoldToolTip.ToolTipIcon = ToolTipIcon.Info;
- BoldToolTip.SetToolTip(BoldButton, "Umožňuje psát tučně.");
- ToolTip ItalicToolTip = new ToolTip();
- ItalicToolTip.UseFading = true;
- ItalicToolTip.UseAnimation = true;
- ItalicToolTip.ReshowDelay = 500;
- ItalicToolTip.InitialDelay = 500;
- ItalicToolTip.AutoPopDelay = 15000;
- ItalicToolTip.ShowAlways = true;
- ItalicToolTip.ToolTipIcon = ToolTipIcon.Info;
- ItalicToolTip.SetToolTip(ItalicButton, "Umožňuje psát kurzívou.");
- ToolTip UnderlineToolTip = new ToolTip();
- UnderlineToolTip.UseFading = true;
- UnderlineToolTip.UseAnimation = true;
- UnderlineToolTip.ReshowDelay = 500;
- UnderlineToolTip.InitialDelay = 500;
- UnderlineToolTip.AutoPopDelay = 15000;
- UnderlineToolTip.ShowAlways = true;
- UnderlineToolTip.ToolTipIcon = ToolTipIcon.Info;
- UnderlineToolTip.SetToolTip(UnderlineButton, "Umožňuje podtrhnout text.");
- ToolTip FontToolTip = new ToolTip();
- FontToolTip.UseFading = true;
- FontToolTip.UseAnimation = true;
- FontToolTip.ReshowDelay = 500;
- FontToolTip.InitialDelay = 500;
- FontToolTip.AutoPopDelay = 15000;
- FontToolTip.ShowAlways = true;
- FontToolTip.ToolTipIcon = ToolTipIcon.Info;
- FontToolTip.SetToolTip(FontButton, "Otevře nabídkou se změnou písma.");
- ToolTip FontColorToolTip = new ToolTip();
- FontColorToolTip.UseFading = true;
- FontColorToolTip.UseAnimation = true;
- FontColorToolTip.ReshowDelay = 500;
- FontColorToolTip.InitialDelay = 500;
- FontColorToolTip.AutoPopDelay = 15000;
- FontColorToolTip.ShowAlways = true;
- FontColorToolTip.ToolTipIcon = ToolTipIcon.Info;
- FontColorToolTip.SetToolTip(FontColorButton, "Otevře nabídku se změnou barvy písma.");
- ToolTip LeftAlignmentToolTip = new ToolTip();
- LeftAlignmentToolTip.UseFading = true;
- LeftAlignmentToolTip.UseAnimation = true;
- LeftAlignmentToolTip.ReshowDelay = 500;
- LeftAlignmentToolTip.InitialDelay = 500;
- LeftAlignmentToolTip.AutoPopDelay = 15000;
- LeftAlignmentToolTip.ShowAlways = true;
- LeftAlignmentToolTip.ToolTipIcon = ToolTipIcon.Info;
- LeftAlignmentToolTip.SetToolTip(LeftAlignmentButton, "Zarovná text doleva.");
- ToolTip RightAlignmentToolTip = new ToolTip();
- RightAlignmentToolTip.UseFading = true;
- RightAlignmentToolTip.UseAnimation = true;
- RightAlignmentToolTip.ReshowDelay = 500;
- RightAlignmentToolTip.InitialDelay = 500;
- RightAlignmentToolTip.AutoPopDelay = 15000;
- RightAlignmentToolTip.ShowAlways = true;
- RightAlignmentToolTip.ToolTipIcon = ToolTipIcon.Info;
- RightAlignmentToolTip.SetToolTip(RightAlignmentButton, "Zarovná text doprava.");
- ToolTip CenterAlignmentToolTip = new ToolTip();
- CenterAlignmentToolTip.UseFading = true;
- CenterAlignmentToolTip.UseAnimation = true;
- CenterAlignmentToolTip.ReshowDelay = 500;
- CenterAlignmentToolTip.InitialDelay = 500;
- CenterAlignmentToolTip.AutoPopDelay = 15000;
- CenterAlignmentToolTip.ShowAlways = true;
- CenterAlignmentToolTip.ToolTipIcon = ToolTipIcon.Info;
- CenterAlignmentToolTip.SetToolTip(CenterAlignmentButton, "Zarovná text na střed.");
- ToolTip HyperlinkToolTip = new ToolTip();
- HyperlinkToolTip.UseFading = true;
- HyperlinkToolTip.UseAnimation = true;
- HyperlinkToolTip.ReshowDelay = 500;
- HyperlinkToolTip.InitialDelay = 500;
- HyperlinkToolTip.AutoPopDelay = 15000;
- HyperlinkToolTip.ShowAlways = true;
- HyperlinkToolTip.ToolTipIcon = ToolTipIcon.Info;
- HyperlinkToolTip.SetToolTip(HyperlinkButton, "Vloží hypertextový odkaz.");
- ToolTip ImageToolTip = new ToolTip();
- ImageToolTip.UseFading = true;
- ImageToolTip.UseAnimation = true;
- ImageToolTip.ReshowDelay = 500;
- ImageToolTip.InitialDelay = 500;
- ImageToolTip.AutoPopDelay = 15000;
- ImageToolTip.ShowAlways = true;
- ImageToolTip.ToolTipIcon = ToolTipIcon.Info;
- ImageToolTip.SetToolTip(ImageButton, "Vloží obrázek.");
- ToolTip CopyToolTip = new ToolTip();
- CopyToolTip.UseFading = true;
- CopyToolTip.UseAnimation = true;
- CopyToolTip.ReshowDelay = 500;
- CopyToolTip.InitialDelay = 500;
- CopyToolTip.AutoPopDelay = 15000;
- CopyToolTip.ShowAlways = true;
- CopyToolTip.ToolTipIcon = ToolTipIcon.Info;
- CopyToolTip.SetToolTip(CopyButton, "Zkopíruje vybraný text.");
- ToolTip PasteToolTip = new ToolTip();
- PasteToolTip.UseFading = true;
- PasteToolTip.UseAnimation = true;
- PasteToolTip.ReshowDelay = 500;
- PasteToolTip.InitialDelay = 500;
- PasteToolTip.AutoPopDelay = 15000;
- PasteToolTip.ShowAlways = true;
- PasteToolTip.ToolTipIcon = ToolTipIcon.Info;
- PasteToolTip.SetToolTip(PasteButton, "Vloží text ve schránce na aktuální pozici kurzoru.");
- ToolTip UndoToolTip = new ToolTip();
- UndoToolTip.UseFading = true;
- UndoToolTip.UseAnimation = true;
- UndoToolTip.ReshowDelay = 500;
- UndoToolTip.InitialDelay = 500;
- UndoToolTip.AutoPopDelay = 15000;
- UndoToolTip.ShowAlways = true;
- UndoToolTip.ToolTipIcon = ToolTipIcon.Info;
- UndoToolTip.SetToolTip(UndoButton, "Tlačítko zpět.");
- ToolTip RedoToolTip = new ToolTip();
- RedoToolTip.UseFading = true;
- RedoToolTip.UseAnimation = true;
- RedoToolTip.ReshowDelay = 500;
- RedoToolTip.InitialDelay = 500;
- RedoToolTip.AutoPopDelay = 15000;
- RedoToolTip.ShowAlways = true;
- RedoToolTip.ToolTipIcon = ToolTipIcon.Info;
- RedoToolTip.SetToolTip(RedoButton, "Tlačítko vpřed.");
- #endregion
- #endregion
- this.redoZasobnik = new Stack<string>();
- this.undoZasobnik = new Stack<string>();
- this.aktualniPrihlaseni = aktualniPrihlaseni;
- this.emailovaZprava = new MailMessage();
- this.prilohy = new AttachmentForm();
- }
- /// <summary>
- /// Tlačítko, které smaže obsah všech formulářů.
- /// </summary>
- private void DeleteButton_Click(object sender, EventArgs e)
- {
- ToTextbox.Text = "";
- CcTextbox.Text = "";
- BccTextbox.Text = "";
- SubjectTextbox.Text = "";
- TextTextarea.Text = "";
- }
- /// <summary>
- /// Tlačítko spravující veškeré dění ohledně příloh.
- /// </summary>
- private void PrilohyButton_Click(object sender, EventArgs e)
- {
- prilohy.ShowDialog();
- // Počet přiložených souborů musíme řešit takto "složitě", neboť v seznamu příloh je poslední příloha neinicializovaná.
- // 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.
- var pocetSouboru = (prilohy.seznamPriloh.Last().label.Text != "...") ? prilohy.seznamPriloh.Count.ToString() : (prilohy.seznamPriloh.Count - 1).ToString();
- // 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.
- if ((prilohy.seznamPriloh.Last().label.Text != "...") ? true : prilohy.seznamPriloh.Count - 1 > 0)
- // Čeština je "krásná" řeč.
- switch (pocetSouboru)
- {
- case "1": PrilohaLabel.Text = "K e-mailu je momentálně přiložen 1 soubor."; break;
- case "2": case "3": case "4": PrilohaLabel.Text = "K e-mailu jsou momentálně přiloženy " + pocetSouboru + " soubory."; break;
- default: PrilohaLabel.Text = "K e-mailu je momentálně přiloženo " + pocetSouboru + " souborů."; break;
- }
- else
- PrilohaLabel.Text = "";
- }
- /// <summary>
- /// Umožní uživateli psát email v jazyce HTML 5. Poskytuje mu k tomu drobné utility, de facto usnadnění.
- /// </summary>
- private void HtmlCheckbox_CheckedChanged(object sender, EventArgs e)
- {
- if (HtmlCheckbox.Checked)
- MessageBox.Show("Zvažte použití této možnosti. E-mailový klient Vašeho adresáta nemusí tuto možnost podporovat.");
- this.undoZasobnik = new Stack<string>();
- this.redoZasobnik = new Stack<string>();
- UndoTimer.Enabled = HtmlCheckbox.Enabled;
- this.undoZasobnik.Push("");
- emailovaZprava.IsBodyHtml = HtmlCheckbox.Checked;
- NahledButton.Visible = HtmlCheckbox.Checked;
- BoldButton.Visible = HtmlCheckbox.Checked;
- ItalicButton.Visible = HtmlCheckbox.Checked;
- UnderlineButton.Visible = HtmlCheckbox.Checked;
- FontButton.Visible = HtmlCheckbox.Checked;
- FontColorButton.Visible = HtmlCheckbox.Checked;
- LeftAlignmentButton.Visible = HtmlCheckbox.Checked;
- CenterAlignmentButton.Visible = HtmlCheckbox.Checked;
- RightAlignmentButton.Visible = HtmlCheckbox.Checked;
- HyperlinkButton.Visible = HtmlCheckbox.Checked;
- ImageButton.Visible = HtmlCheckbox.Checked;
- }
- /// <summary>
- /// Zobrazí náhled HTML kódu.
- /// </summary>
- private void NahledButton_Click(object sender, EventArgs e)
- {
- new HtmlPreviewForm(TextTextarea.Text).ShowDialog();
- }
- #region Implementace obsluh tlačítek usnadňující HTML zadávání.
- // 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.
- // Třeba to někdy časem dotáhnu, momentálně není na takové "kraviny" čas.
- private void DekoraceButton_Click(object sender, EventArgs e)
- {
- int start = TextTextarea.SelectionStart;
- switch (((Button)sender).Name)
- {
- case "BoldButton": TextTextarea.Text = TextTextarea.Text.Insert(TextTextarea.SelectionStart, "<b></b>"); break;
- case "ItalicButton": TextTextarea.Text = TextTextarea.Text.Insert(TextTextarea.SelectionStart, "<i></i>"); break;
- case "UnderlineButton": TextTextarea.Text = TextTextarea.Text.Insert(TextTextarea.SelectionStart, "<u></u>"); break;
- }
- TextTextarea.Focus();
- TextTextarea.SelectionStart = start + 3;
- }
- private void FontButton_Click(object sender, EventArgs e)
- {
- // Na font se uživatele zeptáme pomocí font dialogu.
- FontDialog font = new FontDialog();
- font.ShowEffects = false;
- if (font.ShowDialog() == DialogResult.OK)
- {
- int start = TextTextarea.SelectionStart;
- string fontToHtml = "<span style = \"font-family: " + font.Font.ToString().Split('=')[1].Split(',')[0] + "; font-size: " + font.Font.ToString().Split('=')[2].Split(',')[0] + "px;\">";
- TextTextarea.Text = TextTextarea.Text.Insert(start, fontToHtml + "</span>");
- TextTextarea.Focus();
- TextTextarea.SelectionStart = start + fontToHtml.Length;
- }
- }
- private void FontColorButton_Click(object sender, EventArgs e)
- {
- // Na barvu se uživatele zeptáme pomocí color dialogu.
- ColorDialog barva = new ColorDialog();
- barva.AllowFullOpen = true;
- if (barva.ShowDialog() == DialogResult.OK)
- {
- int start = TextTextarea.SelectionStart;
- string barvaToHtml = "<span style = \"color: rgb(" + barva.Color.R + ", " + barva.Color.G + ", " + barva.Color.B + ");\">";
- TextTextarea.Text = TextTextarea.Text.Insert(start, barvaToHtml + "</span>");
- TextTextarea.Focus();
- TextTextarea.SelectionStart = start + barvaToHtml.Length;
- }
- }
- private void AlignmentButton_Click(object sender, EventArgs e)
- {
- int start = TextTextarea.SelectionStart;
- switch (((Button)sender).Name)
- {
- case "LeftAlignmentButton":
- TextTextarea.Text = TextTextarea.Text.Insert(start, "<div style=\"text-align: left;\"></div>");
- start += 31;
- break;
- case "RightAlignmentButton":
- TextTextarea.Text = TextTextarea.Text.Insert(start, "<div style=\"text-align: right;\"></div>");
- start += 32;
- break;
- case "CenterAlignmentButton":
- TextTextarea.Text = TextTextarea.Text.Insert(start, "<div style=\"text-align: center;\"></div>");
- start += 33;
- break;
- }
- TextTextarea.SelectionStart = start;
- TextTextarea.Focus();
- }
- private void HyperlinkButton_Click(object sender, EventArgs e)
- {
- string odkaz;
- string popisek;
- try
- {
- if ((odkaz = new Prompt().ShowDialog("Vložte odkaz", "Mail Agent 2017 - Vložit hypertextový odkaz")) == null)
- throw new ChybneZadaniException();
- if ((popisek = new Prompt().ShowDialog("Vložte popisek odkazu", "Mail Agent 2017 - Vložit hypertextový odkaz")) == null)
- throw new ChybneZadaniException();
- }
- catch
- { return; }
- int start = TextTextarea.SelectionStart;
- string odkazToHtml = "<a href = \"" + odkaz + "\">" + popisek + "</a>";
- TextTextarea.Text = TextTextarea.Text.Insert(start, odkazToHtml);
- TextTextarea.Focus();
- TextTextarea.SelectionStart = start + odkazToHtml.Length;
- }
- private void ImageButton_Click(object sender, EventArgs e)
- {
- string odkaz;
- try
- {
- if ((odkaz = new Prompt().ShowDialog("Vložte odkaz na obrázek", "Mail Agent 2017 - Vložit obrázek")) == null)
- throw new ChybneZadaniException();
- }
- catch
- { return; }
- int start = TextTextarea.SelectionStart;
- string obrazekToHtml = "<img src = \"" + odkaz + "\">";
- TextTextarea.Text = TextTextarea.Text.Insert(start, obrazekToHtml);
- TextTextarea.Focus();
- TextTextarea.SelectionStart = start + obrazekToHtml.Length;
- }
- private void CopyButton_Click(object sender, EventArgs e)
- {
- Clipboard.SetText(TextTextarea.Text.Substring(TextTextarea.SelectionStart, TextTextarea.SelectionLength));
- TextTextarea.Focus();
- }
- private void PasteButton_Click(object sender, EventArgs e)
- {
- int start = TextTextarea.SelectionStart;
- TextTextarea.Text = TextTextarea.Text.Insert(start, Clipboard.GetText());
- TextTextarea.Focus();
- TextTextarea.SelectionStart = start + Clipboard.GetText().Length;
- }
- #endregion
- #region Implementace tlačítek zpět a vpřed.
- /*
- * Tlačítka si implementujeme po svém, aby splňovaly to, co od nich chceme.
- * 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ě.
- * 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.
- * V případě provedení změny po undo se redo zásobník vymaže.
- */
- private void UndoButton_Click(object sender, EventArgs e)
- {
- if (undoZasobnik.Count > 0)
- {
- redoZasobnik.Push(TextTextarea.Text);
- TextTextarea.Text = undoZasobnik.Pop();
- }
- TextTextarea.Focus();
- }
- private void RedoButton_Click(object sender, EventArgs e)
- {
- if (redoZasobnik.Count > 0)
- {
- undoZasobnik.Push(TextTextarea.Text);
- TextTextarea.Text = redoZasobnik.Pop();
- }
- TextTextarea.Focus();
- }
- private void UndoTimer_Tick(object sender, EventArgs e)
- {
- // Pokud nedošlo od posledního ticku ke změně, nemá smysl pushovat na zásobník stejnou hodnotu.
- if ((TextTextarea.Text != null || undoZasobnik.Last() != TextTextarea.Text) && redoZasobnik.Count == 0)
- undoZasobnik.Push(TextTextarea.Text);
- }
- private void TextTextarea_KeyDown(object sender, KeyEventArgs e)
- {
- if (redoZasobnik.Count > 0)
- {
- 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".
- if (TextTextarea.Text != null || undoZasobnik.First() != TextTextarea.Text)
- undoZasobnik.Push(TextTextarea.Text);
- }
- }
- #endregion
- /// <summary>
- /// Odešle e-mail na dané adresy z uživatelova e-mailu. Kontroluje chyby a nedostatky, které mohly vzniknout při psaní zprávy.
- /// </summary>
- private async void SendButton_Click(object sender, EventArgs e)
- {
- try
- {
- // Nejdříve zkontrolujeme, jestli mají e-mailové adresy správný formát.
- if (string.IsNullOrEmpty(ToTextbox.Text))
- throw new SpatneVyplnenyAdresatException("Musíte vyplnit alespoň jednoho adresáta.");
- foreach (string adresa in ToTextbox.Text.Split(';'))
- if (PrihlaseniUtility.SpravnyFormatAdresy(adresa))
- emailovaZprava.To.Add(adresa);
- else
- throw new SpatneVyplnenyAdresatException("E-mailová adresa má nesprávný formát.");
- if (!string.IsNullOrEmpty(CcTextbox.Text)) foreach (string adresa in CcTextbox.Text.Split(';'))
- if (PrihlaseniUtility.SpravnyFormatAdresy(adresa))
- emailovaZprava.CC.Add(adresa);
- else
- throw new SpatneVyplnenyAdresatException("E-mailová adresa má nesprávný formát.");
- if(!string.IsNullOrEmpty(BccTextbox.Text)) foreach (string adresa in BccTextbox.Text.Split(';'))
- if (PrihlaseniUtility.SpravnyFormatAdresy(adresa))
- emailovaZprava.Bcc.Add(adresa);
- else
- throw new SpatneVyplnenyAdresatException("E-mailová adresa má nesprávný formát.");
- // Optáme se uživatele, jestli chce opravdu odeslat email bez předmětu.
- 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)
- throw new EmailBezPredmetuException();
- emailovaZprava.Subject = SubjectTextbox.Text;
- // Optáme se uživatele, jestli chce opravdu odeslat prázdný email.
- if (string.IsNullOrEmpty(TextTextarea.Text) && MessageBox.Show("Opravdu chcete odeslat prázdný e-mail?", "Nebyl vyplněn žádný text.", MessageBoxButtons.YesNo) == DialogResult.No)
- throw new EmailBezTextuException();
- emailovaZprava.Body = TextTextarea.Text;
- }
- catch (Exception ex)
- {
- ChyboveOknoLabel.ForeColor = System.Drawing.Color.Red;
- if (ex is SpatneVyplnenyAdresatException)
- {
- ChyboveOknoLabel.Show();
- ChyboveOknoLabel.Text = ex.Message;
- ZobrazeniChybyTimer.Enabled = true;
- return;
- }
- else if (ex is EmailBezPredmetuException || ex is EmailBezTextuException)
- { return; }
- else throw; // Upřímně řečeno si momentálně nejsem vůbec jistý, jestli může nastat nějaká jiná výjimka.
- }
- // Přidáme k e-mailu přílohy, pokud existují.
- foreach (var priloha in (prilohy.seznamPriloh.Last().label.Text != "...") ? prilohy.seznamPriloh : prilohy.seznamPriloh.GetRange(0, prilohy.seznamPriloh.Count - 1))
- emailovaZprava.Attachments.Add(new Attachment(priloha.soubor.FileName));
- // Přidáme adresu odesílatele - tedy sebe.
- emailovaZprava.From = new MailAddress(aktualniPrihlaseni.email, aktualniPrihlaseni.jmeno);
- try
- {
- // 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.
- NacitaniTimer.Enabled = true;
- ZobrazeniChybyTimer.Enabled = false;
- ChyboveOknoLabel.Text = ""; ChyboveOknoLabel.ForeColor = System.Drawing.Color.Black;
- // Počkáme na pracovní vlákno, které za nás odešle e-mail, abychom zbytečně neblokovali UI.
- await aktualniPrihlaseni.SmtpPripojeni.SendMailAsync(emailovaZprava);
- }
- // 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í.
- catch
- {
- ChyboveOknoLabel.Show();
- ChyboveOknoLabel.Text = "Zprávu se nepodařilo odeslat.";
- ChyboveOknoLabel.ForeColor = System.Drawing.Color.Red;
- ZobrazeniChybyTimer.Enabled = true;
- return;
- }
- finally
- {
- NacitaniTimer.Enabled = false;
- }
- MessageBox.Show("Zpráva byla úspěšně odeslána.");
- ChyboveOknoLabel.Text = "Zpráva byla úspěšně odeslána.";
- }
- /// <summary>
- /// Skryje chybovou hlášku po uplynutí deseti sekund.
- /// </summary>
- private void ZobrazeniChybyTimer_Tick(object sender, EventArgs e)
- {
- ZobrazeniChybyTimer.Enabled = false;
- ChyboveOknoLabel.Hide();
- ChyboveOknoLabel.ForeColor = System.Drawing.Color.Black;
- }
- /// <summary>
- /// Metoda pro efekt, zobrazuje efekt blikajících teček při přihlašování.
- /// </summary>
- private void NacitaniTimer_Tick(object sender, EventArgs e)
- {
- if (ChyboveOknoLabel.Text.Length >= 71 || ChyboveOknoLabel.Text.Length == 0)
- ChyboveOknoLabel.Text = "Počkejte, prosím. Toto může chvíli trvat. Probíhá odesílání e-mailu ";
- else
- ChyboveOknoLabel.Text += ".";
- }
- }
- /// <summary>
- /// Vyrobíme si okno podobné příkazu prompt v Javascriptu.
- /// 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.
- /// </summary>
- internal class Prompt
- {
- /// <summary>
- /// Implementace metody ShowDialog. Podobná té klasické ShowDialog ze třídy Form.
- /// </summary>
- /// <param name="text">Text, který se zobrazí v labelu.</param>
- /// <param name="popis">Název okna.</param>
- /// <returns>V případě úspěchu bude okno vracet obsah textboxu.</returns>
- public string ShowDialog(string text, string popis)
- {
- Form prompt = new Form()
- {
- Width = 500,
- Height = 150,
- FormBorderStyle = FormBorderStyle.FixedDialog,
- Text = popis,
- StartPosition = FormStartPosition.CenterScreen,
- MaximizeBox = false,
- MinimizeBox = false
- };
- Label label = new Label() { Left = 50, Top = 20, Text = text, Width = 400 };
- TextBox textbox = new TextBox() { Left = 50, Top = 40, Width = 400 };
- Button tlacitko = new Button() { Text = "Potvrdit", Left = 350, Width = 100, Top = 70, DialogResult = DialogResult.OK };
- tlacitko.Click += (sender, e) => { prompt.Close(); };
- prompt.Controls.Add(textbox);
- prompt.Controls.Add(tlacitko);
- prompt.Controls.Add(label);
- prompt.AcceptButton = tlacitko;
- // V případě úspěchu bude okno vracet obsah textboxu.
- return prompt.ShowDialog() == DialogResult.OK ? textbox.Text : null;
- }
- }
- #region Definice výjimek.
- /// <summary>
- /// Definice výjimky pro nevyplněný předmět.
- /// </summary>
- internal class EmailBezPredmetuException : Exception
- {
- public EmailBezPredmetuException() : base() { }
- }
- /// <summary>
- /// Definice výjimky pro prázdný text.
- /// </summary>
- internal class EmailBezTextuException : Exception
- {
- public EmailBezTextuException() : base() { }
- }
- /// <summary>
- /// Definice výjimky pro chybně vyplněné adresáty.
- /// </summary>
- internal class SpatneVyplnenyAdresatException : Exception
- {
- public SpatneVyplnenyAdresatException(string message) : base(message) { }
- }
- #endregion
- }
- /// Soubor AttachmentForm.cs
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Windows.Forms;
- namespace Mail_Agent_2017
- {
- /// <summary>
- /// Toto okno se zobrazí, pokud chce uživatel přidat k e-mailu nějakou přílohu.
- /// </summary>
- public partial class AttachmentForm : Form
- {
- internal List<Priloha> seznamPriloh;
- public AttachmentForm()
- {
- InitializeComponent();
- seznamPriloh = new List<Priloha>();
- InicializujNovouPrilohu(null);
- }
- /// <summary>
- /// Skryje toto okno.
- /// </summary>
- private void PridatButton_Click(object sender, EventArgs e)
- {
- this.Hide();
- }
- /// <summary>
- /// Inicializuje nové ovládací prvky, díky nim může uživatel přidat novou přílohu. Zároveň upravuje GUI.
- /// </summary>
- /// <param name="cesta">Cesta k souboru, v případě, že se jedná o již načtenou přílohu.</param>
- private void InicializujNovouPrilohu(object cesta)
- {
- try
- {
- // 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.
- if (seznamPriloh.Count == 10)
- throw new PrilisMnohoPrilohException("Byl dosažen maximální počet příloh u jednoho emailu.");
- // Posune celé GUI.
- if (seznamPriloh.Count > 5)
- {
- this.ClientSize = new System.Drawing.Size(384, this.ClientSize.Height + 36);
- this.PridatButton.Location = new System.Drawing.Point(90, this.PridatButton.Location.Y + 36);
- }
- // Přidáme ovládací prvky dané přílohy do seznamu, abychom k nim mohli snadno přistupovat.
- // 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.
- // Nicméně, pokud by někdo chtěl kód měnit, může se mu to hodit.
- this.seznamPriloh.Add((cesta == null) ? new Priloha(this, seznamPriloh.Count) : new Priloha(this, seznamPriloh.Count, cesta));
- }
- catch (Exception ex)
- {
- if (ex is PrilisMnohoPrilohException)
- MessageBox.Show(ex.Message);
- }
- }
- /// <summary>
- /// Odstraní existující přílohu a to tak, že danou přílohu odebere ze seznamu příloh a celý seznam posune, také upravuje GUI.
- /// </summary>
- /// <param name="kolikataPriloha">Index přílohy, která se má odstranit.</param>
- private void OdstranExistujiciPrilohu(int kolikataPriloha)
- {
- // 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.
- seznamPriloh.GetRange(kolikataPriloha + 1, seznamPriloh.Count - kolikataPriloha - 1).ForEach(priloha =>
- {
- priloha.label.Location = new System.Drawing.Point(152, priloha.label.Location.Y - 36);
- priloha.tlacitko.Location = new System.Drawing.Point(16, priloha.tlacitko.Location.Y - 36);
- });
- // A pokud jsme kvůli přílohám zvětšovali okno, tak ho zase zmenšíme.
- if (seznamPriloh.Count > 5)
- {
- this.PridatButton.Location = new System.Drawing.Point(90, this.PridatButton.Location.Y - 36);
- this.ClientSize = new System.Drawing.Size(384, this.ClientSize.Height - 36);
- }
- // Uvolnění resourců, aby prvky smazané přílohy nezůstaly na pozadí a nezabíraly tak zbytečně paměť.
- seznamPriloh[kolikataPriloha].Dispose();
- seznamPriloh.RemoveAt(kolikataPriloha);
- // Pokud jsme odebrali poslední přílohu, musíme přidat tlačítko na přidání nové.
- if (seznamPriloh.Count == 9 && seznamPriloh.Last().label.Text != "...")
- InicializujNovouPrilohu(null);
- }
- /// <summary>
- /// Definice třídy příloh, každá příloha se skládá z trojice - tlačítko, label a OpenFileDialog objekt.
- /// </summary>
- internal class Priloha : IDisposable
- {
- public Button tlacitko;
- public Label label;
- public OpenFileDialog soubor;
- private AttachmentForm okno;
- /// <summary>
- /// Zde probíhá inicializace ovládacích prvků.
- /// </summary>
- /// <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>
- /// <param name="kolikataPriloha">Určuje, o kolikátou přílohu se jedná a dle toho umisťuje ovládací prvky.</param>
- public Priloha(AttachmentForm okno, int kolikataPriloha)
- {
- this.okno = okno;
- this.tlacitko = new System.Windows.Forms.Button();
- this.label = new System.Windows.Forms.Label();
- this.soubor = new System.Windows.Forms.OpenFileDialog();
- #region Inicializace ovládacích prvků
- okno.SuspendLayout();
- // Inicializuje tlačítko
- this.tlacitko.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(28)))), ((int)(((byte)(139)))), ((int)(((byte)(196)))));
- this.tlacitko.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
- this.tlacitko.Font = new System.Drawing.Font("Calibri", 11F, System.Drawing.FontStyle.Bold);
- this.tlacitko.ForeColor = System.Drawing.Color.White;
- this.tlacitko.Location = new System.Drawing.Point(16, 100 + kolikataPriloha * 36);
- this.tlacitko.Size = new System.Drawing.Size(130, 28);
- this.tlacitko.TabIndex = kolikataPriloha;
- this.tlacitko.Text = "Vybrat ze souboru";
- this.tlacitko.UseVisualStyleBackColor = false;
- this.tlacitko.Click += new EventHandler(this.OtevriSoubor);
- // Inicializuje label
- this.label.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
- this.label.Font = new System.Drawing.Font("Calibri", 12F);
- this.label.Location = new System.Drawing.Point(152, 100 + kolikataPriloha * 36);
- this.label.Size = new System.Drawing.Size(220, 28);
- this.label.Text = "...";
- this.label.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
- okno.ResumeLayout();
- #endregion
- okno.Controls.Add(this.tlacitko);
- okno.Controls.Add(this.label);
- }
- /// <summary>
- /// Rozšířený konstruktor, pokud již příloha existuje a známe k ní cestu.
- /// </summary>
- /// <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>
- /// <param name="kolikataPriloha">Určuje, o kolikátou přílohu se jedná a dle toho umisťuje ovládací prvky.</param>
- /// <param name="cesta">Cesta ve filesystému k dané příloze.</param>
- public Priloha(AttachmentForm okno, int kolikataPriloha, object cesta) : this(okno, kolikataPriloha)
- {
- this.tlacitko.Text = "Odstranit";
- this.tlacitko.Click += new EventHandler(this.OdstranPrilohu);
- this.label.Text = "..\u005c" + cesta.ToString().Split('\u005c').ToList().Last(); // V labelu zobrazíme pouze název souboru.
- }
- /// <summary>
- /// Obsluha tlačítka, které přidává přílohu.
- /// </summary>
- private void OtevriSoubor(object sender, EventArgs e)
- {
- if (this.soubor.ShowDialog() == DialogResult.OK)
- {
- this.tlacitko.Text = "Odstranit";
- this.label.Text = "..\u005c" + this.soubor.FileName.ToString().Split('\u005c').ToList().Last(); // V labelu zobrazíme pouze název souboru.
- // Tlačítko přidat měníme na tlačítko odstranit, musíme upravit obsluhy daného tlačítka.
- this.tlacitko.Click -= new EventHandler(this.OtevriSoubor);
- this.tlacitko.Click += new EventHandler(this.OdstranPrilohu);
- // Přidáme možnost přidání nové přílohy.
- okno.InicializujNovouPrilohu(null);
- }
- }
- /// <summary>
- /// Obsluha tlačítka, které odebírá přílohu.
- /// </summary>
- private void OdstranPrilohu(object sender, EventArgs e)
- {
- if (MessageBox.Show("Opravdu chcete odstranit tuto přílohu?", "Odstranit", MessageBoxButtons.YesNo) == DialogResult.Yes)
- {
- this.tlacitko.Text = "Vybrat ze souboru";
- this.label.Text = "...";
- this.soubor = new System.Windows.Forms.OpenFileDialog();
- // Tlačítko odstranit měníme na tlačítko přidat, musíme upravit obsluhy daného tlačítka.
- this.tlacitko.Click -= new EventHandler(this.OdstranPrilohu);
- this.tlacitko.Click += new EventHandler(this.OtevriSoubor);
- okno.OdstranExistujiciPrilohu((this.label.Location.Y - 100) / 36); // O kolikátou přílohu se jedná, poznáme podle její pozice.
- }
- }
- public void Dispose()
- {
- this.tlacitko.Dispose();
- this.label.Dispose();
- this.soubor.Dispose();
- }
- }
- /// <summary>
- /// Definice výjimky potřebné pro toto okno.
- /// </summary>
- internal class PrilisMnohoPrilohException : Exception
- {
- public PrilisMnohoPrilohException(string message) : base(message) { }
- }
- }
- }
- /// Soubor HtmlPreviewForm.Cs
- using System;
- using System.Windows.Forms;
- namespace Mail_Agent_2017
- {
- /// <summary>
- /// Zobrazí náhled HTML kódu.
- /// </summary>
- public partial class HtmlPreviewForm : Form
- {
- public HtmlPreviewForm(string kod)
- {
- InitializeComponent();
- HtmlPreviewWebbrowser.DocumentText = "<!DOCTYPE html><html><body style=\"font-family: Calibri;\">" + kod + "</body></html>";
- }
- /// <summary>
- /// Zavře okno s náhledem.
- /// </summary>
- private void ZavritButton_Click(object sender, EventArgs e)
- {
- this.Close();
- }
- }
- }
- /// Soubor ESP.cs
- using System;
- using System.Collections.Generic;
- using System.IO;
- namespace Mail_Agent_2017
- {
- /// <summary>
- /// Třída seskupující informace o jednotlivých e-mail service providerech.
- /// Umožňuje uživateli jednodušší přihlášení ke své e-mailové schránce.
- /// 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.
- /// </summary>
- class ESP
- {
- private List<ESP_Zaznam> seznam;
- /// <summary>
- /// Konstruktor načte údaje o všech ESP z tabulky, která je uložena v souboru.
- /// </summary>
- public ESP()
- {
- this.seznam = new List<ESP_Zaznam>();
- StreamReader esp_seznam = new StreamReader("esp_info");
- while (!esp_seznam.EndOfStream)
- {
- string[] zaznam = esp_seznam.ReadLine().Split(';');
- seznam.Add(new ESP_Zaznam(zaznam[0], zaznam[1], int.Parse(zaznam[2]), bool.Parse(zaznam[3]),
- zaznam[4], int.Parse(zaznam[5]), bool.Parse(zaznam[6]), bool.Parse(zaznam[7])));
- }
- esp_seznam.Close();
- }
- /// <summary>
- /// Třída zahrnující informace o e-mail service providerovi.
- /// </summary>
- internal class ESP_Zaznam : IEquatable<ESP_Zaznam>
- {
- public string nazev;
- public string ImapServer;
- public int ImapPort;
- public bool ImapSsl;
- public string SmtpServer;
- public int SmtpPort;
- public bool SmtpSsl;
- public bool SmtpAuth;
- public ESP_Zaznam(string nazev, string ImapServer, int ImapPort, bool ImapSsl, string SmtpServer, int SmtpPort, bool SmtpSsl, bool SmtpAuth)
- {
- this.nazev = nazev;
- this.ImapServer = ImapServer;
- this.ImapPort = ImapPort;
- this.ImapSsl = ImapSsl;
- this.SmtpServer = SmtpServer;
- this.SmtpPort = SmtpPort;
- this.SmtpSsl = SmtpSsl;
- this.SmtpAuth = SmtpAuth;
- }
- public bool Equals(ESP_Zaznam zaznam)
- {
- return this.nazev == zaznam.nazev;
- }
- }
- /// <summary>
- /// Metoda, která hledá ESP uživatele v tabulce známých ESP.
- /// </summary>
- /// <param name="nazev">E-mail service provider uživatele</param>
- /// <returns>E-mail service provider uživatele</returns>
- public ESP_Zaznam NajdiVhodnehoESP(string nazev)
- {
- foreach (ESP_Zaznam esp in seznam) if (esp.nazev == nazev)
- return esp;
- return null;
- }
- /// <summary>
- /// Metoda, která přidává nový záznam o ESP do tabulky známých ESP.
- /// </summary>
- public void PridejZaznamOESP(string nazev, string ImapServer, int ImapPort, bool ImapSsl, string SmtpServer, int SmtpPort, bool SmtpSsl, bool SmtpAuth)
- {
- seznam.Add(new ESP_Zaznam(nazev, ImapServer, ImapPort, ImapSsl, SmtpServer, SmtpPort, SmtpSsl, SmtpAuth));
- TextWriter esp_seznam = new StreamWriter("esp_info", true);
- esp_seznam.WriteLine("{0};{1};{2};{3};{4};{5};{6};{7}", nazev, ImapServer, ImapPort,
- ImapSsl, SmtpServer, SmtpPort, SmtpSsl, SmtpAuth);
- esp_seznam.Close();
- }
- }
- }
- /// Soubor Prihlasit.cs
- using System;
- using System.Text;
- using System.Security.Cryptography;
- using ImapX;
- using System.Net.Mail;
- using System.Net;
- using System.IO;
- using System.Windows.Forms;
- using System.Collections.Generic;
- namespace Mail_Agent_2017
- {
- /// <summary>
- /// Třída sdružující informace o aktuálním přihlášení.
- /// </summary>
- public class Prihlaseni
- {
- private string _email;
- private string _heslo;
- private string _jmeno;
- public ImapClient ImapPripojeni;
- public SmtpClient SmtpPripojeni;
- /// <summary>
- /// Symetrické šifirování e-mailové adresy podle AES standardu, aby se mohla uložit do souboru.
- /// </summary>
- public string email
- {
- get { return _email == null ? null : Sifrovani.Decrypt(_email); }
- set { _email = Sifrovani.Encrypt(value); }
- }
- /// <summary>
- /// Symetrické šifirování hesla podle AES standardu, aby se mohlo uložit do souboru.
- /// </summary>
- public string heslo
- {
- get { return _heslo == null ? null : Sifrovani.Decrypt(_heslo); }
- set { _heslo = Sifrovani.Encrypt(value); }
- }
- /// <summary>
- /// Symetrické šifirování jména podle AES standardu, aby se mohlo uložit do souboru.
- /// </summary>
- public string jmeno
- {
- get { return _jmeno == null ? null : Sifrovani.Decrypt(_jmeno); }
- set { _jmeno = Sifrovani.Encrypt(value); }
- }
- /// <summary>
- /// 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.
- /// </summary>
- public void UlozPrihlaseniDoSouboru()
- {
- try
- {
- if (_email == null || _heslo == null || _jmeno == null || ImapPripojeni == null || SmtpPripojeni == null)
- 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.");
- }
- catch (ChybneZadaniException ex)
- { MessageBox.Show(ex.Message); return; }
- StreamWriter prihlaseniSoubor = new StreamWriter("login_info");
- prihlaseniSoubor.WriteLine("{0} {1} {2}", _email, _heslo, _jmeno);
- prihlaseniSoubor.WriteLine("{0} {1} {2}", ImapPripojeni.Host, ImapPripojeni.Port, ImapPripojeni.UseSsl);
- prihlaseniSoubor.WriteLine("{0} {1} {2} {3}", SmtpPripojeni.Host, SmtpPripojeni.Port, SmtpPripojeni.EnableSsl, !SmtpPripojeni.UseDefaultCredentials);
- prihlaseniSoubor.Close();
- }
- /// <summary>
- /// Načte poslední přihlášení ze souboru, pokud existuje.
- /// </summary>
- public bool NactiPrihlaseniZeSouboru()
- {
- try
- {
- StreamReader prihlaseniSoubor = new StreamReader("login_info");
- string[] prihlaseni = prihlaseniSoubor.ReadLine().Split(' ');
- string[] IMAP = prihlaseniSoubor.ReadLine().Split(' ');
- string[] SMTP = prihlaseniSoubor.ReadLine().Split(' ');
- this._email = prihlaseni[0];
- this._heslo = prihlaseni[1];
- this._jmeno = prihlaseni[2];
- this.ImapPripojeni = new ImapClient(IMAP[0], int.Parse(IMAP[1]), bool.Parse(IMAP[2]));
- this.SmtpPripojeni = new SmtpClient(SMTP[0], int.Parse(SMTP[1]));
- this.SmtpPripojeni.EnableSsl = bool.Parse(SMTP[2]);
- if (bool.Parse(SMTP[3]))
- {
- this.SmtpPripojeni.UseDefaultCredentials = false;
- this.SmtpPripojeni.Credentials = new NetworkCredential(email, heslo);
- }
- // Pokud se nepovede přihlášení k IMAP serveru, bude uživatel vyzván, aby se přihlásil znovu.
- if (!ImapPripojeni.Connect() || !ImapPripojeni.Login(email, heslo))
- throw new ImapConnectFailException("Přihlášení bylo neúspěšné. Přihlašte se, prosím, znovu.");
- prihlaseniSoubor.Close();
- }
- catch (Exception ex)
- {
- if (ex is ImapConnectFailException)
- MessageBox.Show(ex.Message);
- // 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.
- return false;
- }
- return true;
- }
- /// <summary>
- /// Odhlásí se a odstraní soubor s přihlášením.
- /// </summary>
- public void OdhlasitSe()
- {
- File.Delete("login_info");
- SmtpPripojeni.Dispose();
- ImapPripojeni.Dispose();
- _email = null;
- _heslo = null;
- _jmeno = null;
- }
- }
- /// <summary>
- /// Třída poskytující drobné utility, jež se hodí u přihlašování.
- /// </summary>
- static class PrihlaseniUtility
- {
- /// <summary>
- /// Metoda rozhoduje, zdali má zadaná adresa správný formát.
- /// </summary>
- /// <param name="email">E-mailová adresa, která má být zkontrolována.</param>
- /// <returns>Úspěch v případě správného formátu adresy, neúspěch v opačném případě.</returns>
- public static bool SpravnyFormatAdresy(string email)
- {
- // Využijeme třídu .NET pro emailové adresy a pokusíme se vytvořit novou emailovou adresu.
- // V případě neúspěchu vyvolá výjimku - tedy v případě, že adresa má nesprávný formát.
- try { return new System.Net.Mail.MailAddress(email).Address == email; }
- catch { return false; }
- }
- /// <summary>
- /// Metoda se pokusí připojit k SMTP serveru podle údajů, které zadal uživatel.
- /// Také se pokusí poslat testovací zprávu, jakožto indikátor úspěšného připojení,
- /// </summary>
- /// <returns>V případě úspěšného připojení odkaz na objekt SmtpClient, v opačném případě null.</returns>
- public static SmtpClient SmtpConnect(string SmtpServer, int SmtpPort, bool SmtpSsl, bool SmtpAuth, string email, string heslo)
- {
- // 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.
- // Proč nemusíme? Ověří to za nás připojení k IMAP serveru, které předchází připojení k SMTP serveru.
- SmtpClient SmtpPripojeni = new SmtpClient(SmtpServer, SmtpPort);
- SmtpPripojeni.EnableSsl = SmtpSsl;
- if (SmtpAuth)
- {
- SmtpPripojeni.UseDefaultCredentials = false;
- SmtpPripojeni.Credentials = new NetworkCredential(email, heslo);
- }
- // Metoda vyvolá výjimku, když se nepodaří odeslat zprávu.
- try
- {
- SmtpPripojeni.Send(email , email, "Mail Agent 2017 - Testovací zpráva", @"Přihlášení do aplikace proběhlo úspěšně.");
- return SmtpPripojeni;
- }
- catch
- { return null; }
- }
- /// <summary>
- /// Spustí přihlašovací proces.
- /// </summary>
- /// <param name="aktualniPrihlaseni">Relace přihlášení, která má být inicializována.</param>
- public static void prihlasovaciProces(ref Prihlaseni aktualniPrihlaseni)
- {
- Stack<Form> prihlasovaciProces = new Stack<Form>();
- if (!aktualniPrihlaseni.NactiPrihlaseniZeSouboru())
- {
- /*
- * Přihlašovací proces je řešený pomocí zásobníku oken.
- * 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.
- * Přihlašovací proces končí, když je zásobník prázdný.
- */
- prihlasovaciProces.Push(new LoginForm1(aktualniPrihlaseni, prihlasovaciProces));
- while (prihlasovaciProces.Count > 0)
- prihlasovaciProces.Pop().ShowDialog();
- // Pokud neprobělo přihlášení, dojde k ukončení celé aplikace.
- if (aktualniPrihlaseni.ImapPripojeni == null || aktualniPrihlaseni.SmtpPripojeni == null || aktualniPrihlaseni.email == null || aktualniPrihlaseni.heslo == null)
- Environment.Exit(0);
- // Uložíme aktuální relaci do souboru, abychom ji při příštím spuštění aplikace mohli snadno načíst.
- aktualniPrihlaseni.UlozPrihlaseniDoSouboru();
- }
- }
- }
- #region Definice výjimek
- /// <summary>
- /// Výjimka, která je vyvolaná při chybě při navazování spojení se SMTP serverem.
- /// </summary>
- class SmtpConnectFailException : Exception
- {
- public SmtpConnectFailException(string message) : base(message) { }
- }
- /// <summary>
- /// Výjimka, která je vyvolaná, když uživatel zadá chybné heslo.
- /// </summary>
- class SpatneHesloException : Exception
- {
- public SpatneHesloException(string message) : base(message) { }
- }
- /// <summary>
- /// Výjimka, která je vyvolaná při chybě při navazování spojení s IMAP serverem.
- /// </summary>
- class ImapConnectFailException : Exception
- {
- public ImapConnectFailException(string message) : base(message) { }
- }
- /// <summary>
- /// Výjimka, která je vyvolána při chybném vyplnění formuláře.
- /// </summary>
- class ChybneZadaniException : Exception
- {
- public ChybneZadaniException(string message) : base(message) { }
- public ChybneZadaniException() : base() { }
- }
- #endregion
- /// <summary>
- /// Následující třída poskytuje šifrovací a dešifrovací funkce.
- /// Autorem metod NEJSEM já, byly použity šifrovací funkce nalezené na internetu.
- /// </summary>
- static class Sifrovani
- {
- static readonly string PasswordHash = "h€$$łö";
- static readonly string SaltKey = "M@iL&g€n†2oI7";
- static readonly string VIKey = "@1B2c3D4e5F6g7H8";
- /// <summary>
- /// Metoda šifrující daný text.
- /// </summary>
- /// <param name="plainText">Text, který se má zašifrovat.</param>
- /// <returns>Zašifrovaný text.</returns>
- public static string Encrypt(string plainText)
- {
- byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
- byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
- var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros };
- var encryptor = symmetricKey.CreateEncryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey));
- byte[] cipherTextBytes;
- using (var memoryStream = new MemoryStream())
- {
- using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
- {
- cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
- cryptoStream.FlushFinalBlock();
- cipherTextBytes = memoryStream.ToArray();
- cryptoStream.Close();
- }
- memoryStream.Close();
- }
- return Convert.ToBase64String(cipherTextBytes);
- }
- /// <summary>
- /// Metoda dešifrující daný text.
- /// </summary>
- /// <param name="encryptedText">Text, který se má dešifrovat.</param>
- /// <returns>Dešifrovaný text.</returns>
- public static string Decrypt(string encryptedText)
- {
- byte[] cipherTextBytes = Convert.FromBase64String(encryptedText);
- byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
- var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.None };
- var decryptor = symmetricKey.CreateDecryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey));
- var memoryStream = new MemoryStream(cipherTextBytes);
- var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
- byte[] plainTextBytes = new byte[cipherTextBytes.Length];
- int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
- memoryStream.Close();
- cryptoStream.Close();
- return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount).TrimEnd("\0".ToCharArray());
- }
- }
- }
- /// Soubor LoginForm1.cs
- using System;
- using System.Collections.Generic;
- using System.Windows.Forms;
- namespace Mail_Agent_2017
- {
- // TO-DO: Fade-in efekty u všech součásti formuláře, fade-out efekt pro chybovou hlášku.
- /// <summary>
- /// První přihlašovací okno.
- /// </summary>
- public partial class LoginForm1 : Form
- {
- Prihlaseni aktualniPrihlaseni;
- Stack<Form> prihlasovaciProces;
- public LoginForm1(Prihlaseni aktualniPrihlaseni, Stack<Form> prihlasovaciProces)
- {
- InitializeComponent();
- this.aktualniPrihlaseni = aktualniPrihlaseni;
- this.prihlasovaciProces = prihlasovaciProces;
- AdresaTextbox.Text = aktualniPrihlaseni.email; // Toto je zde pro případ, kdyby se uživatel vracel do tohoto okna.
- }
- /// <summary>
- /// Metoda, která se spustí po kliknutí na tlačítko "Dále" na první přihlašovací obrazovce.
- /// 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.
- /// </summary>
- private void DaleButton_Click(object sender, EventArgs e)
- {
- try
- {
- if (!PrihlaseniUtility.SpravnyFormatAdresy(AdresaTextbox.Text))
- throw new ChybneZadaniException("E-mailová adresa má chybný formát.");
- }
- catch (Exception ex)
- {
- ChyboveOknoLabel.Show();
- ChyboveOknoLabel.Text = ex.Message;
- ZobrazeniChybyTimer.Enabled = true;
- return;
- }
- aktualniPrihlaseni.email = AdresaTextbox.Text;
- prihlasovaciProces.Push(new LoginForm2(aktualniPrihlaseni, prihlasovaciProces));
- this.Close();
- }
- /// <summary>
- /// Skryje chybovou hlášku po uplynutí deseti sekund.
- /// </summary>
- private void ZobrazeniChybyTimer_Tick(object sender, EventArgs e)
- {
- ZobrazeniChybyTimer.Enabled = false;
- ChyboveOknoLabel.Hide();
- }
- }
- }
- /// Soubor LoginForm2.cs
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- using ImapX;
- using System.Threading;
- namespace Mail_Agent_2017
- {
- /// <summary>
- /// Druhé přihlašovací okno.
- /// </summary>
- public partial class LoginForm2 : Form
- {
- Prihlaseni aktualniPrihlaseni;
- Stack<Form> prihlasovaciProces;
- ESP seznamESP;
- /// <summary>
- /// Konstruktor se stará zejména o vyplnění údajů o známých ESP, upravuje dle toho UI.
- /// </summary>
- public LoginForm2(Prihlaseni aktualniPrihlaseni, Stack<Form> prihlasovaciProces)
- {
- InitializeComponent();
- this.aktualniPrihlaseni = aktualniPrihlaseni;
- this.prihlasovaciProces = prihlasovaciProces;
- this.EmailAddressTextbox.Text = aktualniPrihlaseni.email;
- this.HesloTextbox.Text = aktualniPrihlaseni.heslo;
- this.JmenoTextbox.Text = aktualniPrihlaseni.jmeno;
- this.seznamESP = new ESP(); // Načtení tabulky známých ESP.
- // Aplikace zkontroluje, zdali se uživatelův ESP nenachází v tabulce známých ESP.
- if (seznamESP.NajdiVhodnehoESP(aktualniPrihlaseni.email.Split('@')[1]) != null)
- {
- OznameniLabel.Text = "Váš poskytovatel e-mailových služeb je nám známý. Některé údaje budou automaticky předvyplněny.";
- UpravyCheckbox.Checked = false;
- // Musíme řešit pomocí var, protože třída ESP_Zaznam je interní.
- var aktualniESP = seznamESP.NajdiVhodnehoESP(aktualniPrihlaseni.email.Split('@')[1]);
- ImapServerTextbox.Text = aktualniESP.ImapServer;
- ImapServerTextbox.Enabled = UpravyCheckbox.Checked;
- ImapPortTextbox.Text = aktualniESP.ImapPort.ToString();
- ImapPortTextbox.Enabled = UpravyCheckbox.Checked;
- SmtpServerTextbox.Text = aktualniESP.SmtpServer;
- SmtpServerTextbox.Enabled = UpravyCheckbox.Checked;
- SmtpPortTextbox.Text = aktualniESP.SmtpPort.ToString();
- SmtpPortTextbox.Enabled = UpravyCheckbox.Checked;
- ImapSslCheckbox.Checked = aktualniESP.ImapSsl;
- ImapSslCheckbox.Enabled = UpravyCheckbox.Checked;
- SmtpSslCheckbox.Checked = aktualniESP.SmtpSsl;
- SmtpSslCheckbox.Enabled = UpravyCheckbox.Checked;
- SmtpAuthCheckbox.Checked = aktualniESP.SmtpAuth;
- SmtpAuthCheckbox.Enabled = UpravyCheckbox.Checked;
- }
- else
- {
- OznameniLabel.Text = "V případě nesnází se obraťte na Vašeho poskytovatele e-mailových služeb.";
- UpravyCheckbox.Visible = false;
- ZmenaLabel.Visible = false;
- }
- }
- /// <summary>
- /// Implementace tlačítka zpět - po stisknutí tlačítka se vrátí na předchozí přihlašovací okno.
- /// </summary>
- private void ZpetButton_Click(object sender, EventArgs e)
- {
- prihlasovaciProces.Push(new LoginForm1(aktualniPrihlaseni, prihlasovaciProces));
- this.Close();
- }
- /// <summary>
- /// Metoda starající se o navazování spojení se SMTP a IMAP servery.
- /// Rovněž hledá a kontroluje chyby, obeznamuje o nich uživatele.
- /// </summary>
- private async void DaleButton_Click(object sender, EventArgs e)
- {
- ZobrazeniChybyTimer.Enabled = false;
- aktualniPrihlaseni.heslo = HesloTextbox.Text;
- aktualniPrihlaseni.jmeno = JmenoTextbox.Text;
- // 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í.
- ChyboveOknoLabel.Text = "";
- NacitaniTimer.Enabled = true;
- ChyboveOknoLabel.ForeColor = Color.Black;
- ChyboveOknoLabel.Show();
- // Navazování spojení rozběhneme na novém pracovním vlákně jako asynchronní metodu.
- await Task.Run(() =>
- {
- try
- {
- // Chyba: Nebyly vyplněny všechny údaje.
- if (string.IsNullOrWhiteSpace(HesloTextbox.Text) || string.IsNullOrWhiteSpace(JmenoTextbox.Text) || string.IsNullOrWhiteSpace(ImapServerTextbox.Text) ||
- string.IsNullOrWhiteSpace(ImapPortTextbox.Text) || string.IsNullOrWhiteSpace(SmtpServerTextbox.Text) || string.IsNullOrWhiteSpace(SmtpPortTextbox.Text))
- throw new ChybneZadaniException("Nebyly vyplněny všechny údaje.");
- // Chyba: Porty neobsahují číselné hodnoty.
- if (!int.TryParse(ImapPortTextbox.Text, out int imap) || !int.TryParse(SmtpPortTextbox.Text, out int smtp))
- throw new ChybneZadaniException("Porty byly vyplněny chybně.");
- // Inicializace SMTP a IMAP spojení.
- aktualniPrihlaseni.ImapPripojeni = new ImapClient(ImapServerTextbox.Text, int.Parse(ImapPortTextbox.Text), ImapSslCheckbox.Checked, ImapSslCheckbox.Checked);
- aktualniPrihlaseni.SmtpPripojeni = PrihlaseniUtility.SmtpConnect(SmtpServerTextbox.Text, int.Parse(SmtpPortTextbox.Text), SmtpSslCheckbox.Checked,
- SmtpAuthCheckbox.Checked, aktualniPrihlaseni.email, HesloTextbox.Text);
- // Chyba: Nepodařilo se navázat spojení s IMAP serverem.
- if (!aktualniPrihlaseni.ImapPripojeni.Connect())
- throw new ImapConnectFailException("Chyba při navazování spojení s IMAP serverem.");
- // Chyba: Špatná e-mailová adresa nebo heslo.
- else if (!aktualniPrihlaseni.ImapPripojeni.Login(aktualniPrihlaseni.email, aktualniPrihlaseni.heslo))
- throw new SpatneHesloException("Heslo a e-mailová adresa se neshodují.");
- // Chyba: Nepodařilo se navázat spojení se SMTP serverem. Pro otestování spojení se SMTP serverem pošle testovací zprávu.
- else if (aktualniPrihlaseni.SmtpPripojeni == null)
- throw new SmtpConnectFailException("Chyba při navazování spojení se SMTP serverem.");
- }
- catch (Exception ex)
- {
- // Zkontrolujeme, jestli se jedná o výjimku vyvolanou námi.
- if (ex is ChybneZadaniException || ex is SmtpConnectFailException || ex is ImapConnectFailException || ex is SpatneHesloException)
- // 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.
- this.BeginInvoke(new MethodInvoker(delegate ()
- {
- // Zastavení blikajích teček
- NacitaniTimer.Enabled = false;
- ChyboveOknoLabel.Text = ex.Message; ChyboveOknoLabel.ForeColor = Color.Red;
- ZobrazeniChybyTimer.Enabled = true;
- }));
- // Pokud se jedná o jinou výjimku, tak prostě nebudeme uživateli nic tajit a řekneme mu tím, jak neumíme programovat.
- else throw;
- }
- finally
- {
- // Toto je zde pro efekt.
- // 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.
- Thread.Sleep(2500);
- }
- });
- // Výsledek z pracovního vlákna poznáme snadno, a to tak, že pouze v případě chyby se rozběhne tento timer.
- if (ZobrazeniChybyTimer.Enabled)
- return;
- // Po úspěšném navázání spojení přidá záznam do tabulky známých ESP, pokud tam již není.
- if (seznamESP.NajdiVhodnehoESP(aktualniPrihlaseni.email.Split('@')[1]) == null)
- seznamESP.PridejZaznamOESP(aktualniPrihlaseni.email.Split('@')[1], ImapServerTextbox.Text, int.Parse(ImapPortTextbox.Text), ImapSslCheckbox.Checked,
- SmtpServerTextbox.Text, int.Parse(SmtpPortTextbox.Text), SmtpSslCheckbox.Checked, SmtpAuthCheckbox.Checked);
- prihlasovaciProces.Push(new LoginForm3(aktualniPrihlaseni, prihlasovaciProces));
- this.Close();
- }
- /// <summary>
- /// Skryje chybovou hlášku po uplynutí deseti sekund.
- /// </summary>
- private void ZobrazeniChybyTimer_Tick(object sender, EventArgs e)
- {
- ZobrazeniChybyTimer.Enabled = false;
- ChyboveOknoLabel.Hide();
- }
- /// <summary>
- /// Metoda, která obsluhuje tlačítko, které povoluje změny předvyplněných údajů.
- /// </summary>
- private void ZmenaCB_CheckedChanged(object sender, EventArgs e)
- {
- ImapServerTextbox.Enabled = UpravyCheckbox.Checked;
- ImapPortTextbox.Enabled = UpravyCheckbox.Checked;
- SmtpServerTextbox.Enabled = UpravyCheckbox.Checked;
- SmtpPortTextbox.Enabled = UpravyCheckbox.Checked;
- ImapSslCheckbox.Enabled = UpravyCheckbox.Checked;
- SmtpSslCheckbox.Enabled = UpravyCheckbox.Checked;
- SmtpAuthCheckbox.Enabled = UpravyCheckbox.Checked;
- }
- /// <summary>
- /// Metoda pro efekt, zobrazuje efekt blikajících teček při přihlašování.
- /// </summary>
- private void NacitaniTimer_Tick(object sender, EventArgs e)
- {
- if (ChyboveOknoLabel.Text.Length >= 75 || ChyboveOknoLabel.Text.Length == 0)
- ChyboveOknoLabel.Text = "Počkejte, prosím. Toto může chvíli trvat. Probíhá navazování komunikace ";
- else
- ChyboveOknoLabel.Text += ".";
- }
- }
- }
- /// Soubor LoginForm3.cs
- using System;
- using System.Collections.Generic;
- using System.Windows.Forms;
- namespace Mail_Agent_2017
- {
- /// <summary>
- /// Třetí přihlašovací okno.
- /// </summary>
- public partial class LoginForm3 : Form
- {
- Prihlaseni aktualniPrihlaseni;
- Stack<Form> prihlasovaciProces;
- public LoginForm3(Prihlaseni aktualniPrihlaseni, Stack<Form> prihlasovaciProces)
- {
- InitializeComponent();
- this.aktualniPrihlaseni = aktualniPrihlaseni;
- this.prihlasovaciProces = prihlasovaciProces;
- PopisLabel.Text = "Při této příležitosti Vám byla zaslána testovací zpráva.\n" +
- "Nyní můžete vstoupit do aplikace a využívat všechny její funkce.\n\n" +
- "Děkujeme Vám, " + aktualniPrihlaseni.jmeno.Split(' ')[0] + ", že jste si vybral Mail Agent 2017.";
- }
- /// <summary>
- /// Implementace tlačítka zpět - po stisknutí tlačítka se vrátí na předchozí přihlašovací okno.
- /// </summary>
- private void ZpetButton_Click(object sender, EventArgs e)
- {
- prihlasovaciProces.Push(new LoginForm2(aktualniPrihlaseni, prihlasovaciProces));
- this.Close();
- }
- /// <summary>
- /// Přesměruje uživatele do aplikace.
- /// </summary>
- private void DaleButton_Click(object sender, EventArgs e)
- {
- this.Close();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement