How to know whether an email is delivered and read
Introduction
Sending email is very important in many web applications and most web technologies provides built-in classes for that. Microsoft.NET comes with a built-in class named SmtpClient just for that. Although sending email is very easy, because of the nature of communication the difficult part is to know whether the email is successfully delivered and read by the recipient. There are different approaches available to know the delivery status of the email but nothing solves the problem 100%.
In this article I’m going to discuss about the two important ways that are frequently used to know the delivery status of email, one is using read-receipts and the other one is appending an image-tag with the email body.
Email (Electronic Mail) is digital messages that are transmitted from a sender to one more recipients through internet. Emails works in asynchronous way, both the sender and recipient(s) need not to be online at the same time. When analyzing the digital part of the Email, it contains mainly two parts headers and body.
The Headers contains details like sender address, description of the mail (subject), the recipient email address and more.
Ex.
Microsoft Mail Internet Headers Version 2.0
Received: from mail.litwareinc.com ([10.54.108.101]) by mail.proseware.com with Microsoft SMTPSVC(6.0.3790.0);
Wed, 15 Dec 2004 13:39:22 -0800
Received: from mail ([10.54.108.23] RDNS failed) by mail.litware.com with Microsoft SMTPSVC(6.0.3790.0);
Wed, 15 Dec 2004 13:38:49 -0800
From: "Kelly Weadock" <kelly@litware.com>
To: <anton@proseware.com>
Cc: <tim@cpandl.com>
Subject: Review of staff assignments
Date: Wed, 15 Dec 2004 13:38:31 -0800
MIME-Version: 1.0
Content-Type: multipart/mixed;
X-Mailer: Microsoft Office Outlook, Build 11.0.5510
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
Thread-Index: AcON3CInEwkfLOQsQGeK8VCv3M+ipA==
Return-Path: kelly@litware.com
Message-ID: <MAILbbnewS5TqCRL00000013@mail.litware.com>
X-OriginalArrivalTime: 15 Dec 2004 21:38:50.0145 (UTC) FILETIME=[2E0D4910:01C38DDC]
...
The body contains the content of the email either as text or html.
Read-Receipts
A Read-receipt is returned from the receiver to the sender when the email is read successfully by the recipient. Microsoft Outlook employs this mechanism but not all the email applications supports this, not only that a recipient can disable sending receipts altogether. Because of these factors, Read-receipts are not a completely reliable way of knowing the delivery of emails. The Read-receipt can be implemented by inserting one or more of the following lines into the email headers: X-Confirm-Reading-To, Disposition-Notification-To or Return-Receipt-To.
In the receiving side based upon the mail settings the user is forced to send a notification on opening the email. The notification is usually sent as another email to the address sent with the header.
var message = new MailMessage("sender@mainhost.com", "receiver@subhost.com"); message.Subject = "Read receipt test"; message.Body = "This email is just to check whether you can send read-receipts from your email application."; // add the header that requests the user to send a receipt message.Headers.Add("Disposition-Notification-To", "sender@mainhost.com"); var client = new SmtpClient("emailhost.com"); client.Send(message);
Listing 1. Sending email with read-receipts
In the above sample code we have added the header Disposition-Notification-To passing the sender's email address. So all the receipts are returned to the sender.
Opt-out mechanism using image
This mechanism is better than the receipts but still there are limitations. This mechanism won’t work if the user has disabled images in the receiving side and also the emails has to be in HTML format.
The idea is simple!
An image is embedded in the email body which has an SRC attribute pointing to some external resource for ex. an ASPX page or a web service etc. When the user tries to read the message, the image issues a GET request to the external resource passing necessary parameters in query-string. The external-resource processes the request say do some logging and finally return a transparent GIF image.
// a unique-id to attach with the mail var messageId = Guid.NewGuid(); // the server that receives the request from the image and process it var deliveryProcessor = "http://localhost:5555/email-delivery.aspx"; // constructing the image tag with "src" pointing to the external resource // passing the unique-id in the query-string. var imgTag = string.Format(@"<img src=""{0}?msg_id={1}"" alt="" width=""0"" height=""0"" style=""width: 0px; height: 0px; border:0px;"" />", deliveryProcessor, messageId); var message = new MailMessage("sender@mainhost.com", "receiver@subhost.com"); message.Subject = "Email delivery test using images"; message.Body = "An image is attached with this email, please enable the images on reading the email so we will know you got the email."; // append the image tag at the end of the body. message.Body += imgTag; message.IsBodyHtml = true; var client = new SmtpClient("emailhost.com"); client.Send(message);
Listing 2. Sending email with hidden image (assume you've this code in email-send.aspx)
In the above code we have appended an image element to the email body that has dimensions 0px pointing to a resource http://localhost:5555/email-delivery.aspx. We also passed a unique-id that identifies the email in query-string. One more important thing is, since the email has to be in html format the IsBodyHtml property has to be set to true.// Read the message id from the query-string and do some operation. // Return a transparent GIF image. protected void Page_Load(object sender, EventArgs e) { var messageId = Request.QueryString["msg_id"]; if(!string.IsNullOrEmpty(messageId)) { // do something.. like update the database that the message // is read by the recipient. } Response.ContentType = "image/gif"; Response.WriteFile(Request.MapPath("~") + "\\" + "1ptrans.gif"); Response.End(); }
Listing 3. The ASPX page (email-delivery.aspx) that processes the callbacks and returns transparent GIF
The above code describes how the ASPX page processes the callback. It retrieves the message id from querystring, do some processing and finally returns the transparent GIF image.
Summary
In this article we saw about couple of options to know whether the email is successfully delivered and read by the user. The first approach is using read-receipts and not all the email applications supports this and the second one is using a transparent GIF image that will work in most of the cases but the email has to be in the html format and the recipient should enable images in the receiving side.
Hope you enjoyed this article, feel free to share your comments.