Home » How to customize the API to check emails for forms and webservices

How to customize the API to check emails for forms and webservices

You can customize and install the SafetyMails email verification API, with code in the programming language of your choice and with access keys, which will be used for real-time verification of emails in various services, whether landing pages, point-of-sale forms, applications, etc. By definition, SafetyMails will respond to query calls by returning the requested information.

Registering a source:

Remember that for this API to work you need to have a credit subscription activated (see how to subscribe).

To start the process just follow these steps:

  • On the next screen, give the source you are creating a name;
  • Enter the domain of your form (for example, if your form is at “https://safetymails.com/form“, you should just enter “safetymails.com“);
  • After entering the information the API Key and Source Ticket keys will be displayed for use in your script or Webservice.

Example of Ticket Source and API Key

APIKey
55a89975b74************75217b0a2eae840bd

Ticket Source

b440e8d30f068************3d08b84afe2fe50

HMAC Check

A hash-based HMAC (Message Authentication Code) should be used to determine whether a message sent over an insecure channel has been tampered with, as long as the sender and receiver share a secret key.

To generate the hash, you need to use a function that encrypts the value in the HMAC-SHA256 standard, where you enter the value in text and a key for access.

To generate the hash, you need to use a function that encrypts the value in the HMAC-SHA256 standard, where you enter the value in text and The formula for the hash below:

hash = HMAC_SHA256(VALUE, KEY);

VALUE = EMAIL
KEY = API_KEY

This hash must be sent in the request header:

Sf-Hmac: (Hash Content)

Example:

Sf-Hmac: afc5382171c3745890b56********************4aa43506326b4e1fc993cb

Query Syntax

The code used to perform the verification queries should follow the following syntax:

CODE_TICKET = SHA1 (<SOURCE_TICKET>)

https://<SOURCE_TICKET>.safetymails.com/api/<CODE_TICKET>

The email should be sent in POST with the name “email”

If you have any syntax questions, please refer to the language examples below.

Examples of use:

JavaScript example

<html>
    <body>
    <form action="">
        <input type="email" name="email" value="">
        <br>
        <button type="button">OK</button>
    </form>

    <script>
        // This function is just an example, if you prefer you can use your own javascript library
        async function sha1(text) {
            const encoder = new TextEncoder();
            const data = encoder.encode(text);
            const hashBuffer = await crypto.subtle.digest("SHA-1", data);
            return [...new Uint8Array(hashBuffer)]
                .map(byte => byte.toString(16).padStart(2, "0"))
                .join("");
        }

        // This function is just an example, if you prefer you can use your own javascript library
        async function hmacSHA256(value, key) {
            const encoder = new TextEncoder();
            const keyData = encoder.encode(key);
            const valueData = encoder.encode(value);

            const cryptoKey = await crypto.subtle.importKey(
                "raw", keyData, { name: "HMAC", hash: { name: "SHA-256" } }, false, ["sign"]
            );
            const signature = await crypto.subtle.sign("HMAC", cryptoKey, valueData);
            return [...new Uint8Array(signature)]
                .map(byte => byte.toString(16).padStart(2, "0"))
                .join("");
        }

        document.querySelector("button").addEventListener("click", async function () {
            const emailInput = document.querySelector('[type="email"]');
            if (!emailInput || emailInput.value.length < 1)
                throw new Error("Invalid Email Input value");

            // Enter the ticket_source and api_key values generated on the SafetyMails platform below.
            const ticket = '<TK SOURCE ENTERED IN THE SAFETYMAILS PANEL>';
            const api_key = '<APIKEY INFORMED IN THE SAFETYMAILS PANEL>';
            const code = await sha1(ticket);

            const email = emailInput.value;
            const url = `https://${ticket}.safetymails.com/api/${code}`;
            const hmac = await hmacSHA256(email, api_key);

            let form = new FormData();
            form.append('email',email);

            try {
                const response = await fetch(url, {
                    method: "POST",
                    headers: {
                        "Sf-Hmac": hmac
                    },
                    body: form
                });

                if (!response.ok) {
                    console.error(`HTTPCode ${response.status}`);
                    return;
                }

                const data = await response.json();

                if (!data.Success) {
                    console.error("Response error", data);
                    return;
                }

                console.log("Response success", data);
            } catch (error) {
                console.error("Request failed", error);
            }
        });
    </script>
    </body>
</html>

PHP example

<?php 
function SafetyApi($email) {
	$apiKey = '<APIKEY INFORMED IN THE SAFETYMAILS PANEL>';
	$tkSource = '<TK SOURCE ENTERED IN THE SAFETYMAILS PANEL>';
	$timeout = 10;	// Safetymails connection timeout
	$url = "https://{$tkSource}.safetymails.com/api/".sha1($tkSource);
	$header[] = "Sf-Hmac: " . hash_hmac('sha256', $email, $apiKey);
	$post['email'] = $email;

	$process = curl_init($url);
	curl_setopt($process, CURLOPT_HEADER, 0);
	curl_setopt($process, CURLOPT_FRESH_CONNECT, 1);
	curl_setopt($process, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($process, CURLOPT_FORBID_REUSE, 1);
	curl_setopt($process, CURLOPT_TIMEOUT, $timeout);
	curl_setopt($process, CURLOPT_ENCODING, '');
	curl_setopt($process, CURLOPT_POST, 1);
	curl_setopt($process, CURLOPT_HTTPHEADER, $header);
	curl_setopt($process, CURLOPT_POSTFIELDS, http_build_query($post));

	$ret = curl_exec($process);
	curl_close($process);

	$httpCode = curl_getinfo($process, CURLINFO_HTTP_CODE);

	$result = NULL;

	if ($ret === false && curl_errno($process) === CURLE_OPERATION_TIMEOUTED)
		$httpCode = 408;  // Timeout
	elseif ($httpCode == 200) 
		$result = json_decode($ret, true);

	# HTTPCODE 400 - Invalid parameters
	# HTTPCODE 401 - Invalid API Key
	# HTTPCODE 402 - Insufficient credits for the query
	# HTTPCODE 403 - Access from a source other than the one registered
	# HTTPCODE 406 - Invalid or inactive source ticket
	# HTTPCODE 408 - Timeout
	# HTTPCODE 429 - Query limit per hour or minute exceeded

	return ['Status'=>$httpCode, 'Result'=>$result];
}

$emailTest = "[email protected]";
print_r(SafetyApi($emailTest));

Python example


import requests
import hashlib
import hmac
def safety_api(email):
    api_key = '<APIKEY INFORMED IN THE SAFETYMAILS PANEL>'
    tk_source = '<TK SOURCE ENTERED IN THE SAFETYMAILS PANEL>'
    timeout = 10  # Safetymails connection timeout
    
    url = f"https://{tk_source}.safetymails.com/api/{hashlib.sha1(tk_source.encode()).hexdigest()}"
    
    sf_hmac = hmac.new(api_key.encode(), email.encode(), hashlib.sha256).hexdigest()
    headers = {"Sf-Hmac": sf_hmac}
    data = {"email": email}
    
    try:
        response = requests.post(url, headers=headers, data=data, timeout=timeout)
        http_code = response.status_code
        result = response.json() if http_code == 200 else None
    except requests.exceptions.RequestException as e:
        return {"Status": "400", "Result": str(e)}
    
    return {"Status": http_code, "Result": result}
# Exemplo de uso
if __name__ == "__main__":
    email_test = "[email protected]"
    resposta = safety_api(email_test)
    print(resposta)

Java example


import java.net.HttpURLConnection;
import java.net.URL;
import java.io.OutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class SafetyApi {
    public static String generateSha1(String input) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8));
        StringBuilder hexString = new StringBuilder();
        for (byte b : hash) {
            hexString.append(String.format("%02x", b));
        }
        return hexString.toString();
    }

    public static String generateHmacSha256(String key, String data) throws Exception {
        Mac hmac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
        hmac.init(secretKey);
        byte[] hash = hmac.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(hash);
    }

    public static String safetyApi(String email) {
        String apiKey = "<APIKEY INFORMED IN THE SAFETYMAILS PANEL>";
        String tkSource = "<TK SOURCE ENTERED IN THE SAFETYMAILS PANEL>";
        int timeout = 10000; // Timeout em milissegundos
        
        try {
            String sha1TkSource = generateSha1(tkSource);
            String urlStr = "https://" + tkSource + ".safetymails.com/api/" + sha1TkSource;
            String sfHmac = generateHmacSha256(apiKey, email);
            
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Sf-Hmac", sfHmac);
            conn.setDoOutput(true);
            conn.setConnectTimeout(timeout);
            conn.setReadTimeout(timeout);
            
            String postData = "email=" + email;
            try (OutputStream os = conn.getOutputStream()) {
                os.write(postData.getBytes(StandardCharsets.UTF_8));
            }
            
            int responseCode = conn.getResponseCode();
            StringBuilder response = new StringBuilder();
            
            try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
                String line;
                while ((line = br.readLine()) != null) {
                    response.append(line);
                }
            }
            
            return "{ \"Status\": " + responseCode + ", \"Result\": " + response.toString() + " }";
        } catch (Exception e) {
            return "{ \"Status\": \"Erro\", \"Result\": \"" + e.getMessage() + "\" }";
        }
    }
    
    public static void main(String[] args) {
        String emailTest = "[email protected]";
        System.out.println(safetyApi(emailTest));
    }
}

