How to stop spam -too with mailto links.
Tags: javascript, spam, html, ux
Published: 2023-05-27 12:09:05

As website owners, the incessant invasion of spam into our email inboxes via contact forms is a persistent challenge. Addressing this issue requires innovative thinking and unique solutions to maintain a clean and efficient communication channel with our users.

## A typical contact form

The traditional HTML contact form comprises fields for name, email, and a message. Below you can see a typical HTML contact form for any website.


```
<form method="POST" action="...">

  <label for="name">Name</label>
  <input name="name" type="text" />

  <label for="email">Email</label>
  <input name="email" type="email" />

  <textarea rows="50" cols="25" />

</form>
```

### Name

Of course, you want to know the name of the person who tries to contact you. So asking for the name sounds fair, anyway a name does not matter in the first place. 

This makes the input **optional** but welcomed.

### Email

In most of the cases the purpose of a contact form is to start a conversation, so an email address is required to reply. But at this point, you do not know if this email belongs to an actual human being. You can use a verification mechanism to ensure that the email is valid, but you do not if this email is sound. 

This makes the input **crucial** but prone to abuse.

### Message

This field is essential since you want to know what the person wants from you, right!? But here the pain begins. You do not know what they are writing and you should not restrict the people in their words.

## Spam detection

Identifying spam with 100% accuracy is not possible! But there are some ways to minimize the amount of spam finding its way to your inbox.

### Content Filtering

One of the first approaches you might think of is to check the input for suspicious content, e.g. valid email address or suspicious words like _Bitcoin_.

This will work to a certain degree, but there are still plenty of possibilities to surpass those checks. For instance by writing _BTC_ or _Crypto_.

So, you see there will be a lot of maintenance to check all of the "evil" words you do not want in your inbox. 

### Third-Party Libraries

Another option would be to use third-party libraries, that check the contact form against common suspicious content or behavior. 

One popular solution is by solving a Captcha or Puzzle to verify that the message is sent by a human and not by a bot. Therefore, you need to add third-party scripts or an API to perform those checks. But one of the biggest side effects is, that real human beings are confronted now with a popup asking them to solve a stupid riddle or selecting proper images. From a user experience standpoint, this is a solution you should never anticipate!

### Low-Code / No-Code 

Currently, a very promising way to provide online contact forms is to use low-code or no-code solutions, where you just redirect the form as a proxy by the provider. So the `action` attribute of the HTML form will be the URL of the form-as-a-service provider that automatically checks for spam. But these solutions arise other concerns regarding privacy since you redirect the form to a third party that handles personal information and forwards the content as email or push notification to your devices of choice. 

## Thinking outside the box

After trying every example above, and implementing dozens of libraries that claim to prevent spam it was time to rethink the whole contact form situation. 

We wanted a solution that ...

- does not blow up the code base,
- does not require third-party scripts, and
- does not negatively impact user experience.

After brainstorming we came up with a nowadays **uncommon solution**:

### A mailto-link

Everybody knows those buttons on a website that says "contact" and as soon as you click on it your default email program pops up. In the past, this was not a very user-friendly approach, since most users were confused. They expected a contact page or a contact form to see on the screen first. So how can a solution look like, that combines a contact form and a mailto-link?

At first, we removed the name and the email input fields. The big advantage of the mailto-link is that the email is sent by the users' email program, so there is absolutely no need to verify the email address. Bots do not own email programs or post inboxes. Bots just follow commands. And as mentioned earlier the name is not that much important at first contact.

The new contact form looks like this now:

```
<form method="POST" action="#" name="mailto_form" id="contact" onkeyup="generate_mailto()">
  
  <label for="subject">Subject</label>
  <input id="subject" type="text" name="subject" >

  <label for="message">Message</label>
  <textarea name="message" id="message" cols="30" rows="10">
  </textarea>

  <a href="mailto:..." id="mailto-link" role="button">
    Send with (with email-program)</a> to
  <a href="mailto:...">...</a>.
</form>
```
{% codepen https://codepen.io/Manuel-Steinberg/pen/bGmJWZJ
 %}

Instead of the name, we are asking for a summary, like a subject of an email and maybe you have already noticed that there is a JavaScript event attribute present (`onkeyup`) that is triggered after every key press inside the form.

