NAME

libeav - Email Address Validation Library

SYNOPSIS

#include <eav.h>

void eav_init(eav_t *eav);
void eav_free(eav_t *eav);
int eav_setup(eav_t *eav);
int eav_is_email(eav_t *eav, const char *email, size_t length);
const char * eav_errstr(eav_t *eav);

Link with -leav { -lidn2 | -lidn | -lidnkit }.

When linking with idnkit compile with -DHAVE_IDNKIT.

DESCRIPTION

libeav is a small library which allows applications to validate email addresses. An email address consists two parts separated by "@" symbol: local-part "@" domain. The local-part usually identifies a user and the domain is usually represents a Fully Qualified Domain Name (FQDN).

The details of the API are described below. Also, the information may be found in the header file.

HIGH-LEVEL API

First of all, you have to create the eav_t structure. This structure may be created on the stack or via malloc(3). Then, you have to call the eav_init() function to initialize this structure.

After that you may use default settings or change them on your decision. To confirm your choice you have to call the eav_setup() function.

You may change the settings in the eav_t structure at any moment and later call again the eav_setup() function. For details about possible options please look at the section "HIGH-LEVEL API OPTIONS" below.

To check an email address call the eav_is_email() function. If this function returns false, that is, the specified email address is invalid you may get an error message string by calling the eav_errstr() function.

When you have finished working with libeav you have to call the eav_free() function.

The details about each of the mentioned functions above are described in the section "HIGH-LEVEL API FUNCTIONS" below.

See examples below in the section "HIGH-LEVEL API EXAMPLES".

HIGH-LEVEL API OPTIONS

libeav is able to work in different modes, which represents the implementation of the specific RFC. By default the high-level API is using the mode, which conforms to RFC 6531.

The list of fields in the eav_t structure you are able to change is described below:

  • rfc - represents a mode to be used to. The possible values are: EAV_RFC_822, EAV_RFC_5321, EAV_RFC_5322 and EAV_RFC_6531.

    Default value is: EAV_RFC_6531.

  • tld_check - enable/disable the TLD check. Also this options enables or disables the FQDN check, because without it such a check became useless. The possible values are: true (enabled) and false (disabled).

    Default value is: true.

  • allow_tld - the list of TLD types, which will be considered good or acceptable. That is, the eav_is_email() function will return true if a TLD type is listed in allow_tld, otherwise it will return false.

    Note that this option will work only if the tld_check option is enabled.

    libeav uses Top Level Domains (TLD for short) and their types, which can be found at https://www.iana.org/domains/root/db. The list of possible values and their descriptions are present below:

    • EAV_TLD_COUNTRY_CODE - country-code TLDs.

    • EAV_TLD_GENERIC - generic TLDs.

    • EAV_TLD_GENERIC_RESTRICTED - generic-restricted TLDs.

    • EAV_TLD_INFRASTRUCTURE - infrastructure TLDs.

    • EAV_TLD_NOT_ASSIGNED - not assigned TLDs. At IANA website they are listed as "Not assigned" in the "Sponsoring Organisation" field.

    • EAV_TLD_SPONSORED - sponsored TLDs.

    • EAV_TLD_TEST - test TLDs.

    • EAV_TLD_SPECIAL - special & restricted TLDs (RFC 2606, RFC 6761 and RFC 7686).

    This list must constructed by using the bitwise "OR" operator.

    Default value is: EAV_TLD_COUNTRY_CODE | EAV_TLD_GENERIC | EAV_TLD_GENERIC_RESTRICTED | EAV_TLD_INFRASTRUCTURE | EAV_TLD_SPONSORED | EAV_TLD_SPECIAL.

HIGH-LEVEL API FUNCTIONS

This section describes the high-level API functions:

void eav_init(eav_t *eav);

Initialize the eav structure and set default values into its fields.

void eav_free(eav_t *eav);

Destroy neccessary internal libeav structures. Note that eav_free() does not free passed to it the eav structure itself. If this structure was allocated by malloc(3) you have to free it yourself after calling this function.

int eav_setup(eav_t *eav);

Calling this function confirms options chosen by you. Returns 0 on success. Otherwise, returns EEAV_INVALID_RFC if an invalid rfc value was set. You have always call this function before checking email addresses.

int eav_is_email(eav_t *eav, const char *email, size_t length);

Validates the email address passed as email. The length is the length of the email string. Returns 1 on success, that is, the email is a valid email address. Otherwise, the function returns 0.

const char * eav_errstr(eav_t *eav);

Returns an error message string for the last checked email address via the eav_is_email() function.

HIGH-LEVEL API EXAMPLES

This is a basic usage of libeav:

#include <stdio.h>
#include <string.h>
#include <eav.h>

int
main(void)
{
    eav_t eav;
    const char *emails[] = {
        "valid@example.org",
        "invalid@123",
        NULL
    };
    const char *cp;

    /* initialize eav structure */
    eav_init(&eav);

    /* confirm default settings */
    eav_setup(&eav);

    for (cp = emails; *cp != NULL; cp++) {
        if (eav_is_email(&eav, *cp, strlen(*cp)))
            printf("%s is valid\n", *cp);
        else
            printf("error: %s: %s\n", *cp, eav_errstr(&eav));
    }

    /* free libeav resources */
    eav_free(&eav);

    return 0;
}

A more complex example:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <eav.h>

int
main(void)
{
    eav_t *eav = NULL;
    const char *emails[] = {
        "valid@example.org",
        "invalid@123",
        NULL
    };
    const char *cp;

    /* allocate eav_t structure */
    eav = malloc(sizeof(*eav));

    if (eav == NULL) {
        fprintf(stderr, "malloc: out of memory\n");
        return 1;
    }

    /* initialize eav structure */
    eav_init(eav);

    /* use RFC 822 mode */
    eav->rfc = EAV_RFC_822;

    /* forbid special & restricted TLDs */
    eav->allow_tld &= ~EAV_TLD_SPECIAL;

    /* confirm our settings */
    eav_setup(eav);

    for (cp = emails; *cp != NULL; cp++) {
        if (eav_is_email(eav, *cp, strlen(*cp)))
            printf("PASS: %s\n", *cp);
        else
            printf("FAIL: %s: %s\n", *cp, eav_errstr(eav));
    }

    /* free libeav resources */
    eav_free(eav);

    /* Note that eav_free does not free eav structure, because it
     * might be allocated on the stack. Free it by themselves.
     */
    free(eav);

    return 0;
}

FILES

eav.h libeav include file

libeav.so libeav shared library file

libeav.a libeav static library file

LEGAL NOTICE

libeav is released under BSD 2-clause "Simplified" License. For details please read LICENSE files in the distribution.

REPORTING BUGS

Report bugs using https://github.com/gh0stwizard/libeav/issues.

AUTHORS

libeav was originally designed and implemented by Vitaliy V. Tokarev <vitaliy.tokarev@gmail.com>.

Parts of libeav contains the code written by Wietse Venema and JSON.org.

AVAILABILITY

You can obtain the latest version from https://github.com/gh0stwizard/libeav/.