---
name: moltsets-enrich-list-best-email
description: Use this skill when the user has a list of LinkedIn URLs and wants the best available email for each - business email preferred, personal email as fallback.
---

# Enrich List - Best Email

Retrieve the best available email for multiple LinkedIn profiles using `MoltSets:linkedin_to_best_email` (hybrid mode), one call per URL run in parallel.

## Triggers

"get the best email for these LinkedIn URLs", "enrich this list with any email", "highest coverage email lookup", "bulk email enrichment", any pasted or uploaded list of LinkedIn URLs where maximising email hit rate is the goal - without requiring strictly business or personal.

Use **test-enrich-list-email** instead if the user explicitly asks for business email only.

## Set Expectations

Before firing any calls, give the user a brief, dry heads-up. Deadpan over enthusiastic - no filler, no corporate speak.

Facts to convey:
- One call per URL, fired in parallel
- Returns business email per profile where available, personal email as fallback
- ~10–20 seconds for small lists; up to 60–90 seconds for 100 URLs
- Credits only charged on hits - not-found results are free
- Higher combined hit rate than business-only or personal-only lookups
- Every email returned carries an A–F deliverability risk score

## Step 0 - Confirm acceptable risk scores

Every email MoltSets returns carries a deliverability risk score - a grade from A to F. Ask which grades to keep before running anything:

> "MoltSets grades email deliverability risk from A (best) to F (no data). Which grades should I keep? I'd recommend **A, B, C and F** - and dropping **D**, since D is a confirmed bounce, complaint or spam trap."

| Grade | Meaning | Best practice |
|---|---|---|
| A | Strongest engagement signal available | Safe to send immediately |
| B | Solid | Fine in regular sends; on a new or warming domain, send a smaller batch before scaling |
| C | Deliverability can't be confirmed | Segment separately from A/B, warm at low volume, watch engagement, suppress non-responders after 1-2 attempts |
| D | Confirmed bounce, complaint or spam trap | Never send - fastest way to trip spam traps and damage sender reputation for the whole list |
| F | No data - unknown risk, not "safe" | Re-verify before sending, or treat like C |

Use whatever set the user confirms. Treat the grade as a filter, not a guarantee - it lowers risk, it doesn't remove it. Pair it with the user's own sending domain reputation and list hygiene.

## Step 1 - Parse input

Accept:
- Line-separated paste
- Comma-separated list
- CSV (extract the LinkedIn URL column)

Deduplicate and normalise. Construct full URLs from slugs where needed.

Report the count: "X unique LinkedIn URLs."

## Step 2 - Output preference

Before running enrichment, ask the user how they want the results delivered.

First, check which output-capable MCPs are available in this session. Always offer:
1. Table in this window
2. CSV file (saved locally)

Then scan connected MCPs for any that support creating or writing documents, spreadsheets, or structured data (e.g. Google Drive/Sheets, Notion, or similar). Add each detected integration as a numbered option. Do not offer an integration that isn't connected - only surface what's live.

Present the full options list and wait for the user's choice before proceeding.

**If the user picks a file or integration output:** ask for a filename or destination now (before enrichment runs) so there's no delay after results come back.

## Step 3 - Batch by concurrency

`linkedin_to_best_email` takes a single `linkedin_url` per call - there is no batch array. Fire one call per URL in parallel, in batches sized to a sensible concurrency limit (e.g. 10–20 at a time), until the whole list is processed.

## Step 4 - Run enrichment

For each URL, call `MoltSets:linkedin_to_best_email` with `linkedin_url: "[URL]"`. Run these single calls in parallel.

## Step 5 - Output

Deliver results in the format chosen in Step 2.

**Table (in chat):**

| LinkedIn URL | Email | Type | Risk | Kept |
|---|---|---|---|---|
| linkedin.com/in/janesmith | jane@acmecorp.com | business | A | yes |
| linkedin.com/in/johndoe | john.doe@gmail.com | personal | C | yes |
| linkedin.com/in/riskyone | sam@oldco.com | business | D | no - outside accepted set |
| linkedin.com/in/noemail | Not found | - | - | - |

Always show the true risk score on every row, including emails that fall outside the accepted set - flag them in `Kept` rather than dropping them silently, so the user can see what was filtered and why.

**CSV file:** write to the path agreed in Step 2. Include a header row (`LinkedIn URL,Email,Type,Risk,Kept`). Use `Not found` and `-` for empty results.

**Integration (Google Sheets, Notion, etc.):** create a new document/sheet at the destination agreed in Step 2. Same columns and values as the CSV format. Confirm the link or location to the user when done.

Always append a summary regardless of output format:
```
Emails found:    X/N (XX%)
  - business:  X
  - personal:  X

By risk score:
  A: X   B: X   C: X   D: X   F: X
  kept (accepted grades):  X
  filtered (excluded):     X
```

Do not fabricate data.