### The JS-function `generate_mailto()`

Let´s have a look at it...

```
function generate_mailto() {

  var mailto= "mailto:mail@domain.tld"
    , subject = encodeURIComponent(document.mailto_form.subject.value)
    , message = encodeURIComponent(document.mailto_form.message.value);

  mailto += "?subject=" + subject,
  mailto += "&body=" + message,

  document.getElementById("mailto-link").href = mailto,
}
```

So, every time the content changes the mailto-link will be updated with a corresponding subject and message as the body. That information will be added as an additional parameter to the mailto-link. When a user clicks on the link the default email app will open and the corresponding subject and message will be set as a template.

### Masking the email address

But what about the recipient email address that is visible in plain text at the moment you may ask... A valid and important point! Once a bot crawled the HTML code of your contact page it will surely recognize the email address and will use this one for spam.

There is one step left to tackle this issue. Email obfuscation with Unicode representation. For example, the email "mail @ domain.tld" becomes 

{% details Unicode representation %} "\u006d\u0061\u0069\u006c\u0040\u0064\u006f\u006d\u0061\u0069\u006e\u002e\u0074\u006c\u0064" {% enddetails %}

A quick and dirty conversion in JavaScript might look like the following:

```
var mail = "mail@domain.tld";

// Convert to array
let unicode = Array.from(mail);

// Convert char to unicode
unicode = unicode.map(function(item) { 
  let charCode = item.charCodeAt(0);
  return "\\u" + charCode.toString(16).padStart(4, '0');
});

// Convert back to string
unicode = unicode.join('');

console.log(unicode);
//\u006d\u0061\u0069\u006c\u0040\u0064\u006f\u006d\u0061\u0069\u006e\u002e\u0074\u006c\u0064
```

But, no worries there are also tools available one that can do the job for. probably you only need a conversion once and that is it. And this string we can now use for our default declaration as seen in the function `generate_mailto()`. And to mitigate the plain text issue for the part with the email address, we use JavaScript to print it respectively. Therefor, we replace the plain text inside the `<a>`tag with some JavaScript using `document.write()`.

```
<a href="javascript:location='mailto:...';void 0">
  <script type="text/javascript">
    document.write('...')
  </script>
</a>
```

Of course, this solution requires JavaScript enabled on the visitors' side, but this seems to be a reasonable trade-off to achieve the goals mentioned above.

The final HTML form as a template:

```
<form method="post" action="#" name="mailto_form" id="formular" onkeyup="generate_mailto()"> 

  <label for="subject">Subject</label>
  <input id="subject" type="text" name="subject">
 
  <label for="message">Message</label> 
  <textarea name="message" id="message" cols="30" rows="10"> 
  </textarea>

  <!-- Obfuscate Email -->
  <a href="javascript:location='mailto:...';void 0" id="mailto-link" role="button">Open Email programm and send message
  </a> to 

  <a href="javascript:location='mailto:...';void 0">
    <script type="text/javascript">document.write('...')</script>
  </a>.

</form>

<script type="text/javascript">
  function generate_mailto() {
    ... // See the code above
  }
</script>
```

Have a look at the demo and see how the link changes when the subject or message has been changed by hovering with the mouse cursor over the button saying *Send with (with email-program)*

{% codepen https://codepen.io/Manuel-Steinberg/pen/yLRrXye
 %}

## Conclusion

Website owners often struggle with spam in their email inboxes when using contact forms. While various approaches like content filtering, third-party libraries, or low-code solutions exist, they come with drawbacks such as growing codebase, negative user experience, or privacy concerns. Thinking outside the box, a less common but effective solution is to utilize a mailto-link combined with JavaScript to generate the email dynamically. By obfuscating the email address using Unicode representation, the risk of bots harvesting the address is also reduced, not eliminated. This approach offers a lightweight and user-friendly solution without relying on external dependencies or compromising the user experience.

Also, this solution might seem outdated a couple of users already mentioned that the experience was kind of refreshing due to its uniqueness. Some users also mentioned that it feels magical that they type a message online and it will be immediately copied over to a new email. Also with this approach by sending the contact form with their email program on the users' end, the user can be sure that the form was sent since the emails appears in the folder within their email program.