oneapi
Sign in
Utile v1 / Email

Check an email address

Signals about an email address: whether the form is correct, whether the domain has MX records, whether it is a disposable provider, whether it is a plus alias. It sends no verification message.

POST
https://oneapi.ro/api/utile/v1/email/valideaza

Request body

Sent as JSON in the request body (Content-Type: application/json) — not in the query string.

NameTypeDescriptionAccepted values
adresarequired string REQUIRED. The address to check, at most 320 characters. max 320 car.
mxoptional boolean | null 0 skips the DNS lookup and checks syntax only. Checked by default.
An ordinary address Request body
{
    "adresa": "ion.popescu@example.com"
}
Disposable domain Request body
{
    "adresa": "test@mailinator.com"
}
Syntax only, no DNS Request body
{
    "adresa": "ion@exemplu.ro",
    "mx": false
}

Query parameters

This route accepts no query parameters.

How it behaves

  • POST, with the address in the body (JSON): adresa (required, at most 320 characters) and mx (false skips the DNS lookup and checks syntax only; checked by default). An e-mail address is personal data: in a URL it would end up in access logs and in the referrer — so a GET gets 405 metoda_nepotrivita.
  • This is not a verdict. The only check that proves an address exists is sending a message with a confirmation link. Everything this route returns are SIGNALS — an address can pass every check and not exist, while one rejected by the list can be perfectly functional.
  • The address is deliberately NOT validated at the gate with the usual email rule: that is precisely what the route is meant to report. Rejected on entry, a malformed address would never reach the analysis.
  • Missing MX records do not automatically mean the domain cannot receive mail. RFC 5321 says a domain with no MX but with A or AAAA is a valid recipient — hence stare distinguishes fara_mx_dar_cu_a from fara_mx_si_fara_a.
  • Internationalised domains are converted to Punycode before any check, because both the syntax filter and DNS work on the ASCII form. The domeniu in the response is the converted form.
  • The DNS lookup is rate-limited on two levels (per user and global) and cached for 10 minutes per DOMAIN. When the rate is exceeded or the DNS server does not answer, mx.verificat is false with the reason and poate_primi_mail is null — a DNS outage is never turned into “the domain cannot receive mail” and is not cached. The lookup has a 2-second timeout and a single attempt, and after 5 failures in a row the MX check pauses for 2 minutes (the reason says so) — a request no longer hangs 10 seconds on a dead DNS.
  • Zero retention: the address is never written anywhere, not to logs, not to the database. The only thing cached is the DNS answer for the domain, which says nothing about the person in front of the @.

What it is for

  • Catch typos at sign-up, before the confirmation mail is lost.
  • Filter disposable addresses out of a newsletter sign-up form.
  • Separate role accounts (office@) from personal addresses in a contact database.

Response structure

All fields below live inside data.

FieldTypeDescription
adresa string The address, in the form published by the source.
normalizata string The address with the local part lower-cased and the domain in ASCII form.
local string The part before the @.
domeniu string The domain, in ASCII form (Punycode if it was internationalised).
eticheta null The +tag suffix, which some providers ignore on delivery. Useful for de-duplication.
semnale.sintaxa_valida boolean Whether the address passes RFC 5322 and the length limits.
semnale.domeniu_temporar boolean Whether the domain is on the disposable list.
semnale.cutie_de_rol boolean Whether it is a role account (office@, info@) rather than a person's.
semnale.poate_primi_mail boolean Whether the domain has MX or A records. null if the check was not performed.
probleme array What exactly is wrong with the syntax, in words.
mx.verificat boolean Whether the DNS lookup actually got an answer. On false, mx.motiv says why (rate exceeded or a DNS server that did not answer).
mx.stare string are_mx, fara_mx_dar_cu_a or fara_mx_si_fara_a; absent when verificat: false.
mx.poate_primi boolean
mx.servere[] array The mail servers, ordered by priority.
mx.servere[].server string
mx.servere[].prioritate integer
scor integer A 0–100 figure composed from the signals above, for callers who want a single number. It is derived, not measured.
observatie string A note on how to read the response: a computation convention or a limit of the data.
sursa.domenii_temporare string
sursa.mx string
sursa.sintaxa string
mx.motiv Why there was no check; present only when verificat: false.

Response examples

corp: {"adresa": "ion.popescu@example.com"}

POSThttps://oneapi.ro/api/utile/v1/email/valideaza
{
    "data": {
        "adresa": "ion.popescu@example.com",
        "normalizata": "ion.popescu@example.com",
        "local": "ion.popescu",
        "domeniu": "example.com",
        "eticheta": null,
        "semnale": {
            "sintaxa_valida": true,
            "domeniu_temporar": false,
            "cutie_de_rol": false,
            "poate_primi_mail": true
        },
        "probleme": [],
        "mx": {
            "verificat": true,
            "stare": "are_mx",
            "poate_primi": true,
            "servere": [
                {
                    "server": "",
                    "prioritate": 0
                }
            ]
        },
        "scor": 90,
        "observatie": "Semnalele NU sunt un verdict. O adresă poate trece toate verificările și să nu existe; una respinsă de listă poate fi perfect funcțională. Singura dovadă că o adresă e reală e un mesaj de confirmare livrat.",
        "sursa": {
            "domenii_temporare": "disposable-email-domains — CC0 1.0",
            "mx": "interogare DNS live, cu cache de o oră pe domeniu",
            "sintaxa": "RFC 5322 (prin filtrul PHP) plus limitele de lungime din RFC 5321"
        }
    }
}

Error codes

CodeSlugWhen it occurs
401neautentificatToken missing, invalid, expired or revoked.
403feature_indisponibilThe current plan does not include the feature the route depends on.
405eroaremetoda_nepotrivita: the route only accepts POST, with the address in the body.
422validareadresa is missing or longer than 320 characters.
429cota_depasitaThe plan's monthly quota has been exceeded (see Retry-After).

All errors share the same shape. eroare.cod is stable and is the value you should branch on in code — not the text in mesaj, which may change.

{
    "eroare": {
        "cod": "validare",
        "mesaj": "adresa is missing or longer than 320 characters."
    }
}