---
name: "What an email reveals"
repo: https://github.com/useosint/skills
source: https://github.com/useosint/skills/blob/HEAD/skills/what-an-email-reveals/SKILL.md
license: "MIT"
install: "npx skills add useosint/skills --skill what-an-email-reveals"
page: https://100xlab.com/resources/agent-skills/useosint-skills--what-an-email-reveals--1rm8bz6
---

# What an email reveals

An email address is usually the highest-value selector in an investigation: it
carries a name, a domain, an account history, and a breach footprint. The
beginner error is trying to prove the address exists. Existence is the least
interesting thing about it, it is the hardest thing to establish passively, and
the techniques that establish it are the ones that expose you. Work the
structure and the footprint first; treat validation as a bonus.

Never send mail to the subject as a research technique.

## Step 1 — Authorized scope

Read [../../ETHICS.md](../../ETHICS.md). Write down subject, objective,
in-bounds selectors, out-of-bounds actions, and the governing jurisdiction.
Decide in advance whether *interactive* probing — SMTP conversations,
password-reset flows, signup-form enumeration — is authorized. It usually is
not. Everything below is passive unless marked otherwise.

**Done when** scope is written and the interactive-probing decision is recorded.

## Step 2 — Parse and validate

Three different things get called "email validation". They are not
interchangeable.

| Method | What it proves | Cost |
|---|---|---|
| Syntactic | The string could be an address | Free, passive, proves nothing about the mailbox |
| Domain / MX | The domain exists and accepts mail | Free, passive, `dig MX example.com` |
| SMTP `RCPT TO` probe | The server claims the mailbox exists | Interactive, often blocked or lied to, and logged |

Do the first two. The third — opening an SMTP session and issuing `RCPT TO` to
see whether the server accepts the recipient — is a live conversation with the
subject's mail infrastructure from your IP. It gets logged, it gets your address
range blocklisted, and against a **catch-all domain** it is worthless: a
catch-all accepts every recipient, so every address "exists". Greylisting,
tarpitting, and accept-then-bounce policies produce the same useless answer.
Third-party validation APIs mostly wrap the same probe; the exposure moves to
the vendor, the accuracy limits do not change.

Then parse the local part. `first.last`, `flast`, `firstl`, `f.last` each imply
a name and, on a corporate domain, a company-wide convention — see
[reference/corporate-formats.md](reference/corporate-formats.md).

**Gmail normalisation matters.** Gmail ignores dots in the local part and
everything after a `+`. `j.doe+news@gmail.com`, `jdoe@gmail.com` and
`jd.oe@gmail.com` are one mailbox. Consequences: addresses that look different
in two breaches may be the same person, and a `+tag` frequently names the
service the address was given to, which is free intelligence about where the
subject holds accounts. Not every provider behaves this way — check before
assuming.

**Done when** the address is graded valid / invalid / unknown, the normalised
form is recorded, and the name hypothesis is written down.

## Step 3 — Gravatar

Gravatar maps an address to a public avatar by MD5 hash of the lowercased,
trimmed address. Compute the hash and request the avatar; a returned image
means the address was registered with the service, and the associated public
profile can carry a display name, a location, links to other accounts, and
verified accounts on other platforms.

```bash
printf '%s' "jdoe@example.com" | tr 'A-Z' 'a-z' | md5sum
```

Free, passive, no key. Run the avatar through `find-the-original-image`. Treat a
default fallback image as "no Gravatar", not as "address invalid".

**Done when** Gravatar presence is checked and any profile fields captured.

## Step 4 — Where is this address registered

The honest position: reliable account enumeration by email is an *oracle*
problem. Password-reset and signup forms disclose whether an address is
registered, which is exactly why tools exist to automate them — and exactly why
doing so is interactive, often against terms of service, and potentially
notifying (a reset request can email the subject). Flag it, get it authorized
explicitly, or don't do it.

Passive alternatives that cost you nothing:

