The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

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 "TLD MANAGER" field.

    • EAV_TLD_SPONSORED - sponsored TLDs.

    • EAV_TLD_RETIRED - retired TLDs. At IANA website they are listed as "Retired" in the "TLD MANAGER" field.

    • 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.

Accessing result information

After calling the function eav_is_email() you may observe the eav->result value for requesting additional result information. The result field is the eav_result_t structure with the next fields:

    struct eav_result_t {
        bool is_ipv4;
        bool is_ipv6;
        bool is_domain;
        int rc;
        #ifdef HAVE_IDNKIT
            idn_result_t idn_rc;
        #else
            int idn_rc;
        #endif
        #ifdef EAV_EXTRA
            char *lpart;
            char *domain;
        #endif
    };

The description of the fields is shown below:

is_ipv4 - domain-part is a IPv4 address
is_ipv6 - domain-part is a IPv6 address
is_domain - domain-part is a domain
rc - result code, review eav.h for details
idn_rc - idn-library-specific result code

When compiled with -DEAV_EXTRA you may access for additional fields:

lpart - a string value of local-part
domain - a string value of domain-part

A common concept is when the eav_is_email() check is failed, when values of fields above either false or NULL if applicable.

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/.