DEV Community

Cover image for How I Built a Cold Email Script That Personalizes Every Message (With Code)
Lawrence
Lawrence

Posted on

How I Built a Cold Email Script That Personalizes Every Message (With Code)

I'm a university student in Hong Kong. I spent two hours writing cold emails last week — between classes and assignments — trying to land some freelance clients. Every single one started with "Hi [FirstName], I hope you're doing well."

I sent 40. I got zero replies.

The problem wasn't the offer. It was that every email was obviously templated. You could smell it from the first line. And the people I was emailing — marketing directors, founders — get 50 of those a day.

So I built a script to fix it. Here's how it works, and the code behind it.

The Problem With Mail Merge

Standard mail merge replaces [FirstName] with the actual name. That's not personalization. That's a template with a name plugged in.

Real personalization means referencing something specific about the person or their company. Something that proves you actually looked.

But doing that manually for 100 prospects takes 8-10 hours. As a student with a part-time schedule, I don't have that kind of time.

The Solution: One Hook Per Prospect

The script works on a simple premise: you give it one specific hook for each prospect, and it writes the rest.

Here's what the input looks like:

name,role,company,email,hook
Jane Smith,Marketing Director,Acme Corp,jane@acmecorp.com,Acme just launched a new eco-friendly product line and is hiring 3 marketing roles
Enter fullscreen mode Exit fullscreen mode

That hook column is the key. It's the one piece of information that proves you did your homework. The script takes that hook and writes an email that references it naturally.

The Code

The core of the script is a single function that calls an AI model with a structured prompt:

def generate_email(name, role, company, hook):
    prompt = f"""Write a short, personalized cold email.

Recipient: {name}, {role} at {company}
Personalization hook: {hook}

Rules:
- Keep it under 120 words
- Professional but conversational
- Reference the hook naturally
- End with a soft call to action
"""
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "You are a cold email copywriter."},
            {"role": "user", "content": prompt}
        ],
        temperature=0.7,
    )
    return response.choices[0].message.content.strip()
Enter fullscreen mode Exit fullscreen mode

The rest of the script is just CSV reading and writing. No complex infrastructure. No database. Just a loop.

What the Output Looks Like

Here's a real output generated from the hook above:

Subject: Quick thought on Acme's eco-friendly launch

Hi Jane,

I saw Acme just launched a new eco-friendly product line and is hiring 3 marketing roles. That combination usually means the team is stretched thin on content and campaign execution.

I help marketing teams automate personalized outreach so they can focus on strategy, not manual work. Worth a 15-minute chat?

Best,
[Your Name]

It's not perfect. It's not a human copywriter. But it's specific, it's fast, and it doesn't sound like a template.

The One Thing I'd Do Differently

The hook column is everything. If you write a generic hook like "great company," the AI will write a generic email. The quality of the output is directly proportional to the quality of the input.

The second thing: don't let the script send emails. It only generates them. You review the output and send from your own inbox. This protects your domain reputation and keeps you in control of what goes out.

What I Learned

  1. Personalization is about specific signals, not names. The hook matters more than the template.
  2. Prompt engineering is mostly about constraints. "Under 120 words" and "reference the hook naturally" do more work than any clever instruction.
  3. Keep the scope narrow. This script does one thing. It doesn't scrape leads. It doesn't send emails. It writes them. That's it.
  4. Building something small is the fastest way to learn. As a student, I don't have the resources to build a full SaaS. But a single Python script? That I can do in a weekend.

If You Want to Skip the Build

I packaged the full script with a README, a CSV template, and a setup guide. You can see the output quality in a free sample pack first.

Free sample pack (3 example emails): https://wealthaccumulator.gumroad.com/l/yhwke

Full script ($29): https://wealthaccumulator.gumroad.com/l/ovdfpv

It takes about 5 minutes to set up. You'll need Python and an OpenAI API key.

If you have questions about the prompt structure or want to adapt it for your own use case, drop a comment. I'm happy to share what worked and what didn't.

Top comments (0)