- `google-like-a-spy` the full address in quotes, and the local part alone.
  Resumes, conference programmes, mailing-list archives, `WHOIS` history, and
  committed config files are full of addresses.
- Run `what-leaked-about-you`. Breach membership is the single best answer to
  "which services did this identity use", and it is retrospective rather than
  interactive.
- Push the local part into `hunt-a-handle` as a username seed.
- Search code hosting for the address in commit metadata via
  `secrets-in-git-history`.

**Done when** the service list is assembled and each entry is marked passive or
interactive in provenance.

## Step 5 — Read the headers, if you have the message

Only applies when you legitimately possess the message. Headers are where an
email stops being a selector and becomes evidence.

Read the `Received:` chain **bottom-up**: the bottom-most is the earliest hop,
and the originating host is there unless the sending platform strips it.
Everything below the first server you trust can be forged wholesale.

- `Message-ID` — the domain part and the ID's shape often identify the sending
  platform or mail client even when the visible headers are cosmetic.
- `Authentication-Results` — the receiving server's SPF, DKIM, and DMARC
  verdicts. A DKIM `pass` is the strongest thing in the header block: it is a
  cryptographic signature over content, so it survives forwarding claims.
- `X-Mailer` / `User-Agent` — client fingerprint, frequently left in place by
  bulk-mail tooling.
- `Return-Path` vs `From` — a mismatch is normal for mailing lists and
  suspicious in direct correspondence.

Field-by-field guide:
[reference/header-fields.md](reference/header-fields.md).

**Done when** the originating infrastructure is identified or explicitly stated
as unrecoverable.

## Where this goes wrong

- **Catch-all domains defeat verification outright.** Everything validates.
  Detect one by testing an address you invented; if a random string validates,
  every result from that domain is meaningless.
- **Disposable and forwarding services.** Throwaway domains mean the address was
  never meant to persist; relay and alias services (including provider-issued
  private-relay addresses) mean the visible address is a wrapper around a
  mailbox you cannot see. Both cap how far the address can take you — recognise
  them early rather than burning hours.
- **Role addresses** (`info@`, `sales@`, `admin@`) belong to functions, not
  people. Attributing one to an individual is the most common serious error in
  email OSINT, and it survives into reports because it looks like a finding.
- **Inferred addresses are hypotheses.** Deriving `j.doe@company.com` from a
  company pattern gives a plausible address, not a real one. Label it inferred,
  permanently.
- **Breach data is not proof of current ownership.** Addresses get abandoned,
  recycled by providers, and reassigned to new staff at the same company.
- **Forwarding is indistinguishable from forgery** at a glance. Mailing lists
  and security gateways rewrite headers in ways that look like tampering.

## Confidence grading

- **Confirmed** — a DKIM-passing message from the address, or the address
  published by the subject on a source they control, or an authenticated
  Gravatar profile matching a separately confirmed identity.
- **Probable** — MX-valid, appears in a breach alongside a corroborating
  selector, and the local part matches the subject's name pattern.
- **Unconfirmed** — inferred from a corporate format, or found in a single
  aggregator or combolist with no second source.
- **Rejected** — proven catch-all with no supporting evidence, a known
  disposable domain with no linked activity, or a role address attributed to an
  individual on no basis but the domain.

## Worked example

Given `j.okonkwo@northwind-eng.example`. `dig MX` returns records at a hosted
provider — the domain takes mail. Gravatar: no avatar, so no profile pivot.

Two employee addresses in a conference PDF are `t.mwangi@` and `s.aldridge@`, so
the convention is `first-initial.lastname`. That makes `j.okonkwo@`
structurally consistent — evidence about the *format*, not evidence the person
exists. No SMTP probe is run; interactive steps are out of scope here.

The dead end: `what-leaked-about-you` returns nothing for the address, which
initially reads as "not a real user". Re-running against the Gmail-normalised
personal address recovered from a code-hosting commit gives three breaches, one
of them a developer forum with the handle `sunfish_ada`. That handle goes to
`hunt-a-handle`. The corporate address stays graded inferred; the personal one
is the working selector.

