News:

Looking for documentation? Take a look on our wiki

Main Menu

Stopping fake and mistyped customer emails at VirtueMart checkout

Started by SendBridge, Yesterday at 15:20:27 PM

Previous topic - Next topic

SendBridge

Hi everyone,

Disclosure first: I work for SendBridge, an email verification service, and I mention it in step 3. Steps 1, 2 and 4 work without any external service.

The problem this addresses: order confirmations and invoices bouncing because the customer typed "gmial.com", or guest checkouts made with throwaway addresses (often the same people behind fraudulent orders).

VirtueMart only checks the email syntax, so all of these get through. Here is what helped, from simplest to most thorough.

1. Ask for the email twice (core setting)
In the shopper fields manager (Configuration > Shopper Fields) you can add a second email field and compare the two. It's not elegant, but it catches a lot of typos for zero cost.

2. Catch common domain typos before submit
A few lines of JavaScript in your template override of the checkout/registration form can suggest the right domain:

var fixes = {"gmial.com":"gmail.com","gmal.com":"gmail.com","hotmial.com":"hotmail.com","outlok.com":"outlook.com","yaho.com":"yahoo.com"};
jQuery('#email_field').on('blur', function () {
  var v = this.value.trim(), d = v.split('@')[1];
  if (d && fixes[d.toLowerCase()]) {
    if (confirm('Did you mean ' + v.split('@')[0] + '@' + fixes[d.toLowerCase()] + '?')) {
      this.value = v.split('@')[0] + '@' + fixes[d.toLowerCase()];
    }
  }
});

3. Check that the mailbox really exists (server side)
Syntax and typo checks won't tell you whether the mailbox exists or whether it's a disposable inbox. For that you need an MX lookup plus an SMTP-level check. Most shared hosts block outbound port 25, so the usual route is an email verification API over HTTPS instead (for example SendBridge's email address verification service; other providers work the same way). A small system plugin hooks into user/order saving and rejects the address when the API says "invalid" or "disposable":

// plugins/system/emailcheck/emailcheck.php (simplified)
public function plgVmOnUserStore(&$data)
{
    $email = isset($data['email']) ? trim($data['email']) : '';
    if ($email === '') return true;

    $http = Joomla\CMS\Http\HttpFactory::getHttp();
    try {
        $res = $http->get('https://YOUR-VERIFIER/verify?email=' . urlencode($email),
                          ['Authorization' => 'Bearer ' . $this->params->get('api_key')], 3);
        $status = json_decode($res->body)->status ?? 'unknown';
    } catch (Exception $e) {
        return true; // fail open, never block a sale because the API is slow
    }
    if (in_array($status, ['invalid', 'disposable'])) {
        vmError('Please enter a valid, permanent email address.');
        return false;
    }
    return true;
}

Two things to keep in mind:
- Always fail open (short timeout, allow the order on errors), so an outage on the verifier's side never costs you a sale.
- Don't reject "catch-all" results. Plenty of company domains accept every address, so treat those as valid.

4. Clean the existing customer list
If you send newsletters (AcyMailing etc.), export the addresses from #__virtuemart_userinfos / #__users once and run them through the same check before the next campaign. Bounce rates matter a lot for whether your mail lands in the inbox.

Is anyone doing this with a ready-made extension instead? I'd be interested to compare.

Peter Braun (SendBridge)
Peter Braun | SendBridge - email verification API: https://sendbridge.com