en un clic
cold-outreach
// Find local businesses on Google Maps, extract contact emails from their websites, generate personalized outreach emails with LLM, and send via SMTP. Full pipeline for B2B cold email campaigns.
// Find local businesses on Google Maps, extract contact emails from their websites, generate personalized outreach emails with LLM, and send via SMTP. Full pipeline for B2B cold email campaigns.
从文稿内容生成专业 PPTX 演示文稿,支持用户提供的模板/参考图风格提取、AI 配图(siliconflow-img-gen)和素材图库(pexels/pixabay)。纯 Python 生成,无需 Google/ChatGPT API。
通过自媒体平台搜索内容创作者,按预设关键词和判定标准筛选潜在客户。用于 HEARTBEAT 定时任务。
维护 IR(投资人关系专员)的 SQLite 追踪数据库,记录投资人档案和接触历史,避免重复接触,跟踪进展状态。
Scrape Amazon product details via browser and generate platform-optimized promotional content (Twitter/X, Instagram, WeChat) using LLM. No third-party API needed — browser-based extraction only.
Search and download copyright-free images and video clips from Pexels API. Supports both photo search (--type image) and video search (--type video, default).
Search and download copyright-free images and video clips from Pixabay API. Alternative to pexels-footage when Pexels has no suitable results. Supports both photo search (--type image) and video search (--type video, default).
| name | cold-outreach |
| description | Find local businesses on Google Maps, extract contact emails from their websites, generate personalized outreach emails with LLM, and send via SMTP. Full pipeline for B2B cold email campaigns. |
| metadata | {"openclaw":{"emoji":"📧","always":false,"requires":{"bins":["python3"]},"requiredEnv":["SMTP_SERVER","SMTP_USER","SMTP_PASSWORD"],"optionalEnv":["SMTP_PORT","SMTP_FROM","SILICONFLOW_API_KEY"]}} |
Use this skill when:
1. Warm up: navigate to https://www.google.com/maps
2. Perform the search:
https://www.google.com/maps/search/{niche}+{location}
Example: https://www.google.com/maps/search/餐厅+上海朝阳区
3. Wait 3 seconds for results to load
4. For each visible business card in the sidebar:
Extract:
- Business name (visible heading)
- Rating (if shown)
- Address (if shown)
- Phone number (if shown)
- Website URL (if a link icon is present → click to get URL, then go back)
5. Scroll down to load more results (up to the user-specified limit, default: 20)
6. If Google shows CAPTCHA or "unusual traffic" → stop immediately, report to user
7. Save collected data to: ./outreach_data/businesses_YYYY-MM-DD.csv
CSV format:
name,address,phone,website,email
"上海味道餐厅","上海市朝阳区xxx路123号","010-12345678","https://example.com",""
For each business that has a website URL:
Method A — xurl (fast, for static sites):
Use xurl to GET the homepage
Apply regex: \b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b
If email found → record it
Method B — browser (for JS-rendered sites, if Method A fails):
Navigate to the homepage
If no email found on homepage → try /contact and /about paths
Search for "mailto:" links or visible email text
If no email found after both methods → leave email column empty, log "no_email"
Pause 0.5–1 second between each website request to avoid rate limiting.
For each business with a valid email address, generate a personalized email:
LLM Prompt:
"Write a brief, personalized cold outreach email in [Chinese/English].
Business name: {business_name}
Industry: {niche}
Our offer: {user_provided_value_proposition}
Rules:
- Subject line: concise, specific to their business (NOT generic)
- Body: 3–4 sentences max
1. Opening: reference their specific business (show you did research)
2. Value: what we can do for them (focus on their benefit, not our product)
3. CTA: one clear, low-friction ask (e.g., 'Would you be open to a 15-minute call?')
- Plain text only (no HTML, no markdown)
- No pushy sales language
Return JSON:
{
'subject': '...',
'body': '...'
}"
For each business with subject + body generated:
python3 ./skills/cold-outreach/scripts/send_email.py \
--to "{business_email}" \
--subject "{subject}" \
--body "{body}"
Wait 2–3 seconds between each send.
Track results in real time:
outreach_data/sent_YYYY-MM-DD.csvoutreach_data/failed_YYYY-MM-DD.csv with error reason# Send with inline body text
python3 ./skills/cold-outreach/scripts/send_email.py \
--to "target@example.com" \
--subject "Subject line" \
--body "Email body text"
# Send with body from file
python3 ./skills/cold-outreach/scripts/send_email.py \
--to "target@example.com" \
--subject "Subject line" \
--body-file ./outreach_data/template.txt
Returns JSON:
{"ok": true, "to": "target@example.com", "message": "sent"}
{"ok": false, "to": "target@example.com", "error": "Connection refused"}
| Variable | Description | Example |
|---|---|---|
SMTP_SERVER | SMTP hostname | smtp.gmail.com |
SMTP_PORT | Port (default: 587) | 587 |
SMTP_USER | Login / sender address | you@gmail.com |
SMTP_PASSWORD | Password or app password | xxxx xxxx xxxx |
SMTP_FROM | Display name + address | 张三 <you@gmail.com> |
Gmail users: Must use App Passwords (Google Account → Security → App Passwords). Regular passwords will be rejected.
QQ Mail: use SMTP password from QQ mail settings → POP3/SMTP, server: smtp.qq.com, port 587.
| Situation | Action |
|---|---|
| Google CAPTCHA | Stop collection, report to user |
| Business website returns 4xx/5xx | Log as "unreachable", skip email extraction |
| SMTP auth failure | Stop sending, check credentials with user |
| SMTP connection refused | Check SMTP_SERVER and SMTP_PORT |
SMTPDataError: 550 spam rejection | Stop sending — email content flagged as spam, revise template |