## Pivots

| New selector | Skill |
|---|---|
| Name from local part or Gravatar | `find-anyone` |
| Local part as username | `hunt-a-handle` |
| Email domain | `who-owns-this-domain`, `recon-a-domain-passively` |
| Employer from a corporate domain | `x-ray-a-company` |
| Breach appearances | `what-leaked-about-you` |
| Address in commits or config | `secrets-in-git-history` |
| Originating IP from headers | `find-exposed-servers` |
| Gravatar or profile avatar | `find-the-original-image` |
| Address posted in dumps or channels | `find-leaks-in-the-wild` |

## Legal and ToS notes

SMTP probing and password-reset enumeration are interactive, commonly prohibited
by terms of service, and in some jurisdictions arguably unauthorized
interrogation of a system. Get them in writing before you use them. Under GDPR
and UK data protection law an email address is personal data on its own —
collect only what the objective needs, store it encrypted, and set a deletion
date with the case file. Message content you possess may carry separate
confidentiality or privilege obligations independent of the OSINT question.

## Step 6 — Report

Run `write-the-intel-brief`. State validity and how it was established, whether
the domain is catch-all, the service list with passive/interactive provenance,
breach exposure, and the identity attribution with its confidence grade.

**Done when** every address is marked observed or inferred, and no inferred
address is stated as fact.

---

## Supporting file: reference/corporate-formats.md

# Inferring a corporate email format

Most organisations issue addresses from a single template. Recover the template
from a few known addresses and you can generate a plausible address for any
employee whose name you have. The output is always a *hypothesis*, and must be
labelled inferred in any report.

## Common templates

Running example: Jane Q. Okonkwo at `northwind.example`.

| Pattern | Result |
|---|---|
| `first.last` | jane.okonkwo@ |
| `firstlast` | janeokonkwo@ |
| `first_last` | jane_okonkwo@ |
| `first-last` | jane-okonkwo@ |
| `flast` | jokonkwo@ |
| `f.last` | j.okonkwo@ |
| `firstl` | janeo@ |
| `first.l` | jane.o@ |
| `first` | jane@ |
| `last` | okonkwo@ |
| `last.first` | okonkwo.jane@ |
| `lastf` | okonkwoj@ |
| `fmlast` | jqokonkwo@ |
| `first.middle.last` | jane.q.okonkwo@ |
| `employee ID` | e40122@ |
| `first.last<n>` | jane.okonkwo2@ (collision suffix) |

Roughly in order of prevalence: `first.last`, `flast`, `firstlast`, `first`,
`f.last`. Start there.

## Deriving the pattern

You need two or three real addresses with known corresponding names. Sources
that are public and passive:

- Press releases, investor relations pages, and regulatory filings — media
  contacts are almost always real, individual addresses.
- Conference programmes, academic papers, and standards documents (PDFs).
- Job postings that name a hiring contact.
- Mailing-list archives, bug trackers, and public support forums.
- Commit metadata on code hosting: corporate laptops commit with corporate
  addresses. Use `secrets-in-git-history`.
- Domain registration and technical contacts, where not redacted: use
  `who-owns-this-domain`.
- `google-like-a-spy` with the domain plus an `@` and a common first name.

Two addresses that agree on a pattern are a weak inference. Three from
independent sources is workable. One is nothing.

## Complications that break the inference

**Multiple domains.** Large organisations run separate domains for corporate,
engineering, regional subsidiaries, and acquisitions. The pattern may be
consistent while the domain is not. Check MX records for candidate domains and
look for which one the known addresses actually use.

**Acquisitions.** Staff from an acquired company often keep legacy addresses,
which get forwarded. Someone's real address may follow the *previous* employer's
convention entirely.

