Over before it started — how to not bounce mistyped user emails

Email is the lifeblood of modern web applications. It‘s how we welcome new users, confirm key actions, deliver content and notifications, and bring people back when they haven‘t engaged for a while. But what good is an email if it never reaches the intended recipient?

One of the biggest challenges in managing email campaigns is avoiding hard bounces due to invalid, mistyped, or non-existent addresses. As a full-stack developer who has built several web apps relying heavily on email, I‘ve learned that a little proactive validation can go a long way in keeping your list clean and your sender reputation intact.

The cost of bad email addresses

Before we dive into specific validation techniques, let‘s take a look at some eye-opening industry data on email bounce rates.

Industry Hard Bounce Rate
Agriculture 0.61%
Education 0.72%
Financial Services 0.56%
Healthcare Services 0.58%
IT/Tech/Software Services 0.45%
Manufacturing 0.78%
Marketing/Advertising 0.53%
Media/Publishing 0.44%
Nonprofit 0.46%
Real Estate 0.82%
Retail 0.43%
Travel/Transportation 0.87%

Source: Campaign Monitor

As you can see, even in the best performing industries, a little over 0.4% of emails hard bounce on average. That means for every 10,000 emails sent, 40 will never reach the intended recipient. In the worst industries, it‘s closer to 80-90 emails per 10,000.

While those numbers may seem small, they add up quickly, especially for high-volume senders. If you‘re sending 100,000 emails per month, a 0.5% bounce rate translates to 500 lost emails and potentially 500 lost users or customers.

But the cost of bounced emails goes beyond just lost opportunities. High bounce rates can also damage your sender reputation and deliverability with major ISPs and email providers. If too many of your emails bounce, you risk being labeled as a spammer and having all your emails blocked or routed to the junk folder.

According to Sender Score‘s 2018 Annual Report, senders with a reputation score of 91-100 (the best possible range) had an average hard bounce rate of just 0.85%. By contrast, senders scoring 71-80 had a hard bounce rate of 4.11% — over 4x higher.

Validating email addresses

So what can you do to keep invalid emails off your list in the first place? As a full-stack developer, you have several tools at your disposal.

Client-side validation

The first and most basic line of defense is to validate the format of the email address in the user‘s browser before the form is even submitted. At a minimum, you‘ll want to check for the presence of an @ sign and a period in the domain portion of the address.

Here‘s a simple JavaScript function using a regular expression to test for proper email format:

function isValidEmail(email) {
  const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return re.test(email);
}

You can easily integrate this into your frontend form validation logic to prevent users from submitting badly formatted addresses. However, this alone is not sufficient, as it‘s still possible for users to enter correctly formatted addresses that don‘t actually exist, like [email protected].

DNS and SMTP validation

For more robust validation, you‘ll need to go beyond checking the address format and actually verify that the domain exists and can receive email. This is where DNS and SMTP come in.

The Domain Name System (DNS) is like the phone book of the internet, mapping human-readable domain names to machine-readable IP addresses. By querying DNS, you can check if the domain in the email address has a valid MX record, indicating that it is configured to receive email.

Here‘s an example of a DNS lookup in Node.js using the built-in dns module:

const dns = require(‘dns‘);

function hasMxRecord(email) {
  const domain = email.split(‘@‘)[1];

  return new Promise((resolve, reject) => {
    dns.resolveMx(domain, (err, addresses) => {
      if (err || addresses.length === 0) {
        resolve(false);
      } else {
        resolve(true);
      }
    });
  });
}

If the domain has a valid MX record, the next step is to attempt to open an SMTP connection and verify that the specific email address exists. This is known as an SMTP "callback" and involves pretending to send an email to the address and checking the server‘s response.

Here‘s a simplified example using the nodemailer library:

const nodemailer = require(‘nodemailer‘);

async function emailExists(email) {
  const transporter = nodemailer.createTransport({
    host: ‘mail.example.com‘,
    port: 25,
    tls: {
      rejectUnauthorized: false
    }
  });

  try {
    await transporter.verify();
    await transporter.sendMail({
      from: ‘[email protected]‘,
      to: email,
      subject: ‘Verify Email‘,
      text: ‘Please ignore this email.‘
    });
    return true;
  } catch (err) {
    if (err.code === ‘EENVELOPE‘) {
      return false;
    } else {
      throw err;
    }
  }
}

