Everybody knows that the minute you put your email address into the href attribute of an <A> tag with a mailto: prefix, the spam harvesters are going to scrape it and it will increase the amount of absolutely ludicrous spam that (hopefully at least) ends up in your Junk Mail folder.
There are a number of ways to make a "mailto:" link continue to work but to provide obfuscated glop to the spambot harvesting crawlers that is completely useless to them, since they examine the html of the page, not what you "see" in the rendered page.
One way to do this is to convert everything into it's HTML Entity representation. Browsers are happy with this, but since spambots cannot see anything in the HTML they have scraped from the page that Regex-es into what could be an email address, they typically miss it.
There are a number of javascript examples that will do this, but up until today I have not seen any ASP.NET controls that perform this useful action of "entity-izing" the email link.
So, I decided to have a little fun and write a control, and put it out into the public domain for .NET developers. Now when authoring a custom control to perform some functionality, the first thing we should ask ourselves as developers is whether there is already a control that we can derive our class from in order to save time with existing needed functionality that's already present.
And of course in this case, the answer is yes - we have the ASP.NET Hyperlink control; all we really need to do is provide a feature where if the NavigateUrl contains "mailto:" we take over from there.
So this control derives from Hyperlink, and all I needed to do to put it together was to override the control's Render method, and provide my own private method to obfuscate the content that follows so that it works as a mailto: link in the page but is useless to spambot harvesters and the horses-ass punk script kiddies that run them. I don't know about you, but when the last scumbag email spammer is in jail, I will sleep well at night.
Here's the code:
using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
[assembly : TagPrefix("PAB.WebControls", "pab")]
namespace PAB.WebControls
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:EmailLink runat=server></{0}:EmailLink>")]
public class EmailLink : HyperLink
{
private string HtmlObfuscate(string text)
{
string tempHtmlObfuscate = null;
int i = 0;
int acode = 0;
string repl = "";
tempHtmlObfuscate = text;
for (i = tempHtmlObfuscate.Length; i >= 1; i--)
{
acode = Convert.ToInt32(tempHtmlObfuscate[i - 1]);
if (acode == 32)
{
repl = " ";
}
else if (acode == 34)
{
repl = "\"";
}
else if (acode == 38)
{
repl = "&";
}
else if (acode == 60)
{
repl = "<";
}
else if (acode == 62)
{
repl = ">";
}
else if (acode >= 32 && acode <= 127)
{
repl = "&#" + Convert.ToString(acode) + ";";
}
else
{
repl = "&#" + Convert.ToString(acode) + ";";
}
if (repl.Length > 0)
{
tempHtmlObfuscate = tempHtmlObfuscate.Substring(0, i - 1) +
repl + tempHtmlObfuscate.Substring(i);
repl = "";
}
}
return tempHtmlObfuscate;
}
protected override void Render(HtmlTextWriter writer)
{
HyperLink link = this;
writer.Write("<a");
if (!string.IsNullOrEmpty(link.NavigateUrl))
{
if (link.NavigateUrl.StartsWith("~"))
writer.WriteAttribute("href", link.ResolveClientUrl(link.NavigateUrl));
else if (link.NavigateUrl.StartsWith("mailto:"))
{
link.NavigateUrl = HtmlObfuscate(link.NavigateUrl);
writer.WriteAttribute("href", link.NavigateUrl);
}
else
{
writer.WriteAttribute("href", link.NavigateUrl);
}
}
if (!string.IsNullOrEmpty(link.CssClass))
writer.WriteAttribute("class", link.CssClass);
if (!string.IsNullOrEmpty(link.Target))
writer.WriteAttribute("target", link.Target);
foreach (string key in link.Attributes.Keys)
writer.WriteAttribute(key, link.Attributes[key]);
writer.Write(">");
RenderContents(writer);
writer.Write("</a>");
}
protected override void RenderContents(HtmlTextWriter output)
{
output.Write(Text);
}
}
}The nice thing about this is that you can still use it as a regular Hyperlink control, the cool stuff only happens if the NavigateUrl property begins with "mailto:". You can also do stuff like this:
NavigateUrl = "mailto:you@yourDomain.com?subject=hi, wanted to get back to you&cc=otherguy@yourdomain.com"
-- and it will take care of the whole thing so when you click on the link, it comes up in your default email client with the TO, the Subject and the CC all prefilled in.
You can download the Visual Studio 2005 Control solution, which includes a Web Application Project "tester" app. Remember, the less food we give the email spambot crawlers to chew on, the better off we'll all be. Keep all your email links obfuscated. |