**Collisions.** Two people with the same name force a deviation — a middle
initial, a number, a full first name where others get an initial. The deviation
is invisible from outside.

**Name normalisation.** Accents, hyphens, apostrophes, and non-Latin scripts get
transliterated or stripped, and different organisations do it differently.
Compound and multi-part surnames may be joined, hyphenated, or truncated.
Preferred names diverge from legal names ("Bob" for Robert), and the address may
use either.

**Aliases.** Many organisations issue several addresses per mailbox — a
`first.last` alias over an employee-ID mailbox, for example. Both work; only one
appears in the directory.

**Catch-all domains.** If the domain accepts everything, no amount of validation
will distinguish a real address from a generated one. Test with an obviously
invented name before believing any verification result.

## Role and functional addresses

`info@`, `sales@`, `support@`, `admin@`, `hr@`, `security@`, `abuse@`,
`postmaster@`, `noreply@`, `careers@`, `press@`, `legal@`.

These belong to a function and are usually read by a shared mailbox or a
ticketing system. Never attribute one to a named individual. They are still
useful: `abuse@` and `security@` are often required to be monitored and can
confirm a domain is actively administered, and the auto-reply from a ticketing
system fingerprints the vendor — though soliciting one is interaction, not
passive research.

## Using an inferred address

Do not treat it as confirmed by an SMTP probe — probing is interactive, and
catch-all domains make the result meaningless anyway. Instead, look for the
inferred string appearing independently: in a breach corpus via
`what-leaked-about-you`, in indexed documents via `google-like-a-spy`, in commit
history, or on Gravatar. An independent appearance upgrades the hypothesis to a
finding. Nothing else does.

Record inferred addresses in a separate column from observed ones. The
distinction gets lost the moment they share a table, and an inferred address
that leaks into a client report as fact is a serious error.

---

## Supporting file: reference/header-fields.md

# Email header field reference

Applies only to messages you legitimately possess. Export the raw source (the
"show original" / "view source" function in any mail client) rather than working
from what the client renders — clients hide, reorder, and prettify headers.

## Reading order

Headers are prepended as the message travels, so the file reads newest-first.
Start at the bottom of the `Received:` block and work upward. That gives you the
message's actual path in chronological order.

The trust boundary is the point where the message entered infrastructure you or
the recipient controls. Everything added after that point is trustworthy;
everything claimed before it is sender-supplied and can be fabricated in bulk. A
forged chain is usually a block of plausible-looking `Received:` lines at the
bottom, followed by the one real line added by the first honest relay.

## Trace headers

| Header | What it carries | How it lies |
|---|---|---|
| `Received` | One hop: receiving host, sending host and its IP, protocol, timestamp | Everything below the trust boundary can be invented. The claimed sending hostname is often a `HELO` string the sender chose |
| `Received-SPF` | The receiving server's SPF evaluation for that hop | Only covers the envelope sender domain, not the visible `From` |
| `Authentication-Results` | SPF, DKIM and DMARC verdicts as judged by the receiver | Only meaningful if added by a server you trust; senders can add a fake one |
| `Return-Path` | The envelope sender, where bounces go | Routinely differs from `From` for mailing lists and bulk senders. Mismatch alone is not evidence of fraud |
| `X-Originating-IP` | Client IP, added by some webmail providers | Increasingly omitted. Present in older archives, which is where it is most useful |

## Authentication results, in order of evidentiary weight

**DKIM** is the strongest. A `dkim=pass` verdict means a cryptographic signature
over selected headers and the body validated against a public key in the signing
domain's DNS. It survives relaying, and it means the signing domain genuinely
handled this content. Note the `d=` parameter — the signing domain is often the
sending *platform*, not the apparent sender.

**SPF** authorises a sending IP for the envelope domain. `pass` says the IP was
allowed to send for that domain; it says nothing about the visible `From`, which
is why SPF alone is weak evidence of authorship. It also breaks under
forwarding.

**DMARC** ties the visible `From` domain to an SPF or DKIM pass on an aligned
domain, and publishes a policy for failure. A `dmarc=pass` is the closest a
header gives you to "this really came from that domain".

A missing `Authentication-Results` header does not mean the message failed
checks. It usually means the receiving server did not run them.

## Identity and client headers

| Header | Investigative value |
|---|---|
| `Message-ID` | A globally unique ID. Its right-hand domain and its left-hand format are a fingerprint: bulk platforms, ticketing systems, CRMs, and mail clients each generate distinctively shaped IDs. Often identifies the sending system when nothing else does |
| `X-Mailer`, `User-Agent` | The composing client or library. Bulk-send tooling frequently leaves it in |
| `Date` | Sender-supplied. Compare against the earliest trustworthy `Received` timestamp — a large gap or a timezone inconsistent with the claimed sender is a flag |
| `In-Reply-To`, `References` | Reconstruct thread structure, and prove which messages the sender had seen |
| `List-Id`, `List-Unsubscribe` | Confirms a mailing list, and names it |
| `X-*` custom headers | Bulk platforms, spam filters and gateways add vendor-specific headers that name the vendor. Read them all; they are the least curated part of the message |

## MIME and attachment metadata

Boundary strings are generated by the composing library and are themselves a
client fingerprint. Attachment filenames, `Content-Type` parameters, and the
attachment's own embedded metadata carry more identity than the headers do — run
attachments through `secrets-in-file-metadata`, and embedded images through
`find-the-original-image`.

## Turning headers into selectors

- Originating IP → geolocation is coarse and often wrong for mobile and
  corporate networks; passive infrastructure detail via `find-exposed-servers`,
  ownership via `who-owns-this-domain`.
- Sending domain → `who-owns-this-domain` and `recon-a-domain-passively`.
- Signing domain (`d=` in DKIM) → identifies the platform used to send.
- Any address in `From`, `Reply-To`, `Cc` → back to the main skill.

## What headers will not give you

The sender's physical location. A residential IP narrows to an ISP and a broad
region at best; VPNs, mobile carriers, and corporate egress make even that
unreliable, and every major webmail provider now sends from its own
infrastructure so the originating client IP simply is not present. If the
question is "where was this person", headers are the wrong instrument.

---

## Supporting file: ETHICS.md

# Ethics, Legality & Authorized Scope

OSINT is powerful. These skills are built for **lawful, authorized, defensive
work**: threat intelligence, fraud investigation, due diligence, journalism,
missing-persons research, penetration-test reconnaissance, and personal digital
self-defense.

Every workflow skill opens with an **authorized scope** gate. Honor it.

## The rules

1. **Passive by default.** Prefer observation over interaction. Never log in to,
   probe, exploit, or send traffic to a target's private systems without written
   authorization. Reading a public profile is OSINT; brute-forcing a login is a
   crime.
2. **Stay legal in your jurisdiction.** Computer-misuse, wiretap, stalking,
   harassment, and data-protection laws (GDPR, CCPA, etc.) all apply to
   research. When unsure, stop and get counsel.
3. **No harassment, doxxing, or stalking.** Do not use these skills to locate,
   intimidate, or expose private individuals for harm. Aggregating someone's
   personal data to threaten them is abuse, full stop.
4. **Minimize and protect data.** Collect only what the objective requires.
   Store case data encrypted, share on need-to-know, and delete when done.
5. **Corroborate before you conclude.** A single selector match is a lead, not a
   fact. Attribution requires multiple independent, corroborating sources.
6. **Respect terms of service and rate limits.** Automated scraping can be
   illegal or get you banned. Use official APIs where they exist.

## Not for

Stalking, harassment, doxxing, unauthorized access, or any activity prohibited
by law. If your objective is to harm a person, these skills are not for you.

By using this repository you accept full responsibility for how you apply it.
The authors provide it "as is" with no warranty (see [LICENSE](LICENSE)).