Go example


package main

import (
	"crypto/hmac"
	"crypto/sha1"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"
)

const (
	apiKey   = "<APIKEY INFORMED IN THE SAFETYMAILS PANEL>"
	tkSource = "<TK SOURCE ENTERED IN THE SAFETYMAILS PANEL>"
	timeout  = 10 * time.Second // Connection timeout
)

// Function to generate SHA1
func generateSHA1(input string) string {
	h := sha1.New()
	h.Write([]byte(input))
	return hex.EncodeToString(h.Sum(nil))
}

// Function to generate HMAC-SHA256
func generateHMACSHA256(key, data string) string {
	h := hmac.New(sha256.New, []byte(key))
	h.Write([]byte(data))
	return hex.EncodeToString(h.Sum(nil))
}

// Function that makes the request to the API
func safetyAPI(email string) (map[string]interface{}, error) {
	urlStr := fmt.Sprintf("https://%s.safetymails.com/api/%s", tkSource, generateSHA1(tkSource))
	hmacSignature := generateHMACSHA256(apiKey, email)

	// Creating data in form-data format
	formData := url.Values{}
	formData.Set("email", email)
	formEncoded := formData.Encode() // "[email protected]"

	// Creating the POST request
	client := http.Client{Timeout: timeout}
	req, err := http.NewRequest("POST", urlStr, strings.NewReader(formEncoded))
	if err != nil {
		return nil, err
	}

	// Defining headers
	req.Header.Set("Sf-Hmac", hmacSignature)
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded") // Send in form-data

	// Sending the request
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// Read reply
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	// Creating the return
	result := map[string]interface{}{
		"Status": resp.StatusCode,
		"Result": string(body), // Returns the API JSON as a string
	}

	return result, nil
}