If the address does not exist, the SMTP server will return an error with the code "EENVELOPE". However, it‘s important to note that not all SMTP servers support callbacks, so the absence of an error does not necessarily guarantee the address is valid.

Third-party APIs

For the most comprehensive email validation, many developers turn to third-party APIs that combine multiple techniques and data sources. Services like Kickbox, NeverBounce, and ZeroBounce can check an email address against their own internal databases of known bounced and low-quality addresses in addition to performing DNS and SMTP checks.

Using a validation API is usually as simple as sending a GET request with the email address as a query parameter and parsing the JSON response. For example, here‘s how you might use the Kickbox API in Node/Express:

const axios = require(‘axios‘);

async function validateEmail(email) {
  const apiKey = process.env.KICKBOX_API_KEY;
  const url = `https://api.kickbox.com/v2/verify?email=${email}&apikey=${apiKey}`;

  try {
    const response = await axios.get(url);
    const { result, reason, role, disposable, accept_all, sendex } = response.data;

    if (result === ‘deliverable‘) {
      return {
        valid: true,
        roleAccount: role,
        disposable,
        catchAll: accept_all,
        reputation: sendex
      };
    } else {
      return {
        valid: false,
        reason
      };
    }
  } catch (err) {
    console.error(err);
    return {
      valid: false,
      reason: ‘Error validating email‘
    };
  }
}

The Kickbox API returns a wealth of data beyond just a valid/invalid boolean, including whether the address is a role account (e.g. info@, sales@), a disposable address, or a "catch-all" address that accepts mail for any username at the domain. It even provides a "Sendex" score from 0-1 indicating the desirability of the address from a deliverability standpoint.

Of course, using a third-party API comes with some trade-offs. It introduces an external dependency and potential point of failure for your application. It also means trusting the service to handle your users‘ email addresses appropriately and securely. And depending on your sending volume, it can add a non-trivial cost as most services charge per validation.

Best practices beyond validation

While proactive validation is essential for maintaining list quality, it‘s just one part of a holistic email hygiene strategy. Here are some other best practices I‘ve learned as a full-stack developer and email marketer:

  1. Use double opt-in whenever possible. Requiring new subscribers to click a confirmation link in their inbox ensures you have a valid, engaged address. It also protects you from bots and malicious signups.

  2. Honor unsubscribes and bounces promptly. If a user opts out of your emails or their address consistently bounces, stop sending to them immediately. Continuing to email them will only hurt your sender reputation.

  3. Authenticate your sending domain. Setting up SPF and DKIM records for your domain helps prove to ISPs that you are a legitimate sender and not a spammer spoofing your identity.

  4. Monitor your bounce and complaint rates closely. A sudden spike in either metric is a sign that something is wrong with your list or content. Investigate and correct the issue promptly to avoid long-term damage to your reputation.

  5. Periodically re-engage or remove inactive subscribers. If a user hasn‘t opened or clicked your emails in several months, try sending a targeted re-engagement campaign. If they still don‘t respond, it‘s best to remove them from your list rather than continue sending to an unengaged address.

Finally, it‘s worth mentioning that collecting and storing email addresses comes with some legal responsibilities, particularly under laws like the EU‘s General Data Protection Regulation (GDPR). Make sure you have clear language in your sign-up forms and privacy policy explaining how you will use subscribers‘ email addresses and how they can opt out or request deletion of their data.

Putting it all together

To sum up, here‘s a high-level checklist for ensuring your app collects high-quality, valid email addresses:

  1. Implement client-side format validation using regex
  2. Verify domain has valid MX record using DNS lookup
  3. Attempt SMTP callback to check if individual address exists
  4. For extra assurance, use a third-party verification API
  5. Enforce double opt-in to confirm user consent and engagement
  6. Regularly clean your list of bounces, complaints, and inactive addresses
  7. Follow email authentication and legal compliance best practices

By following these steps and monitoring the right metrics, you can build an email program that consistently reaches the right inboxes and drives real results for your business. It takes some extra effort upfront, but the long-term benefits are well worth it.

As a full-stack developer, you have the power and responsibility to set your application and your users up for email success. Don‘t let a few mistyped addresses stand in the way.

Similar Posts