In this article, you will learn how to build a fully functional phishing simulator from scratch on Windows — no expensive tools, no vendor lock-in, just open source software you control completely. By the end you will have a working mail server, landing pages, campaign tracking, and your first phishing simulation ready to launch against your own team.

$50,000 a year to send fake phishing emails to your own colleagues. That is the going rate for most enterprise phishing simulation platforms. You do not have to pay it. KnowBe4, Cofense, Proofpoint — they work. But your campaign data lives on their servers, you get the templates they choose, and when something breaks you wait in a support queue.
Building your own fixes all of that. You own the data, you control every template, and — this part matters — understanding how it works makes you significantly better at spotting the real thing.
This is Part 1 of two. By the end you will have a working phishing simulator on Windows — mail server, landing pages, tracking, and your first campaign running. Part 2 covers AI-generated lures, automated OSINT, and a Docker setup that brings the whole stack up in one command.
One thing first — get written authorization before running any of this against real users. There is a template at the end of this article. Do not skip it. Running an unauthorized phishing simulation against colleagues, even with good intentions, can end careers. Get it signed
1. Understanding What You Are Actually Building
A phishing simulator is not one tool. It is four things working together. Before you install anything, get this picture clear in your head:

Campaign Manager — GoPhish This is your cockpit. You build email templates here, upload your target list, schedule campaigns, and watch results come in live. Who opened. Who clicked. Who typed their password into your fake login page. GoPhish handles all of this and wraps it in a clean web interface.
Mail Server — hMailServer GoPhish does not send emails on its own — it needs a mail server to do the actual delivery. hMailServer is free, runs on Windows, and gives you full control over how your emails leave the machine. Without a properly configured mail server, every email you send lands straight in spam and nobody sees it.
Landing Page Server — GoPhish built-in When someone clicks the link in your email, they land here. This page is a clone of your company’s real login page. It captures what the user types, then immediately redirects them to the real login page so they think they just mistyped their password. They have no idea anything happened.
Tracking Dashboard — GoPhish built-in Real-time view of everything. Every open, every click, every credential submission — logged with timestamps, IP addresses, and browser details.
2. What You Need Before You Touch Anything
Hardware
You do not need anything exotic. If you have a spare Windows machine or a VM sitting around, that works fine for internal campaigns.
| Component | Minimum | What I Actually Recommend |
|---|---|---|
| Machine | Windows 10/11, any spec | Dedicated Windows Server 2019/2022 |
| RAM | 4GB | 8GB |
| Storage | 20GB free | 50GB free |
| Network | Internal access | Static IP if running external campaigns |
Software — Download These First
- GoPhish — github.com/gophish/gophish/releases
- hMailServer — hmailserver.com/download
- Python 3.11+ — python.org/downloads
- OpenSSL for Windows — slproweb.com/products/Win32OpenSSL.html
- Notepad++ — for editing config files without losing your mind
A Domain
You need a domain that is not your real company domain. If your company is acmecorp.com, register something like acmecorp-it.com or acme-helpdesk.com. Close enough to look familiar. Far enough to stay clearly separate from production.
Namecheap or Cloudflare both work. Expect to spend around $10–15 a year. Do not cheap out on this step — a suspicious looking domain kills the realism of your entire campaign before the email is even opened.
3. Setting Up GoPhish on Windows
GoPhish is the heart of the operation. It is a single binary — no installer, no dependencies.
Step 1 — Download and Extract
Download the latest Windows release from the GoPhish GitHub releases page. At the time of writing, look for gophish-v0.12.1-win64.zip.
Extract it to a dedicated folder:
C:\PhishSim\gophish\Your folder should look like this after extraction:
C:\PhishSim\gophish\ gophish.exe config.json static\ templates\ db\
Step 2 — Configure GoPhish
Open config.json in Notepad++. This is where you tell GoPhish where to listen and how to behave.
{ "admin_server": { "listen_url": "127.0.0.1:3333", "use_tls": true, "cert_path": "gophish_admin.crt", "key_path": "gophish_admin.key" }, "phish_server": { "listen_url": "0.0.0.0:80", "use_tls": false, "cert_path": "example.crt", "key_path": "example.key" }, "db_name": "sqlite3", "db_path": "gophish.db", "migrations_prefix": "db/db_", "contact_address": "", "logging": { "filename": "", "level": "" }}
What each setting means:
admin_server.listen_url: 127.0.0.1:3333— The GoPhish admin dashboard only listens on localhost. This means only someone on this machine can access the admin panel. Never expose this to the internet.phish_server.listen_url: 0.0.0.0:80— The landing page server listens on all interfaces on port 80. This is the page targets land on when they click your link. It needs to be reachable.db_path: gophish.db— All campaign data, templates, results stored in a local SQLite database file. Back this up regularly.
Step 3 — Run GoPhish
Open PowerShell as Administrator and navigate to your GoPhish folder:
cd C:\PhishSim\gophish.\gophish.exe
On first run you will see output like this:
time="2026-09-16T10:00:00Z" level=info msg="Please login with the username admin and the password [GENERATED_PASSWORD]"time="2026-09-16T10:00:00Z" level=info msg="Starting admin server at https://127.0.0.1:3333"time="2026-09-16T10:00:00Z" level=info msg="Starting phishing server at http://0.0.0.0:80"
Copy that generated password immediately. It only shows once. Open your browser and go to https://127.0.0.1:3333. Accept the self-signed certificate warning and log in with username admin and the generated password. Change your password immediately after first login.
Step 4 — Run GoPhish as a Windows Service
You do not want to keep a PowerShell window open forever. Run GoPhish as a background service using NSSM (Non-Sucking Service Manager).
Download NSSM from nssm.cc/download. Extract it and run:
# Navigate to where nssm.exe is extractedcd C:\Tools\nssm\win64# Install GoPhish as a service.\nssm.exe install GoPhish# In the GUI that opens:# Path: C:\PhishSim\gophish\gophish.exe# Startup directory: C:\PhishSim\gophish# Click Install service# Start the service.\nssm.exe start GoPhish
GoPhish now starts automatically when the machine boots and runs silently in the background.
4. Setting Up hMailServer
GoPhish can send emails, but it relies on an SMTP server to actually deliver them. hMailServer is a free, lightweight mail server for Windows that gives you full control over how emails are sent.
Step 1 — Install hMailServer
Run the hMailServer installer. During installation:
- Select Server as the installation type
- Use the built-in database engine (MySQL not needed for this scale)
- Set a strong administrator password — write it down
Step 2 — Configure Your Domain
Open hMailServer Administrator from the Start menu.
- Connect to localhost with your admin password
- Right click Domains → Add Domain
- Enter your phishing domain:
acmecorp-it.com - Click Save
Step 3 — Create a Sending Account
Under your new domain:
- Click Accounts → Add
- Username:
helpdesk - Password: something strong
- Click Save
This creates the email address helpdesk@acmecorp-it.com — your sending address.
Step 4 — Configure SMTP Settings in hMailServer
Go to Settings → Protocols → SMTP:
Max message size: 20480 (20MB)Max recipients per message: 100Delivery of e-mail: Always use internal relay
Go to Settings → Advanced → IP Ranges:
Add your local machine IP to the allowed relay range. This lets GoPhish (running on the same machine) send through hMailServer without authentication errors.
Step 5 — Connect GoPhish to hMailServer
In the GoPhish admin panel, go to Sending Profiles → New Profile:
Name: Internal HelpdeskFrom: IT Helpdesk <helpdesk@acmecorp-it.com>Host: 127.0.0.1Port: 25
Leave username and password blank — hMailServer will accept connections from localhost without authentication based on the IP range you configured.
Click Send Test Email to verify it works before building any campaign.
5. DNS Configuration — The Part That Makes or Breaks Delivery
This is where most people get it wrong. If your DNS is not configured correctly, every email you send lands in spam. Even perfectly written emails. Even ones that look completely legitimate. DNS is what email servers check before they decide whether to trust you.
You need three records on your phishing domain. All of these are set in your domain registrar’s DNS panel (Namecheap, Cloudflare, etc.).
SPF Record — Tells the World Which Servers Can Send From Your Domain
Type: TXTName: @Value: v=spf1 ip4:YOUR_MACHINE_IP ~all
Replace YOUR_MACHINE_IP with the public IP of the machine running hMailServer. The ~all at the end means emails from other IPs are a soft fail — they may still be delivered but marked suspicious. Use -all for hard fail once you are confident everything is working.
What this does: When a receiving mail server gets an email from helpdesk@acmecorp-it.com, it looks up this SPF record and checks whether the sending IP is on the approved list. If it is, the email passes this check.
DKIM Record — Cryptographically Signs Your Emails
DKIM adds a digital signature to every email you send. The receiving server uses your public key (published in DNS) to verify the signature. If it matches, the email has not been tampered with in transit.
Generate DKIM keys using OpenSSL. Open PowerShell:
# Generate private keyopenssl genrsa -out dkim_private.key 2048# Extract public key from private keyopenssl rsa -in dkim_private.key -pubout -out dkim_public.key# View the public key to copy into DNSGet-Content dkim_public.key
The public key output looks like this:
-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2a7T...-----END PUBLIC KEY-----
Remove the header, footer, and all line breaks. The resulting single long string goes into your DNS record:
Type: TXT
Name: mail._domainkey
Value: v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ…
Now configure hMailServer to sign outgoing emails with the private key: In hMailServer Administrator go to Domains → acmecorp-it.com → Signatures:
Enabled: Yes
Private key file: C:\PhishSim\keys\dkim_private.key
Selector: mail
Domain: acmecorp-it.com
DMARC Record — Tells Receivers What to Do If SPF or DKIM Fails
Type: TXTName: _dmarcValue: v=DMARC1; p=none; rua=mailto:dmarc@acmecorp-it.com
Start with p=none — this means monitor only, do not reject anything. Once you have confirmed everything is working and delivery is clean, move to p=quarantine and eventually p=reject.
Verify your DNS is working correctly using MXToolbox:
- Go to mxtoolbox.com/SuperTool.aspx
- Run SPF lookup, DKIM lookup, and DMARC lookup for your domain
- All three should show green
6. Email Templates — The Psychology Behind Each One
A phishing email works because it triggers something — urgency, authority, familiarity, fear. Before you write a single line of HTML, decide which trigger you are testing. Different triggers catch different people, and understanding which ones work on which departments tells you a lot about where your training gaps actually are.
Here are three templates to get you started. Each one targets a different psychological lever.
Template 1 — IT Helpdesk Password Reset
Trigger: Fear of losing access
This one works because people are conditioned to respond to IT requests. The deadline makes them act fast without thinking.
<html><head> <meta charset="UTF-8"> <style> body { font-family: Arial, sans-serif; font-size: 14px; color: #333; } .header { background-color: #0078D4; padding: 20px; color: white; } .content { padding: 30px; } .button { background-color: #0078D4; color: white; padding: 12px 24px; text-decoration: none; border-radius: 4px; display: inline-block; margin: 20px 0; } .footer { font-size: 11px; color: #666; border-top: 1px solid #eee; padding: 20px; } </style></head><body> <div class="header"> <strong>IT Helpdesk — Action Required</strong> </div> <div class="content"> <p>Hi {{.FirstName}},</p> <p>Our systems flagged that your account password has not been updated in the last 90 days. Under our updated security policy (ref: IT-SEC-2026-09), all accounts must complete password verification before <strong>Friday, September 18</strong>.</p> <p>Accounts not verified by this deadline will be suspended until IT confirms your identity in person.</p> <a href="{{.URL}}" class="button">Verify My Account</a> <p>If you have already done this, ignore this message. Questions? Call the helpdesk at ext. 4400.</p> <p>Thanks,<br>IT Helpdesk Team</p> </div> <div class="footer"> Automated message from IT Security. Do not reply directly. </div></body></html>
The two GoPhish variables doing the work:
{{.FirstName}} — GoPhish pulls this from your target list CSV and drops the person’s first name in automatically. Seeing your own name in an email is one of the oldest and most effective personalization tricks.
{{.URL}} — GoPhish generates a unique tracking link for every single target. When Sarah clicks, GoPhish knows Sarah clicked. When James clicks, GoPhish knows James clicked. This is how you get individual-level results rather than aggregate stats.
<html><head> <meta charset="UTF-8"> <style> body { font-family: Calibri, sans-serif; font-size: 14px; color: #333; } .content { padding: 30px; max-width: 600px; } .button { background-color: #217346; color: white; padding: 10px 20px; text-decoration: none; border-radius: 3px; display: inline-block; margin: 15px 0; } .footer { font-size: 11px; color: #888; margin-top: 30px; } </style></head><body> <div class="content"> <p>Hi {{.FirstName}},</p> <p>As part of the annual compliance cycle, all employees must review and acknowledge the updated <strong>Employee Data Handling Policy (2026 revision) </strong> before September 30.</p> <p>Takes around 3 minutes. Click below to review and confirm — your response is recorded automatically.</p> <a href="{{.URL}}" class="button"> Review and Acknowledge </a> <p>Questions? Reach out to HR directly.</p> <p>Best regards,<br> Human Resources<br>People & Culture</p> <div class="footer"> This link expires September 30, 2026. </div> </div></body></html>
Template 3 — Finance Invoice Approval
Trigger: Routine familiarity
This one does not scream urgency. It looks like something the finance team sees every single day. That normalcy is exactly what makes it dangerous — people click without thinking because it feels routine.
<html><head> <meta charset="UTF-8"> <style> body { font-family: Arial, sans-serif; font-size: 14px; color: #222; } .content { padding: 25px; max-width: 600px; } .invoice-box { border: 1px solid #ddd; padding: 15px; margin: 20px 0; background: #f9f9f9; } .button { background-color: #C00000; color: white; padding: 10px 22px; text-decoration: none; border-radius: 3px; display: inline-block; margin: 15px 0; } </style></head><body> <div class="content"> <p>Hi {{.FirstName}},</p> <p>The following invoice needs your approval before the payment run on Friday.</p> <div class="invoice-box"> <strong>Invoice #: INV-2026-04471</strong><br> Vendor: Meridian Technology Solutions<br> Amount: $12,450.00<br> Due: September 19, 2026<br> Category: Software Licensing </div> <p>Log in to the finance portal to approve or flag for review.</p> <a href="{{.URL}}" class="button">Review Invoice</a> <p>Thank you,<br>Finance Operations</p> </div></body></html>
To add any of these to GoPhish — Email Templates → New Template → paste the HTML into the HTML editor tab. Name them clearly. You will thank yourself later when you are managing ten campaigns across five departments and cannot remember which template was which.
7. The Landing Page
The email gets the click. The landing page is where you find out how far someone would have gone in a real attack.
Clone Your Real Login Page
GoPhish has a built-in importer that does the heavy lifting:
- Landing Pages → New Page
- Click Import Site
- Enter your company’s real login URL — your Microsoft 365 portal, your internal HR system, whatever fits the scenario
- GoPhish fetches the HTML and assets automatically
After importing, make two changes:
Enable credential capture Check Capture Submitted Data. GoPhish will now log what users type into the form. Whether you also check Capture Passwords is a judgment call — most security teams log that a submission happened without storing actual passwords. Check your organization’s policy and be explicit about what you are capturing in your authorization letter.
Set the redirect After submission, send the target to the real login page:
Redirect to: https://login.microsoftonline.com
They will think they mistyped their password. They try again on the real page and get in. They never know the first attempt was captured.
Optional — Redirect to a Training Page Instead
Some teams prefer to immediately tell the user what happened rather than silently logging it. Both approaches are valid. The immediate debrief tends to be more effective for learning — people remember the moment they realize they fell for it.
<html><head> <meta charset="UTF-8"> <title>Security Awareness</title> <style> body { font-family: Arial, sans-serif; text-align: center; padding: 60px; background: #f0f4f8; } .card { background: white; padding: 40px; border-radius: 8px; max-width: 500px; margin: 0 auto; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } h2 { color: #C00000; } p { color: #555; line-height: 1.6; } a { display: inline-block; margin-top: 20px; background: #0078D4; color: white; padding: 10px 24px; border-radius: 4px; text-decoration: none; } </style></head><body> <div class="card"> <h2>This Was a Phishing Test</h2> <p>You just clicked a link from a simulated phishing email sent by your security team.</p> <p>Nothing bad happened — but in a real attack, your credentials would now be with an attacker.</p> <p>Please complete the 5-minute awareness module below. It will show you exactly what to look for next time.</p> <a href="https://your-training-portal.com"> Go to Training </a> </div></body></html>
8. Building Your Target List
GoPhish imports targets as a simple CSV. The format is:
First Name,Last Name,Email,PositionSarah,Chen,sarah.chen@acmecorp.com,Accounts Payable ManagerJames,Park,james.park@acmecorp.com,Finance DirectorPriya,Sharma,priya.sharma@acmecorp.com,HR Business Partner
A few things worth saying here:
Pull this list from HR or Active Directory — do not guess email formats. One email that bounces and lands in the wrong inbox can blow the whole campaign.
Start small. Twenty to thirty people for your first run. You will make mistakes on your first campaign — a small group means those mistakes have a small blast radius.
Target one department at a time. Mixed campaigns give you mixed data. If finance has a 40% click rate and engineering has a 5% click rate, you want to know that — not see them averaged into a 22% that tells you nothing useful.
Make sure every person on your list is covered by your authorization letter. No exceptions.
To import — Users & Groups → New Group → Bulk Import Users → upload your CSV.
9. Launching the Campaign
Everything is in place. Here is how to put it together.
Go to Campaigns → New Campaign and fill it in:
Name: Q3 2026 — IT Helpdesk — Finance TeamEmail Template: IT Helpdesk Password ResetLanding Page: Company Login CloneURL: http://YOUR_MACHINE_IPLaunch Date: Tomorrow, 9:00 AMSend Emails By: 11:00 AM (2 hours after launch)Sending Profile: Internal HelpdeskGroups: Finance Team
The Send Emails By setting is important. Do not send 50 emails in the same second — that pattern looks automated and triggers spam filters. Staggering delivery over two hours looks human. GoPhish handles the timing automatically once you set this window.
Click Launch Campaign and let it run.
10. Reading Your Results
GoPhish gives you a live view as the campaign runs. Here is what each status means and — more importantly — what it actually tells you:
| Status | What It Means | What It Tells You |
|---|---|---|
| Email Sent | Delivered to inbox | Your mail server and DNS are working |
| Email Opened | Target opened it | Subject line worked |
| Clicked Link | Target clicked the link | The email was convincing enough |
| Submitted Data | Target entered credentials | They would have been compromised in a real attack |
| Email Reported | Target reported it as suspicious | This is the one you actually want to see |
That last one — Email Reported — is what most teams ignore and should not. A team with a 40% click rate but a 30% report rate is in a better position than a team with a 5% click rate and zero reports. The first team is paying attention and telling someone. The second team is just quietly ignoring suspicious emails, which in a real attack means the attacker has days of undetected access.
11. What Happens After — The Debrief
The simulation is only half of it. What you do in the 24 hours after the campaign ends determines whether any of this actually changes behavior.
Within 24 hours:
- Export results from GoPhish as CSV
- Identify who clicked or submitted
- Send each of them a personal debrief email — not a mass blast, a personal one
- Do not name anyone publicly. Do not post stats on a shared channel. Do not make it a competition. The moment people feel shamed they stop reporting suspicious emails because they are afraid of looking stupid. That is the worst possible outcome for your security posture
- Reach out personally to thank people who reported correctly. That behavior needs positive reinforcement
The debrief email should:
- Explain clearly what just happened
- Show them the specific signals they missed in the email
- Link to a short training module — 5 minutes maximum
- Have a human tone, not a corporate one
Schedule follow-up campaigns for high-risk groups 60 to 90 days later. One simulation changes nothing. Repeated exposure with targeted training over time is what actually moves the numbers.
Authorization Letter — Get This Signed First
PHISHING SIMULATION AUTHORIZATION

Print it. Get it signed by someone with authority — your CISO, your CTO, your legal team. File it before you launch anything. Every campaign gets its own signed letter.
What Is Coming in Part 2
Part 1 gave you a working simulator. Part 2 makes it smarter:
- Using Ollama locally to generate AI-personalized email lures for each target — no two emails alike, no data leaving your machine
- Integrating TheHarvester and SpiderFoot for automated OSINT reconnaissance before email generation
- A Python script that handles the full workflow — OSINT to AI email generation to GoPhish campaign creation — with one command
- A Docker Compose file that spins the entire stack up in one shot
- Metrics that actually matter beyond click rates
- A simple reporting dashboard built in Python
Leave a Reply