Skip to content

email field can contain a double dot, producing an invalid address #243

Open

Description

@femarcano

Describe the bug

The email field can contain a double dot (..), which makes it an invalid address. For example:

{
  "name": { "title": "Mr", "first": "Hans-J.", "last": "Schaub" },
  "email": "hans-j..schaub@example.com"
}

hans-j..schaub@example.com is not a valid email address — the local part contains an empty label between two dots. Any consumer that validates the field with a standard email format (e.g. zod.email(), validator.js, Django's EmailValidator) will reject the entire response payload, not just the one record. That makes a single affected user enough to break a client that fetches a batch.

Root cause

The email is assembled in api/1.4/api.js:177:

this.include('email', tr.transliterate(`${name[0]}.${name[1]}`).replace(/ /g, '').toLowerCase() + '@example.com');

The first and last name are joined with a ., and the name is otherwise only stripped of spaces and transliterated. Nothing removes a dot that is already part of the name, so a name that itself ends in a . produces two consecutive dots.

There are exactly four such entries in the shipped name lists, all German male first names in api/1.4/data/DE/lists/male_first.txt:

line name generated email
370 Hans D. hansd..schmidt@example.com
392 Hans-H. hans-h..schmidt@example.com
399 Hans-J. hans-j..schaub@example.com
613 Klaus-D. klaus-d..schmidt@example.com

How to reproduce

Reproduce the generator locally against the affected name:

const transliterate = (s) => s.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
const build = (first, last) =>
  transliterate(`${first}.${last}`).replace(/ /g, '').toLowerCase() + '@example.com';

build('Hans-J.', 'Schaub'); // -> 'hans-j..schaub@example.com'

Or hit the live API repeatedly until one of the affected German male names is drawn:

for i in $(seq 1 200); do
  curl -s "https://randomuser.me/api/?results=100" \
    | jq -r '.results[] | select(.email | test("\\.\\.")) | "\(.name.first) | \(.email)"'
  sleep 0.5
done

Frequency

Roughly 1 in 3000 users returned by the API has a malformed email:

  • 4 affected names out of 1025 entries in DE/lists/male_first.txt → 1 in 256 German male users
  • German users are ~1/21 of a mixed-nationality payload, and ~1/2 of those are male
  • So a payload of 100 users contains a malformed email roughly 1% of the time

Observed over 3000 live users: 1 occurrence (hans-j..schaub@example.com, from Hans-J. Schaub, nat DE).

Suggested fix

Collapse consecutive dots in the local part after the name is joined, so the separator is not duplicated:

const local = transliterate(`${name[0]}.${name[1]}`)
  .replace(/ /g, '')
  .replace(/\.{2,}/g, '.')   // collapse duplicate separators
  .toLowerCase();
this.include('email', local + '@example.com');

Alternatively, strip trailing dots from the name before joining. Fixing the four data entries alone would also resolve the current occurrences, but the generator would still emit a malformed address for any future name containing a dot, so guarding in the generator is the more durable fix.

Impact

Clients that validate the response against a schema are affected disproportionately, because validation is all-or-nothing per payload: one malformed address in a batch of 100 rejects all 100 users. Clients that read the field as a plain string are unaffected.

I hit this while consuming the API behind a Zod schema — the strict zod.email() check rejected the whole payload, so the UI rendered an empty list instead of the 100 users that were actually returned.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions