February 8, 2007

ASP.NET 2.0 Mask Your Email Addresses With Dynamically Generated Images

There's already a gazillion blogs and articles all copying each other on creating images dynamically and serving them as the HTTP response. Here's a practical example that demonstrates using this technique to dynamically generate an image representing an email address. Suppose you have a website that shows user's email addresses in their profiles. Showing an image of your user's email addresses rather than plain text or hyperlinks reduces the amount of email address harvesting that might otherwise occur.

Start by creating a web page, say /test/Default.aspx. You'll access the page and can test this out using your web browser. For example:

http://mywebsite.com/test/?txt=someone@mywebsite.com&bk=255,255,255&fg=0,0,0&fo=Arial&w=400&h=15&of=gif

The various URL parameters define the image that you desire. I support gif & jpeg. The txt= URL parameter is just there for testing purposes. If you were to encode email addresses this way they'd obviously be a lot easier to harvest. So I recommend replacing this parameter with an id parameter, perhaps the id representing the website user or profile.

Using the image generator in a page is simple:
Email: <img src="/test/?txt=someone@mywebsite.com&bk=255,255,255&amp;amp;fg=0,0,0&fo=Arial&w=400&h=15&of=gif" />

You can of course customize the image with alt="", width, height etc.

Here's the page code. There's no validation and it's not super clean. I won't bother explaining all the code because the API docs are easy enough to understand along with all the other examples out there. My approach does render a high quality gif that will look comparable to the rendered HTML on your web browser. The footprint of the generated file is pretty small.


using System;
using System.Data;
using System.Drawing;
using System.Drawing.Text;
using System.Drawing.Imaging;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

namespace tools.emailgen
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string text = Request["txt"];
String bkgColor = Request["bk"];
string[] bkgColorParts = null;
String fgColorStr = Request["fg"];
string[] fgColorParts = null;

ImageFormat imgFmt = Request["of"] == null ? ImageFormat.Jpeg :
Request["of"].ToLower().Equals("gif") ? ImageFormat.Gif :
ImageFormat.Jpeg;

if (!String.IsNullOrEmpty(bkgColor))
{
bkgColorParts = bkgColor.Split(',');
}
if (!String.IsNullOrEmpty(fgColorStr))
{
fgColorParts = fgColorStr.Split(',');
}

String fontStr = Request["fo"];
int fontSize = Request["fs"] == null ? 10 : Convert.ToInt32(Request["fs"]); ;

int width = Request["w"] == null ? 400 : Convert.ToInt32(Request["w"]);
int height = Request["h"] == null ? 15 : Convert.ToInt32(Request["h"]);

Bitmap bmp = new Bitmap(width, height);
Graphics graphics = Graphics.FromImage(bmp);

System.Drawing.Color bgColor;
System.Drawing.Color fgColor;

if (bkgColorParts != null && bkgColorParts.Length == 3)
{
bgColor = Color.FromArgb(Convert.ToInt32(bkgColorParts[0]),
Convert.ToInt32(bkgColorParts[1]),
Convert.ToInt32(bkgColorParts[2]));
}
else
{
bgColor = Color.FromArgb(255, 255, 255);
}
if (fgColorParts != null && fgColorParts.Length == 3)
{
fgColor = Color.FromArgb(Convert.ToInt32(fgColorParts[0]),
Convert.ToInt32(fgColorParts[1]),
Convert.ToInt32(fgColorParts[2]));
}
else
{
fgColor = Color.FromArgb(255, 255, 255);
}

SolidBrush bgBrush = new SolidBrush(bgColor);
SolidBrush brushWrite = new SolidBrush(fgColor);

graphics.FillRectangle(bgBrush, 0, 0, width, height);
graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
// graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

graphics.DrawString(text,
new Font(fontStr, fontSize), brushWrite, new Point(0, 0));

Response.ContentType = String.Format("image/{0}",
imgFmt);
bmp.Save(Response.OutputStream, imgFmt);
Response.End();
}
}
}



Hope that comes in handy. Rick Strahl also has a nice article on creating thumbnail images on the fly should that be something else you're looking to do.

2 comments:

Comedy Kid said...

You could also just use a Web 2.0 (online) image generator to create a dynamic clipart image with your custom text message (or email address) on www.ImageGenerator.org, good alternative for those not having a web server with ASP GDI installed...

Shan Plourde said...

True, providing you're ok with the caveats of doing so - watch out for service provider throughput, quality and longevity if you're using a free third party like that. Or, roll your own on a hosting provider that allows this and access it that way.