• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1460
  • Last Modified:

Sending E-Mail with console app

Hi experts,

I am trying to send emails to users via a console application and i wish to record for each user if the email was sent on not.

right now only when i stick a breakpoint or console app on the code does it record this information.

is there anything wrong with the logic?

this code is called after the email is sent so i should the "message sent" on my screen
======================================
        public static void SmtpClient_OnCompleted(object sender, AsyncCompletedEventArgs e)
        {
            //Get the Original MailMessage object
            MailMessage mail = (MailMessage)e.UserState;

            //write out the subject
            string subject = mail.Subject;

            if (e.Cancelled)
            {
                Console.WriteLine("Send canceled for mail with subject [{0}].", subject);
            }
            if (e.Error != null)
            {
                Console.WriteLine("Error {1} occurred when sending mail [{0}] ", subject, e.Error.ToString());
            }
            else
            {
                Console.WriteLine("Message [{0}] sent.", subject);
            }
        }
        =========================================================

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using System.Configuration;
using System.Collections.Specialized;
using System.Net.Mail;
using System.IO;
using System.ComponentModel;
using WelcomeEmail;

namespace WelcomeEmail
{
    class Utilities
    {
        #region SendMail Code
        public static void SendMail(string sAMAccountName, string Mail)
        {

            //Create the MailMessage object
            MailMessage msg = new MailMessage();
            object userState = msg;

            // Configure basic infomation for an e-mail message
            string FromName = ConfigurationManager.AppSettings["FromName"];
            string FromEmail = ConfigurationManager.AppSettings["FromEmail"];
            string Subject = ConfigurationManager.AppSettings["Subject"];

            //Assign the attachment path
            string FileNameFM = Environment.CurrentDirectory + @"\Attachments\test.doc";
       

            //Create the email server host    
            SmtpClient smtp = new SmtpClient("****.****.co.uk");                                                                                  
     
            //Assign from address
            msg.From = new MailAddress(FromEmail, FromName);

            //Assign to address
            msg.To.Add(new MailAddress(Mail, sAMAccountName));
           
         
            //assign subject, and body
            msg.Subject = Subject;
            AlternateView htmlView = AlternateView.CreateAlternateViewFromString
           ("<b>Dear Colleagues,</b><br><p>Welcome</p>",   null, "text/html");

            msg.AlternateViews.Add(htmlView);
            msg.Priority = MailPriority.High;

            msg.Attachments.Add(new System.Net.Mail.Attachment(FileNameFM));
     
         
                try
                {
                    //Send the message with SmtpClient
                    smtp.SendAsync(msg,userState);
                      //wire up the event for when the Async send is completed
           smtp.SendCompleted += new SendCompletedEventHandler(SmtpClient_OnCompleted); ======================called it here, some how after it reads this,....
                  }
                catch (SmtpFailedRecipientsException ex)
                {
                    Console.WriteLine("Failed to deliver message to {0}", ex.FailedRecipient);
                }
           
            }


 
    }
}

