2017-09-16 7 views
-1

Je suis en train d'avoir un problème avec mon programme, j'essaie d'apprendre comment envoyer des emails avec smtp et j'ai écrit ce code pour le faire. Lorsque j'essaie de cliquer sur le bouton 1, le programme se bloque et rien ne se passe. PS: Évidemment que j'ai changé l'email et le mot de passe à "email" et "mot de passe" avant de poster ceci. PS2: J'écris mon code en portugais donc tout ce que vous ne comprenez pas peut être considéré comme une variable ou "x".Geler le programme en essayant d'envoyer des emails avec smtp

EDIT: J'ai résolu le problème avec une ligne simple, un port est manquant sur le programme, qui a le même problème vient d'ajouter smtp.Port = 587; .

code ci-dessous:

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; 
using System.Net.Mail; 
using MySql.Data.MySqlClient; 
using System.Net; 

namespace Inicio 
{ 
    public partial class Email : Form 
    { 
     MySqlConnection con = new MySqlConnection(@"Data Source=localhost;port=3306;Initial Catalog=digital wallet;User ID=root;password="); 
     public Email() 
     { 
      InitializeComponent(); 
     } 

     private void SendEmail() 
     { 

      if (textBox1.Text == "" || textBox2.Text == "") 
      { 
       MessageBox.Show("Preencha todos os campos", "Erro", 
       MessageBoxButtons.OK, MessageBoxIcon.Error); 
      } 
      else 
      { 
       int i = 0; 
       con.Open(); 
       MySqlCommand cmd = con.CreateCommand(); 
       cmd.CommandType = CommandType.Text; 
       cmd.CommandText = "select EMAIL from conta where EMAIL = @email and LOGIN = @login "; 
       cmd.Parameters.AddWithValue("@email", textBox2.Text); 
       cmd.Parameters.AddWithValue("@login", textBox1.Text); 
       cmd.ExecuteNonQuery(); 
       DataTable dt = new DataTable(); 
       MySqlDataAdapter da = new MySqlDataAdapter(cmd); 
       da.Fill(dt); 
       i = Convert.ToInt32(dt.Rows.Count.ToString()); 

       if (i == 0) 
       { 
        MessageBox.Show("Login ou email inválidos", "Erro", 
        MessageBoxButtons.OK, MessageBoxIcon.Error); 
       } 
       else 
       { 
        cmd.CommandText = "select * from CONTA where LOGIN = @login"; 
        cmd.ExecuteNonQuery(); 

        string senha = ""; 
        string email = ""; 

        MySqlDataReader reader = cmd.ExecuteReader(); 
        while (reader.Read()) 
        { 
         senha = reader.GetString("SENHA"); 
         email = reader.GetString("EMAIL"); 
        } 

        reader.Close(); 

        using (SmtpClient smtp = new SmtpClient()) 
        { 
         smtp.Host = "outlook.com"; 
         smtp.UseDefaultCredentials = false; 
         NetworkCredential netCred = new NetworkCredential("email", "password"); 
         smtp.Credentials = netCred; 
         smtp.EnableSsl = true; 

         using (MailMessage msg = new MailMessage("email", email)) 
         { 
          msg.Subject = "Recuperação de senha."; 
          StringBuilder sb = new StringBuilder(); 
          sb.AppendLine("A sua senha é atual é: " + senha + Environment.NewLine); 
          sb.AppendLine("Obrigado," + Environment.NewLine); 
          sb.AppendLine("Digital wallet. " + Environment.NewLine); 
          msg.Body = sb.ToString(); 
          msg.IsBodyHtml = false; 
          smtp.Send(msg); 
         } 
        } 
       } 
      } 
     } 
     private void button1_Click(object sender, EventArgs e) 
     { 
      SendEmail(); 
     } 

     private void button2_Click(object sender, EventArgs e) 
     { 
      this.Close(); 
     } 
    } 
} 

Répondre

0

