Metadata-Version: 2.4
Name: emailguesser
Version: 0.3.0
Summary: Generate plausible email address permutations from name, username, DOB, location and domain hints, as JSON, CSV or text.
Author-email: OSINTverse <hi@osintverse.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/OSINTVerseHQ/EmailGuesser
Project-URL: Repository, https://github.com/OSINTVerseHQ/EmailGuesser
Project-URL: Issues, https://github.com/OSINTVerseHQ/EmailGuesser/issues
Keywords: email,email-generator,email-permutator,email-guesser,email-finder,osint,reconnaissance,username,json,cli
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Provides-Extra: translit
Requires-Dist: unidecode>=1.3; extra == "translit"
Provides-Extra: verify
Requires-Dist: dnspython>=2.4; extra == "verify"
Dynamic: license-file

<div align="center">

# EmailGuesser

### Email permutation generator and email address guesser for OSINT

Turn a name, username, birth year, DOB, location and domain into a **ranked list of the email addresses a person most likely uses**, as JSON, CSV or plain text. Offline, zero dependencies, pure Python.

[![CI](https://github.com/OSINTVerseHQ/EmailGuesser/actions/workflows/ci.yml/badge.svg)](https://github.com/OSINTVerseHQ/EmailGuesser/actions/workflows/ci.yml)
[![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
![Dependencies: none](https://img.shields.io/badge/dependencies-none-brightgreen)
![Offline](https://img.shields.io/badge/network-offline-lightgrey)
![Output: JSON/CSV/TXT](https://img.shields.io/badge/output-JSON%20%2F%20CSV%20%2F%20TXT-orange)

[Quick start](#quick-start) · [Inputs](#input-fields) · [CLI](#command-line-reference) · [Python API](#python-api) · [Output](#output-formats) · [FAQ](#faq) · [License](#license-and-attribution)

</div>

---

## See it in action

```bash
emailguesser --first John --last Doe --year 1990 --domain gmail.com --limit 6 --category name
```

| Rank | Email | Pattern | Score |
| --- | --- | --- | --- |
| 1 | `john.doe@gmail.com` | `{first}.{last}` | 0.95 |
| 2 | `jdoe@gmail.com` | `{first_initial}{last}` | 0.90 |
| 3 | `johndoe@gmail.com` | `{first}{last}` | 0.85 |
| 4 | `j.doe@gmail.com` | `{first_initial}.{last}` | 0.80 |
| 5 | `doe.john@gmail.com` | `{last}.{first}` | 0.60 |
| 6 | `doej@gmail.com` | `{last}{first_initial}` | 0.60 |

The tool prints the same data as JSON by default, and as JSONL, CSV or a plain list of addresses on request (see [output formats](#output-formats)).

## Why EmailGuesser

People pick email addresses from a small set of habits: `first.last`, `flast`, `firstlast`, a nickname plus a birth year. EmailGuesser encodes those habits as a pattern table, applies them to the details you supply, and ranks the results so the most probable addresses come first.

- **One tool, many formats.** Use it from the terminal, from a script, or as a Python library; emit JSON, JSONL, CSV or a plain address list.
- **Private by design.** No accounts, no API keys, no network calls. Everything runs on your machine.
- **Tuned for real behaviour.** Company domains favour `first.last`; free-mail domains favour names with years, dates and usernames. A known address teaches the tool a company's format.
- **Easy to extend.** Patterns, scores, nicknames and default domains live in small, readable files.

## Features

- **Hundreds of email format permutations** from name, username, year, DOB, location and domain.
- Covers **every login pattern from [NAMINT](https://github.com/seintpl/NAMINT)**, with and without number suffixes (checked by a test).
- **Names handled properly**: middle names and initials, multi-word and hyphenated names, apostrophes, accents (`José Müller` becomes `jose.muller`).
- **Nickname aware**: `Robert` also tries `bob`, `rob`, `bobby`; add your own with `--alias`.
- **Date-of-birth aware**: suffixes such as `1990`, `90`, `1405`, `140590`, `14051990`.
- **Username aware**: repeatable `--username`, with separator variants (`j_doe`, `j.doe`, `jdoe`).
- **Location aware**: your city and country become tokens; the country code also pulls in regional providers (`yahoo.co.in`, `web.de`, `mail.ru`).
- **Learns a company format**: pass a known address with `--known-email` and matching candidates are ranked to the top.
- **Custom or default domains**: your company domain, or Gmail, Outlook, Yahoo and more.
- **Ranked output**: every address has a 0 to 1 `score`, a `pattern` id and a `category`.
- **Batch mode**: run a whole JSON, JSONL or CSV file of people in one call.
- **Validated and de-duplicated** local parts, with optional Gmail dot/plus folding and a per-domain cap.
- **Cross-platform**: Windows, macOS and Linux, Python 3.9+.

## Common use cases

- **OSINT and investigations**: build candidate addresses to check with breach-lookup, account-discovery or search tools you are authorised to use.
- **Sales and recruiting outreach**: guess a work email from a name and company domain, or learn the format from one known colleague.
- **Penetration testing and red teaming**: build target lists for authorised phishing simulations and social-engineering assessments.
- **Self-audit and account recovery**: work out which address you might have signed up with.

> EmailGuesser only **generates guesses**. It does not check that an address exists. See the [FAQ](#faq).

## How it works

```mermaid
flowchart LR
    A[Your inputs<br/>name, username, year,<br/>DOB, location, domain] --> B[Normalise<br/>accents, hyphens,<br/>nicknames]
    B --> C[Build tokens<br/>first, f, last, l,<br/>1990, 90, 1405 ...]
    C --> D[Apply pattern table<br/>skip patterns with<br/>missing tokens]
    D --> E[Validate and<br/>de-duplicate]
    E --> F[Score, sort<br/>and limit]
    F --> G[JSON / CSV / TXT]
```

## Installation

Requires Python 3.9 or newer.

```bash
pip install emailguesser
```

For non-Latin names (Cyrillic, Greek, Arabic, CJK), install the optional transliteration extra:

```bash
pip install "emailguesser[translit]"
```

Or clone and run without installing:

```bash
git clone https://github.com/OSINTVerseHQ/EmailGuesser.git
cd EmailGuesser
python -m emailguesser --help
```

After `pip install`, the `emailguesser` command is available in your terminal.

## Quick start

**1. Guess a work email from a name and company domain**

```bash
emailguesser --first John --last Doe --domain example.com --limit 5 --pretty
```

**2. Learn a company's format from one known address**

```bash
emailguesser --first Jane --last Smith --known-email "Bob Jones <bjones@acme.com>" --format txt
```

**3. Use everything you know**

```bash
emailguesser --first John --middle Michael --last Doe --username jdoe \
  --year 1990 --dob 1990-05-14 --location "Mumbai, India" \
  --domain example.com --domain gmail.com --pretty
```

**4. Get a plain list to pipe into another tool**

```bash
emailguesser --first John --last Doe --year 1990 --min-score 0.5 --limit 0 --format txt
```

**5. Read input from a JSON file, or run many people at once**

```bash
emailguesser --input request.json --pretty
emailguesser --batch people.csv --format csv -o candidates.csv
```

`people.csv` just needs headers matching the input fields, for example `first,last,domain`.

**6. Generate here, verify elsewhere**

EmailGuesser never touches the network, so pair it with a verification step you
are authorised to run. The plain list format pipes cleanly into other tools:

```bash
emailguesser --first John --last Doe --domain acme.com --format txt --limit 0 > candidates.txt
# then check candidates.txt with a breach-lookup, account-discovery or
# email-verification tool, for example the OSINTverse API (https://osintverse.com).
```

## Input fields

| Field | CLI flag | Required | Notes |
| --- | --- | --- | --- |
| First name | `--first` | With last name, unless a username is given | Multi-word names work (`Mary Ann`) |
| Middle name | `--middle` | No | Enables middle-name and middle-initial patterns |
| Last name | `--last` | With first name, unless a username is given | Hyphenated and multi-word names work (`Van Der Berg`) |
| Username | `--username` | No | Repeatable. A pasted email address is reduced to its local part |
| Alias / nickname | `--alias` | No | Repeatable extra first-name form (`billg`, `jdoe`) |
| Known email | `--known-email` | No | `"Name <local@domain>"`, `Name:local@domain`, or just `local@domain`. Learns the domain's format |
| Year | `--year` | No | 4 digits (1900 to 2100) |
| Date of birth | `--dob`, `--dob-format dmy\|mdy\|ymd` | No | `1990-05-14` is read as ISO; other formats follow `--dob-format` (default `dmy`) |
| Location | `--location` | No | `"City, Country"` or `"City, CC"`. The country code also adds regional providers |
| Domain | `--domain` | No | Repeat or comma-separate. If omitted, popular free-mail providers are used |

You need at least a first and last name, or a username.

## Command-line reference

| Option | Description |
| --- | --- |
| `--format json\|jsonl\|txt\|csv` | Output format. Default `json` |
| `--limit N` | Maximum results. Default `50`. Use `0` for unlimited |
| `--max-per-domain N` | Cap results per domain (`0` = no cap) |
| `--min-score X` | Drop results scoring below `X` (0 to 1) |
| `--category C` | Only include one pattern category: `name`, `personal`, `username`, `location`. Repeatable |
| `--gmail-dots` | Treat Gmail dot and `+tag` variants as the same address when de-duplicating |
| `--input FILE` | Read input fields (and options) from a JSON file. `-` reads stdin. CLI flags override |
| `--batch FILE` | Run many inputs from a JSON array, JSONL or CSV file. `-` reads stdin |
| `--explain` | Add a per-address score breakdown (json/jsonl output) |
| `--pack FILE` | Custom pattern pack (JSON/TOML) adding patterns, nicknames and domains |
| `--calibration FILE` | Score→probability table (see below) adding a `probability` field |
| `--provider-aware` | (online) Detect each domain's mail provider by MX; fold dot-variants on Google-hosted domains |
| `--verify mx\|smtp` | (online) Check deliverability. Needs the `[verify]` extra. Authorised use only |
| `--drop-undeliverable` | With `--verify`, drop addresses that are clearly undeliverable |
| `-o, --output FILE` | Write output to a file instead of stdout |
| `--pretty` | Indent JSON output |
| `--version` | Print the version and exit |

Errors go to stderr as `{"error": "..."}` and the exit code is `2`.

### Learn a company format, verify, explain

```bash
# Learn acme.com's convention from one known colleague, then rank Jane's address
emailguesser --first Jane --last Smith --known-email "Bob Jones <bjones@acme.com>" --format txt

# (online) keep only addresses whose domain can receive mail
emailguesser --first Jane --last Smith --domain acme.com --verify mx --drop-undeliverable

# see exactly why each address scored what it did
emailguesser --first John --last Doe --domain acme.com --explain --pretty
```

Verification and provider detection are opt-in, make network requests, and need
the extra: `pip install "emailguesser[verify]"`. Use them only against domains
you are authorised to probe.

### Calibrated probabilities

A `score` ranks candidates; it is not itself the chance an address is real. Fit a
score→probability table from your own verified data and apply it:

```bash
python -m emailguesser.calibrate your_data.csv -o table.json   # needs a true_email column
emailguesser --first John --last Doe --calibration table.json  # adds a "probability"
```

### Custom pattern packs

Add patterns, nicknames and domains without editing source (see
[`examples/pack.example.json`](examples/pack.example.json)):

```bash
emailguesser --first John --last Doe --pack mypack.json
```

### Run it anywhere

```bash
pipx install emailguesser                 # isolated CLI
docker run --rm emailguesser --first John --last Doe --domain acme.com
python scripts/build_pyz.py && python dist/emailguesser.pyz --help   # single file, no install
```

A static, backend-free **browser version** lives in [`web/`](web/) (runs the
generator in-browser via Pyodide).

## Python API

```python
from emailguesser import generate

result = generate(
    first_name="John",
    middle_name="Michael",
    last_name="Doe",
    usernames=["jdoe"],
    aliases=["johnny"],
    year="1990",
    dob="1990-05-14",
    location="Mumbai, India",
    domains=["example.com", "gmail.com"],
    known_emails=["Bob Jones <bjones@example.com>"],
    limit=20,
    max_per_domain=0,
)

for item in result["emails"]:
    print(item["score"], item["email"])
```

`generate()` also accepts a dictionary or an `Inputs` object as its first argument, plus the CLI options as keyword arguments: `limit`, `min_score`, `max_per_domain`, `categories`, `gmail_dots`, `dob_format`. It returns a plain, JSON-serialisable `dict`. To render it, use `emailguesser.output.render(result, "csv")` or `render_batch([...], "jsonl")`.

## Output formats

- **json** (default): the full result object below.
- **jsonl**: one JSON email object per line, ready for `jq` and line-based tools.
- **txt**: one email address per line, highest score first.
- **csv**: `email,local_part,domain,pattern,category,score` with a header row.

In batch mode, `jsonl` and `csv` gain a leading `query` column identifying which input produced each row.

### JSON output shape

```json
{
  "input": {
    "first_name": "John", "middle_name": "", "last_name": "Doe",
    "usernames": [], "aliases": [], "year": "1990", "dob": "",
    "location": {}, "domains": ["gmail.com"], "known_emails": []
  },
  "meta": {
    "count": 6,
    "total_candidates": 251,
    "truncated": true,
    "limit": 6,
    "min_score": 0.0,
    "max_per_domain": 0,
    "domains_used": ["gmail.com"],
    "generated_at": "2026-10-18T09:00:00Z",
    "warnings": ["no middle name given: middle-name patterns skipped"]
  },
  "emails": [
    {"email": "john.doe@gmail.com", "local_part": "john.doe", "domain": "gmail.com",
     "pattern": "{first}.{last}", "category": "name", "score": 0.95}
  ]
}
```

| Field | Meaning |
| --- | --- |
| `emails[].pattern` | The pattern that produced the address, such as `{first}.{last}` |
| `emails[].category` | `name`, `personal`, `username` or `location` |
| `emails[].score` | Likelihood estimate from 0 to 1. Results are sorted high to low |
| `meta.total_candidates` | Addresses found before `--limit` was applied |
| `meta.warnings` | Skipped patterns and notes about your input |

## How scoring works

```
score = pattern popularity x domain-type multiplier x domain popularity   (capped at 1)
```

- **Pattern popularity**: `first.last` ranks above `lastf`, which ranks above `first-m-last`.
- **Domain type**: company domains favour plain name patterns; free-mail domains favour name plus number, date and username patterns.
- **Name variants**: alternative spellings of multi-word names and guessed nicknames are down-weighted.
- **Known format**: a candidate matching a `--known-email` format for that domain is boosted to the top.

All weights live in `emailguesser/patterns.py` and `emailguesser/domains.py`. After any change, run the calibration harness to see whether ranking of real addresses improved:

```bash
python tests/calibration.py
```

## FAQ

**Does EmailGuesser check whether an email address exists?**
No. It is offline and generation-only and never contacts a mail server.

**How is it different from NAMINT?**
NAMINT is a browser-based tool that builds name and login search patterns. EmailGuesser is a Python command-line tool and library focused on email addresses. It covers all NAMINT login patterns and adds nicknames, usernames, date-of-birth, location, known-format inference, scoring, de-duplication and JSON/CSV/TXT output.

**Which providers are used by default?**
Gmail, Outlook, Yahoo, Hotmail, iCloud, Proton, Live, AOL, MSN and GMX. A location country code adds regional providers. Passing `--domain` replaces this list.

**Why so many Gmail variants?**
Gmail ignores dots in the local part. Pass `--gmail-dots` to collapse `j.doe@gmail.com` and `jdoe@gmail.com` into one.

**Does it support non-English names?**
Accents are converted to ASCII out of the box. For non-Latin scripts, install `emailguesser[translit]`, which transliterates Cyrillic, Greek, Arabic and CJK.

**Can I add my own patterns, nicknames or domains?**
Yes. Edit `emailguesser/patterns.py`, `emailguesser/nicknames.py` or `DEFAULT_DOMAINS` in `emailguesser/domains.py`.

## Responsible use

EmailGuesser is meant for OSINT research, authorised security testing, outreach that follows the law, and personal use. Do not use it for harassment, stalking, spam or any unlawful activity. You are responsible for complying with privacy, anti-spam and data-protection laws (such as GDPR and CAN-SPAM) where you operate.

## Development and tests

```bash
git clone https://github.com/OSINTVerseHQ/EmailGuesser.git
cd EmailGuesser
pip install -e ".[dev]"
ruff check emailguesser tests
ruff format --check emailguesser tests
python -m pytest
```

```
emailguesser/
  normalize.py     name, username and domain cleaning (+ transliteration hook)
  nicknames.py     bundled nickname table
  tokens.py        date parsing and name/date tokens
  patterns.py      pattern table and scores
  domains.py       default/regional domains and location parsing
  known_format.py  parse a known-email reference
  fields.py        input-field aliases
  validate.py      local-part validation
  generator.py     core engine and public generate() API
  output.py        json / jsonl / txt / csv rendering
  cli.py           command-line interface
tests/             pytest suite + calibration harness
```

## Contributing

Issues and pull requests are welcome. Good first contributions: new patterns for naming conventions you have seen in the wild (use the "new pattern" issue template), nicknames, better scores backed by data, and extra tests. Please run `ruff check`, `ruff format --check` and `python -m pytest` before opening a pull request.

## License and attribution

EmailGuesser is released under the [MIT License](LICENSE). You are free to use, copy, modify and redistribute it, including commercially, as long as you **keep the copyright notice and license text** with your copy.

If you use EmailGuesser in a project, report or product, please credit it:

> Email candidates generated with [EmailGuesser](https://github.com/OSINTVerseHQ/EmailGuesser) by OSINTverse.

GitHub's **Cite this repository** button uses [`CITATION.cff`](CITATION.cff).

## Credits

Pattern ideas were inspired by [seintpl/NAMINT](https://github.com/seintpl/NAMINT) (MIT License).

---

<sub>**Keywords:** email permutator, email generator, email guesser, email finder, email format finder, email pattern generator, email combinations, email permutations, OSINT tool, username to email, name to email, find email by name, Python OSINT, reconnaissance, penetration testing, red team, JSON, CSV.</sub>