===================================it calls this code===============
       #region DirectoryEntry
        public static DirectoryEntry FindUsers(String userName)
        {
            string StartTime;
            DirectoryEntry entry = GetDirectoryEntry();
            DirectorySearcher search = new DirectorySearcher(entry);
            //Pass the filepath and filename to the StreamWriter Constructor
            StreamWriter sw = new StreamWriter("C:\\Test.txt", true);
           StartTime = DateTime.Today.ToString("yyyyMMddHHmmss.Z");
 
     
           search.Filter = ("(&(ObjectClass=user)(whenCreated=20070705153119.0Z))");

            Console.WriteLine("Listing of users in the Active Directory");
            sw.WriteLine("Listing of users in the Active Directory");
            //sw.WriteLine("Date Run : " + StartTime);
            Console.WriteLine("==================================");
            sw.WriteLine("==================================");
            foreach (SearchResult resEnt in search.FindAll())
            {
                try
                {
                    System.DirectoryServices.DirectoryEntry de = resEnt.GetDirectoryEntry();
                    Console.WriteLine("Display Name  : " + de.Properties["DisplayName"].Value.ToString());
                    sw.WriteLine("Display Name  : " + de.Properties["DisplayName"].Value.ToString());
                    Console.WriteLine("WhenCreated : " + de.Properties["whenCreated"].Value.ToString());
                    sw.WriteLine("When Created  : " + de.Properties["whenCreated"].Value.ToString());
                    Console.WriteLine("Email         : " + de.Properties["Mail"].Value.ToString());
                    sw.WriteLine("Email  : " + de.Properties["Mail"].Value.ToString());
                    Console.WriteLine("User Name     : " + de.Properties["sAMAccountName"].Value.ToString());
                    sw.WriteLine("User Name  : " + de.Properties["sAMAccountName"].Value.ToString());
                           
                    //Call the SendMail Method
                  Utilities.SendMail(de.Properties["sAMAccountName"].Value.ToString(), de.Properties["Mail"].Value.ToString());=======it calls this again
                 
                  }
                catch (Exception ex)
                {
                    string debug = ex.Message;
                }
                Console.WriteLine("===========    End of user   =============");
                sw.WriteLine("===========    End of user   =============");
            }
              Console.WriteLine("===========    End of Listing   =============");
              sw.WriteLine("===========    End of Listing   =============");
            //  Console.ReadLine();
               //Close the file
            sw.Close();
     
            return null;
        }
        #endregion
       
        how do i fix this.
       
        thanks
0
SirReadAlot
Asked:
SirReadAlot
  • 14
  • 7
1 Solution
 
TSmoothCommented:
I think the problem you're running into is that your instance of SmtpClient is locally scoped to your method that is sending the email. Once it goes out of scope, the event handler will no longer be valid because the instance of the object is no longer valid, and thus it will most likely not fire. To work around this, you could setup the SmtpClient before your foreach loop and attach the event handler there as well. Then pass this into your SendMail method.
0
 
SirReadAlotAuthor Commented:
wow,
thanks for the tip.
0
 
SirReadAlotAuthor Commented:
but how comes it works only when there is a readline or a breakpoint
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
TSmoothCommented:
I had wondered that myself at first and what I believe is happening in those cases is that you are delaying the execution of the function long enough for the asyncrhonous event to take place while the SmtpClient object is still in scope.
0
 
SirReadAlotAuthor Commented:
hi,

can u show me how to do this

To work around this, you could setup the SmtpClient before your foreach loop and attach the event handler there as well. Then pass this into your SendMail method.
0
 
SirReadAlotAuthor Commented:
i have this

        #region DirectoryEntry
        public static DirectoryEntry FindUsers(String userName)
        {
            string StartTime;
            DirectoryEntry entry = GetDirectoryEntry();
            DirectorySearcher search = new DirectorySearcher(entry);
            //Pass the filepath and filename to the StreamWriter Constructor
            StreamWriter sw = new StreamWriter("C:\\Test.txt", true);
           StartTime = DateTime.Today.ToString("yyyyMMddHHmmss.Z");
 
   
           search.Filter = ("(&(ObjectClass=user)(whenCreated=20070705153119.0Z))");

            Console.WriteLine("Listing of users in the Active Directory");
            sw.WriteLine("Listing of users in the Active Directory");
            //sw.WriteLine("Date Run : " + StartTime);
            Console.WriteLine("==================================");
            sw.WriteLine("==================================");

            //Create the email server host    
            SmtpClient smtp = new SmtpClient("mail.xxxx.co.uk");    ============================  i added this        
            smtp.SendCompleted += new SendCompletedEventHandler(SmtpClient_OnCompleted);========= and this

            foreach (SearchResult resEnt in search.FindAll())
            {
                try
                {
                    System.DirectoryServices.DirectoryEntry de = resEnt.GetDirectoryEntry();
                    Console.WriteLine("Display Name  : " + de.Properties["DisplayName"].Value.ToString());
                    sw.WriteLine("Display Name  : " + de.Properties["DisplayName"].Value.ToString());
                    Console.WriteLine("WhenCreated : " + de.Properties["whenCreated"].Value.ToString());
                    sw.WriteLine("When Created  : " + de.Properties["whenCreated"].Value.ToString());
                    Console.WriteLine("Email         : " + de.Properties["Mail"].Value.ToString());
                    sw.WriteLine("Email  : " + de.Properties["Mail"].Value.ToString());
                    Console.WriteLine("User Name     : " + de.Properties["sAMAccountName"].Value.ToString());
                    sw.WriteLine("User Name  : " + de.Properties["sAMAccountName"].Value.ToString());
                         
                    //Call the SendMail Method
                  Utilities.SendMail(de.Properties["sAMAccountName"].Value.ToString(), de.Properties["Mail"].Value.ToString());
                 
                  }
                catch (Exception ex)
                {
                    string debug = ex.Message;
                }
                Console.WriteLine("===========    End of user   =============");
                sw.WriteLine("===========    End of user   =============");
            }
              Console.WriteLine("===========    End of Listing   =============");
              sw.WriteLine("===========    End of Listing   =============");
            //  Console.ReadLine();
               //Close the file
            sw.Close();
     
            return null;
        }
        #endregion

how do i accomplish this
Then pass this into your SendMail method.
0
 
TSmoothCommented:
You would modify your SendMail method to be this:

 public static void SendMail(string sAMAccountName, string Mail, SmtpClient smtp)
        {

            //Create the MailMessage object
            MailMessage msg = new MailMessage();
            object userState = msg;

            // Configure basic infomation for an e-mail message
            string FromName = ConfigurationManager.AppSettings["FromName"];
            string FromEmail = ConfigurationManager.AppSettings["FromEmail"];
            string Subject = ConfigurationManager.AppSettings["Subject"];

            //Assign the attachment path
            string FileNameFM = Environment.CurrentDirectory + @"\Attachments\test.doc";
       

            //Create the email server host    
            // SmtpClient smtp = new SmtpClient("****.****.co.uk");                                                                                  
     
            //Assign from address
            msg.From = new MailAddress(FromEmail, FromName);

            //Assign to address
            msg.To.Add(new MailAddress(Mail, sAMAccountName));
           
         
            //assign subject, and body
            msg.Subject = Subject;
            AlternateView htmlView = AlternateView.CreateAlternateViewFromString
           ("<b>Dear Colleagues,</b><br><p>Welcome</p>",   null, "text/html");

            msg.AlternateViews.Add(htmlView);
            msg.Priority = MailPriority.High;

            msg.Attachments.Add(new System.Net.Mail.Attachment(FileNameFM));
     
         
                try
                {
                    //Send the message with SmtpClient
                    smtp.SendAsync(msg,userState);
                      //wire up the event for when the Async send is completed
           smtp.SendCompleted += new SendCompletedEventHandler(SmtpClient_OnCompleted); ======================called it here, some how after it reads this,....
                  }
                catch (SmtpFailedRecipientsException ex)
                {
                    Console.WriteLine("Failed to deliver message to {0}", ex.FailedRecipient);
                }
           
            }


Then change the lines:
 //Call the SendMail Method
                  Utilities.SendMail(de.Properties["sAMAccountName"].Value.ToString(), de.Properties["Mail"].Value.ToString(), smtp);

To this:

 //Call the SendMail Method
                  Utilities.SendMail(de.Properties["sAMAccountName"].Value.ToString(), de.Properties["Mail"].Value.ToString());
0
 
SirReadAlotAuthor Commented:
WILL  try it shortly
0
 
SirReadAlotAuthor Commented:
i have done this