Vous exécutez dans un environnement graphique. Les événements doivent revenir le plus rapidement possible, sinon l'interface graphique est "verrouillée". L'activité du disque et du réseau en particulier a tendance à être longue. Vous devez appliquer une forme de multitâche (et déplacer l'opération de longue durée dans cette autre tâche) pour éviter le blocage de l'interface graphique.

En tant que débutant, je conseille d'utiliser le BackgroundWorker pour le multitâche. Async ... wait est plus avancé.

Editer: Voici mon exemple de code WinForms + BackgroundWorker. Cela devrait vous aider à commencer à l'utiliser correctement.

#region Primenumbers 
 
private void btnPrimStart_Click(object sender, EventArgs e) 
 
{ 
 
\t if (!bgwPrim.IsBusy) 
 
\t { 
 
\t \t //Prepare ProgressBar and Textbox 
 
\t \t int temp = (int)nudPrim.Value; 
 
\t \t pgbPrim.Maximum = temp; 
 
\t \t tbPrim.Text = ""; 
 

 
\t \t //Start processing 
 
\t \t bgwPrim.RunWorkerAsync(temp); 
 
\t } 
 
} 
 

 
private void btnPrimCancel_Click(object sender, EventArgs e) 
 
{ 
 
\t if (bgwPrim.IsBusy) 
 
\t { 
 
\t \t bgwPrim.CancelAsync(); 
 
\t } 
 
} 
 

 
private void bgwPrim_DoWork(object sender, DoWorkEventArgs e) 
 
{ 
 
\t int highestToCheck = (int)e.Argument; 
 
\t //Get a reference to the BackgroundWorker running this code 
 
\t //for Progress Updates and Cancelation checking 
 
\t BackgroundWorker thisWorker = (BackgroundWorker)sender; 
 

 
\t //Create the list that stores the results and is returned by DoWork 
 
\t List<int> Primes = new List<int>(); 
 
\t 
 

 
\t //Check all uneven numbers between 1 and whatever the user choose as upper limit 
 
\t for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2) 
 
\t { 
 
\t \t //Report progress 
 
\t \t thisWorker.ReportProgress(PrimeCandidate); 
 
\t \t bool isNoPrime = false; 
 

 
\t \t //Check if the Cancelation was requested during the last loop 
 
\t \t if (thisWorker.CancellationPending) 
 
\t \t { 
 
\t \t \t //Tell the Backgroundworker you are canceling and exit the for-loop 
 
\t \t \t e.Cancel = true; 
 
\t \t \t break; 
 
\t \t } 
 

 
\t \t //Determin if this is a Prime Number 
 
\t \t for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2) 
 
\t \t { 
 
\t \t \t if (PrimeCandidate % j == 0) 
 
\t \t \t \t isNoPrime = true; 
 
\t \t } 
 

 
\t \t if (!isNoPrime) 
 
\t \t \t Primes.Add(PrimeCandidate); 
 
\t } 
 

 
\t //Tell the progress bar you are finished 
 
\t thisWorker.ReportProgress(highestToCheck); 
 

 
\t //Save Return Value 
 
\t e.Result = Primes.ToArray(); 
 
} 
 

 
private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e) 
 
{ 
 
\t pgbPrim.Value = e.ProgressPercentage; 
 
} 
 

 
private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
 
{ 
 
\t pgbPrim.Value = pgbPrim.Maximum; 
 
\t this.Refresh(); 
 

 
\t if (!e.Cancelled && e.Error == null) 
 
\t { 
 
\t \t //Show the Result 
 
\t \t int[] Primes = (int[])e.Result; 
 

 
\t \t StringBuilder sbOutput = new StringBuilder(); 
 

 
\t \t foreach (int Prim in Primes) 
 
\t \t { 
 
\t \t \t sbOutput.Append(Prim.ToString() + Environment.NewLine); 
 
\t \t } 
 

 
\t \t tbPrim.Text = sbOutput.ToString(); 
 
\t } 
 
\t else 
 
\t { 
 
\t \t tbPrim.Text = "Operation canceled by user or Exception"; 
 
\t } 
 
} 
 
