원클릭으로
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.
| 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 |
从文稿内容生成专业 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).