public static void SendMail(string sAMAccountName, string Mail, SmtpClient smtp)
        {

            //Create the MailMessage object
            MailMessage msg = new MailMessage();
            object userState = msg;

            // Configure basic infomation for an e-mail message
            string FromName = ConfigurationManager.AppSettings["FromName"];
            string FromEmail = ConfigurationManager.AppSettings["FromEmail"];
            string Subject = ConfigurationManager.AppSettings["Subject"];

            //Assign the attachment path
            string FileNameFM = Environment.CurrentDirectory + @"\Attachments\test.doc";
       

            //Create the email server host    
            // SmtpClient smtp = new SmtpClient("****.****.co.uk");                                                                                  
     
            //Assign from address
            msg.From = new MailAddress(FromEmail, FromName);

            //Assign to address
            msg.To.Add(new MailAddress(Mail, sAMAccountName));
           
         
            //assign subject, and body
            msg.Subject = Subject;
            AlternateView htmlView = AlternateView.CreateAlternateViewFromString
           ("<b>Dear Colleagues,</b><br><p>Welcome</p>",   null, "text/html");

            msg.AlternateViews.Add(htmlView);
            msg.Priority = MailPriority.High;

            msg.Attachments.Add(new System.Net.Mail.Attachment(FileNameFM));
     
         
                try
                {
                    //Send the message with SmtpClient
                    smtp.SendAsync(msg,userState);
                      //wire up the event for when the Async send is completed
    smtp = new SmtpClient("mail.mace.co.uk");====called it here
                  }
                catch (SmtpFailedRecipientsException ex)
                {
                    Console.WriteLine("Failed to deliver message to {0}", ex.FailedRecipient);
                }
           
            }

and

 #region DirectoryEntry
        public static DirectoryEntry FindUsers(String userName)
        {
            string StartTime;
            DirectoryEntry entry = GetDirectoryEntry();
            DirectorySearcher search = new DirectorySearcher(entry);
            //Pass the filepath and filename to the StreamWriter Constructor
            StreamWriter sw = new StreamWriter("C:\\Test.txt", true);
            StartTime = DateTime.Today.ToString("yyyyMMddHHmmss.Z");

                  search.Filter = ("(&(ObjectClass=user)(whenCreated=20070705153119.0Z))");

            Console.WriteLine("Listing of users in the Active Directory");
            sw.WriteLine("Listing of users in the Active Directory");
            //sw.WriteLine("Date Run : " + StartTime);
            Console.WriteLine("==================================");
            sw.WriteLine("==================================");

            //Create the email server host    
            SmtpClient smtp = new SmtpClient("mail.mace.co.uk");
            smtp.SendCompleted += new SendCompletedEventHandler(SmtpClient_OnCompleted);

            foreach (SearchResult resEnt in search.FindAll())
            {
                try
                {
                    System.DirectoryServices.DirectoryEntry de = resEnt.GetDirectoryEntry();
                    Console.WriteLine("Display Name  : " + de.Properties["DisplayName"].Value.ToString());
                    sw.WriteLine("Display Name  : " + de.Properties["DisplayName"].Value.ToString());
                    Console.WriteLine("WhenCreated : " + de.Properties["whenCreated"].Value.ToString());
                    sw.WriteLine("When Created  : " + de.Properties["whenCreated"].Value.ToString());
                    Console.WriteLine("Email         : " + de.Properties["Mail"].Value.ToString());
                    sw.WriteLine("Email  : " + de.Properties["Mail"].Value.ToString());
                    Console.WriteLine("User Name     : " + de.Properties["sAMAccountName"].Value.ToString());
                    sw.WriteLine("User Name  : " + de.Properties["sAMAccountName"].Value.ToString());


                    //Call the SendMail Method
                    Utilities.SendMail(de.Properties["sAMAccountName"].Value.ToString(), de.Properties["Mail"].Value.ToString(), smtp);

                }
                catch (Exception ex)
                {
                    string debug = ex.Message;
                }
                Console.WriteLine("===========    End of user   =============");
                sw.WriteLine("===========    End of user   =============");
            }
            Console.WriteLine("===========    End of Listing   =============");
            sw.WriteLine("===========    End of Listing   =============");
            //  Console.ReadLine();
            //Close the file
            sw.Close();

            return null;
        }
        #endregion