#endregion

+0

Eh bien ... On dirait que j'ai du travail à faire. –

0

Traitement de votre requête SQL, la connexion au serveur smtp et transférer les données de messagerie au serveur prend du temps. Puisque vous exécutez toutes ces choses dans l'UI-Thread, votre formulaire se fige.

Ajouter un BackgroundWorker à votre formulaire, ajoutez les gestionnaires d'événements pour .DoWork et .RunWorkerCompleted et ajoutez le SQL et d'autres choses SMTP à la fonction DoWork. Sur Button1Cliquez sur Démarrer BackgroundWorker avec .RunWorkerAsync. Passez un tableau de chaînes à cette fonction avec vos contenus TextBox1 et TextBox2. Vous devez le faire puisque vous ne pouvez pas accéder à ces éléments à partir de la fonction DoWork. En option, vous pouvez vérifier avec .IsBusy si le travailleur est déjà actif. Après avoir démarré le travail, vous devez verrouiller l'interface utilisateur ou afficher un message ou quelque chose comme ça pour dire à l'utilisateur qu'un processus d'arrière-plan est en cours d'exécution. Pour ce faire, à partir de la fonction Button1Click.

Modifiez ensuite la fonction .DoWork pour extraire le tableau de chaînes transmis. Vous faites cela en accédant au DoWorkEventArgs.Arguments passé et les transtyper au type que vous avez passé à RunWorkerAsync - en string-array. Échange l'accès TextBox aux valeurs du tableau.

Dans la fonction RunWorkerCompleted, vous devez déverrouiller l'interface utilisateur.

Commencez à lire à propos BackgroundWorker et vous pouvez utiliser la fonction de rapportage informer l'utilisateur sur les progrès, quelque chose comme la collecte de données SQL, la connexion au serveur smtp, transférer des données de courrier, fait '...

+0

Donc, apparemment le code est bon? –

+0

J'ai quitté le programme en cours et je reçois une exception qui indique que le temps de fonctionnement limite dépasser. –

+0

Fonctionnement Limite de temps Exceeded implique que quelque chose s'est mal passé du côté Networking. Mauvaises informations d'identification ou protocole. Serveur introuvable. Quelque chose comme ca. Vous devez regarder dans les Exceptions intérieures pour savoir exactement quoi. Le risque de tomber dans un délai d'attente comme celui-ci est une raison pour toujours mettre des choses en réseau dans le multitâche. – Christopher

0

Luan Teixeira,

Vous devriez regarder dans le Asynchronous Programming with Async and Await. Cela va résoudre ton problème.

Pour démontrer ce que je dis. Découvrez ce code.

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 
    private async Task SendEmail() 
    { 

     if (textBox1.Text == "" || textBox2.Text == "") 
     { 
      MessageBox.Show("Preencha todos os campos", "Erro", 
      MessageBoxButtons.OK, MessageBoxIcon.Error); 
     } 
     else 
     { 
      await Email.SendEmail(); 

      MessageBox.Show("Nice"); 
     } 
    } 
    private async void button1_Click(object sender, EventArgs e) 
    { 
     await SendEmail(); 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     this.Close(); 
    } 
} 

public class Email 
{ 
    public async static Task SendEmail() 
    { 
     await Task.Delay(15000); 
    } 
} 

Vous pouvez écrire quelque chose dans textbox1 et textbox2 et cliquez sur le bouton. Attendez 15 secondes (je simule une tâche vraiment énorme qui peut prendre 15 secondes). En attendant, vous pouvez voir que l'interface utilisateur ne gèle pas. Vous pouvez déplacer la fenêtre. Après 15 secondes, vous allez recevoir un message "Nice".

C'est parce que dans mon code l'énorme tâche ne s'exécute pas dans le thread graphique.

Hope it helps Amitiés Daniel

+0

Merci pour cela, je vais jeter un oeil à cela. –