func main() {
	email := "[email protected]"
	resposta, err := safetyAPI(email)
	if err != nil {
		fmt.Println("Erro:", err)
	} else {
		fmt.Println(resposta)
	}
}

Return message examples

The return of the queries is in JSON format, according to the table below:

Success:Return of type bool (true or false), which tells you whether the call was successful.
DomainStatus:Domain status of the queried e-mail.
Status:Result of email validation, if successful.
Email:Verified email address
Limited:It tells you whether the e-mail queried is from a limited ISP, i.e. one that receives a limited number of requests.
Public:Informs whether the email queried is from the ‘Corporate’ domain (private domains and/or domains that have private rules for receiving) or ‘Email provider’ (domains that have public rules for receiving).
Advice:SafetyMails’ suggested classification for the status of the queried e-mail (Valid, Invalid, Risky or Unknown).
Balance:Number of credits available in your account.
Msg:Returns the error message regarding the failed call (only when the call presents an error).

Return in case of successful query

{
    "Success":true,
    "Email":"[email protected]",
    "Referer":"www.safetymails.com",
    "DomainStatus":"VALID",
    "Status":"VALID",
    "Advice":"Valid",
    "Public":null,
    "Limited":null,
    "Balance":4112343
}

Return in case of query error

{
    "Success":false,
    "Email":"[email protected]",
    "Referer":"www.safetymails.com",
    "Status":"PENDING",
    "Advice":"Unknown",
    "Msg":"Invalid referrer"
}

Error messages

Look out for the following error messages:

HTTPCodeErrorDescription
400Invalid parametersIncorrect or non-existent access keys.
401Invalid API KeyIncorrect or non-existent access keys.
406Invalid or inactive Source TicketYou are trying to perform queries for an inactive API source. Go to your dashboard and activate the source properly.
403Source different from the registered source(%s)<>(%s):You are trying to perform queries for a different API source than the one registered in your account. Check the source and try again.
429Query limit per hour or minute or daily exceeded – Contact SupportTo protect your form from misuse, your API only allows a total of 20 queries per day from the same IP (default). To make more queries than this, please contact support ([email protected])
402No credits to perform the researchYour account has no credits to perform the query. É preciso adquirir créditos.

If you need further advice, please contact our support team ([email protected])

More Reading

Post navigation