Introduction
So, you had a fight with your girlfriend and she is not taking your phone calls. You left countless messages but she never replied. You sent her emails but have no idea that if she checked them or not. In these situations it will be a good idea to get a notification when your girlfriend has opened her email. This will give you a little piece of mind that at least she is reading your emails. Let's see how we can implement this functionality.
Basic Idea
The basic idea is to embed a very small invisible image in the email. The image will contain a GUID as a query string. The image is downloaded by the client which makes a request back to the server and sends the query string. The query string is extracted and the field in the database is updated indicating that the user has checked the email.
Creating an Invisible Image
You can create a very small image with a white background. This can be as small as a dot. In this article we have made the image larger so that you will have a better idea of what we are talking about. Take a look at the image below:
The image above also contains the red dot. The red dot is only used so that you will have a better idea where the image is displayed. In actual production code you will use a much smaller image.
Attaching a GUID with Image
The next step is to attach a Guid as a query string with the image. In production code this Guid will come from a database table which will be used to track which user has checked their email and which has not but in this case we will be creating a dummy Guid. Take a look at the following code which attaches a Guid with the image URL as a query string parameter.
protected string GetImageUrl()
{
return String.Format(<a href="%22http://localhost:1404/WhiteImage.png?id={0}"">http://localhost:1404/WhiteImage.png?id={0}</a>,
Guid.NewGuid().ToString());
}
And here is the ASPX code that uses the GetImageUrl
method.
<form id="form1" runat="server">
<div>
This is some email that I am reading. This is a test email.
<img src='<%= GetImageUrl() %>' />
</div>
</form>
The HTML produced by the above code will look something like this:
Our next task is to handle the request from our WhiteImage.png image. The best way to handle this request is to create a custom HttpHandler.
Creating EmailViewedNotificationHandler
The purpose of EmailViewedNotificationHandler
is to intercept the request for WhiteImage.png and then update a field in the database and finally render the image to the browser. The ProcessRequest
method is where the magic happens. Let's take a look at the ProcessRequest
implementation.
public void ProcessRequest(HttpContext context)
{
string id = context.Request.QueryString["id"] as String;
if (String.IsNullOrEmpty(id)) return;
Guid guid = new Guid(id);
_emailNotificationService.MarkEmailRead(guid);
MemoryStream ms = new MemoryStream();
Bitmap bitMap = new Bitmap(context.Request.PhysicalPath);
bitMap.Save(ms, ImageFormat.Png);
byte[] buffer = ms.ToArray();
context.Response.Clear();
context.Response.ContentType = "image/png";
context.Response.BinaryWrite(buffer);
context.Response.End();
}
The ProcessRequest
method first extracts the query string and gets the Guid. Then the EmailNotificationService
class is used to update the Guid status in the database. This class is not implemented in the article. Finally, the image is written to the MemoryStream
which is outputted to the client.
Adding HttpHandler Configuration in Web.Config
In order to work with the new HttpHandler you will need to register it in the Web.config file. Take a look at the following code that does this:
<httpHandlers>
<remove verb="*" path="*.asmx"/>
<add verb="*" path="WhiteImage.png"
type="LearningWebApplication.EmailViewedNotificationHandler"/>
</httpHandlers>
You might also want to adjust your FileMappings
in IIS to work with the new HttpHandler.
Conclusion
In this article we learned how to create a simple HttpHandler that will notify the sender when the email is opened. This can be useful in scenarios where viewing of an email is absolutely necessary.
NOTE: If the client has an image blocking filter active then the image will never be downloaded and the above code will not work.
UPDATE: You can also use the .GIF transparent images
References
- Sending Emails in ASP.NET 2.0
- Sending Emails in ASP.NET