views:

182

answers:

3

Hi

I am sending email using the following utility class, if receiver [email protected] is not exist or the email never reach him for one reason or another, I want my application to be notified.

It works only when the smtp client failed to connect to the smtp server, I got an exception in this case, otherwise, the only way to know if email fail to reach the client is by checking client account.

 public static class EmailUtil
    {
        /// <summary>
        /// Fires exception if string is null or empty
        /// </summary>
        /// <param name="param">param value</param>
        /// <param name="paramName">is the parameter name to be shown in the exception message</param>
        private static void CheckStringParam(string parameter, string paramName)
        {
            if (String.IsNullOrEmpty(parameter))
            {
                throw new ArgumentException(String.Format("{0} can't be null or empty", paramName));
            }
        }

        public static void SendEmail(EmailArgument emailArg)
        {
            CheckStringParam(emailArg.FromEmail, "emailArg.FromEmail");
            CheckStringParam(emailArg.Subject, "emailArg.Subject");
            CheckStringParam(emailArg.Body, "emailArg.Body");
            string body = emailArg.Body;

            MailMessage mailMsg = new MailMessage();
            mailMsg.From = new MailAddress(emailArg.FromEmail);

            foreach(string recipient in emailArg.ToEmails)
            {
                if (String.IsNullOrEmpty(recipient))
                {
                    throw new ArgumentException("One of the values in the emailArg.ToEmails array is null or empty");
                }

                mailMsg.To.Add(new MailAddress(recipient));
            }

            mailMsg.IsBodyHtml = emailArg.IsHtml;

            if (emailArg.PutHtmlTags)
            {
                body = String.Format("{0}" + body + "{1}", "<HTML><Body>", "</Body></HTML>");
            }

            mailMsg.Body = body;
            mailMsg.BodyEncoding = emailArg.BodyEncoding;

            // Get client info from the config file , it is tested with Web.config, need to be tested with App.config
            SMTPConfiguration smtpConfig = (SMTPConfiguration)System.Configuration.ConfigurationManager.GetSection("SMTPConfigurationGroup/SMTPServer");

            SmtpClient client = new SmtpClient(smtpConfig.Host, smtpConfig.Port);
            client.EnableSsl = smtpConfig.EnableSSL;
            client.Credentials = new System.Net.NetworkCredential(smtpConfig.Username, smtpConfig.Password);



            // The notifications of failure are sent only to the client email.
            // Exceptions are not guranteed to fire if the Receiver is invalid; for example gmail smtp server will fire exception only when [email protected] is not there. 
            // Exceptions will be fired if the server itself timeout or does not responding (due to connection or port problem, extra).
            mailMsg.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;

            client.Send(mailMsg);            
        }


    }
+6  A: 

SMTP is a 'best effort' transport. Once you send the message to the SMTP server, you can't really know if it got to the destination or not (which may take days if there are connectivity problems along the way). You might get an email back (like I said - possibly days later) from some SMTP server along the way that that the delivery failed.

Note that even if you add a header to the message indicating that you want positive acknowledgment that the message was received, clients can be configured or instructed not to send such notification.

Michael Burr
I wonder if there is some way that we can use the protocol to at least return an error code based on the address existing?
IrishChieftain
@IrishChieftain: Chances are that the server you connect to doesn't know. To have a chance of it knowing, you'd have to connect to an SMTP server for the domain the email address is in. Even then, there's no guarantee that the server will know if the address is valid. SMTP is designed to work without the server knowing everything about the destination - it just needs to know enough to pass it on to something that should know even more.
Michael Burr
And most servers now return "OK" even when addresses are known not to be valid at a particular SMTP server. It's also a limited countermeasure against spam.
JasonTrue
+2  A: 

Web beacon is the most common tool for e-mail tracking. It usually is a small transparent image 1px x 1px embeded in the html of an e-mail message. By embeded I mean an img tag - here is an example: <img src="www.somedomainhere.com/someimge.gif?[tracking_code]" />. Then you can log every request to that image. This method works only if the user is able to read HTML formated messages.

Pavel Nikolov
and their client downloads them (outlook does not by default, nor does yahoo)
dkackman
Oho... that's something new and cool.
Arnis L.
Even if they allow HTML, many email clients now block externally-linked images until you give them explicit permissions, thanks mostly to abuse by spammers using them to verify email address targets.
JasonTrue
@JasonTrue - This method does NOT work in 100% of the cases but it is the most common one. I've used it and it worked for me.@dkackman - You can use iframes instead of images (I haven't tested whether outlook blocks iframes).
Pavel Nikolov
@Pavel: Any competent mail client would block loading of all external content until told otherwise.
Novelocrat
It won't tell you that email address wasn't opened, but it's an adequate indicator that a message was opened. So it doesn't tell you that the mail "didn't reach" the user, only that there's no evidence that it arrived.
JasonTrue
A: 

Please see this where I posted an answer in relation to this on superuser.com, that may be the thing you are looking for...

Hope this helps, Best regards, Tom.

tommieb75