but only works with breakpoint
0
 
SirReadAlotAuthor Commented:
0
 
TSmoothCommented:
It's still possible that smtp is going out of scope even the way we did it and I was a bit worried about that possibility. It all depends on when the smtp client object sends messages. You could try making the smtp object global to your application so that it exists from the time your application starts til the time you close the application. If your "End of Listing" line is being output to the console before any email message sent messages are being written to the output then this is indeed what is happening. You could try adding a sleep() call after your foreach statement to delay the ending of the method for a set amount of time to see if the Send's complete in that period of time.

Is there a particular reason you are sending them all asynchronously? Does your console application stay running for an extended period of time after the emails are triggered to be sent?
0
 
SirReadAlotAuthor Commented:
...Is there a particular reason you are sending them all asynchronously? Does your console application stay running for an extended period of time after the emails are triggered to be sent?
ans
====
not at all!!!

i needed a way to record if an email was sent or not, i tried catch (SmtpFailedRecipientsException ex) but even if the email fails, nothing is caught.

i saw a couple of sites which suggested that catch (SmtpFailedRecipientsException ex) does actually do anything
0
 
SirReadAlotAuthor Commented:
just need to record if an email was sent or not

http://msdn2.microsoft.com/en-us/library/x5x13z6h.aspx
0
 
TSmoothCommented:
If you just use the smtp.Send instead of the asynchronous version, that "sends" the email immediately and thus technically your email was sent. There's no reason to do it asynchronously. Now if one of the recipients doesn't exist or something like that, there's no way to really track that because kick back emails can take hours or even days to come back and your program would have to monitor an inbox to see if any of these bounced back emails came which in turn would require that your program was always running.

I would simply put a try/catch block around the regular synchronous send method to catch any errors such as an invalid email address or if the smtp client is unable to connect to the server. If the Send() method doesn't cause an exception then you can record that the mail was sent.
0
 
TSmoothCommented:
Also one thing I noticed after reading through the SendAsync method's reference you linked:

"After calling SendAsync, you must wait for the e-mail transmission to complete before attempting to send another e-mail message using Send or SendAsync."

I don't belive your code was doing this which would also explain why you were experiencing issues.
0
 
SirReadAlotAuthor Commented:
i am going to use a regular try method

   try
            {
                //Send the message with SmtpClient
                smtp.Send(msg);=================================synchronous
       
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to deliver message to {0}", ex);
            }
        }
0
 
SirReadAlotAuthor Commented:
Also one thing I noticed after reading through the SendAsync method's reference you linked:

"After calling SendAsync, you must wait for the e-mail transmission to complete before attempting to send another e-mail message using Send or SendAsync."

I don't belive your code was doing this which would also explain why you were experiencing issues.


sure i guess there is no point tracking this as well
0
 
SirReadAlotAuthor Commented:
i think i tried this last week

' If the Send() method doesn't cause an exception then you can record that the mail was sent.'
      try
            {
                //Send the message with SmtpClient
                smtp.Send(msg);
       
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to deliver message to {0}", ex);
            }
        }

see this link
0
 
TSmoothCommented:
What I don't think you're realizing is that in the situation below, if the smtp.Send() fails, nothing inside the "try" block after that line will execute. It will immediately skip everything and go to the catch block. Thus you don't need to do an if statement on the Send() call.  Basically you want all of your code that you had in the SendCompleted event handler to be placed after the Send() call like so:

' If the Send() method doesn't cause an exception then you can record that the mail was sent.'
      try
            {
                //Send the message with SmtpClient
                smtp.Send(msg);
           
                // This will not execute of the send fails. Thus if you get to this line, the mail was sent.
               // Recordt that it was sent here.
                //write out the subject
            string subject = msg.Subject;

           Console.WriteLine("Message [{0}] sent.", subject);
           
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to deliver message to {0}", ex);
            }
        }
0
 
SirReadAlotAuthor Commented:
thanks
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

  • 14
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now