Temp mail
in Go.
Disposable email for Go, one HTTP call away.
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("POST",
"https://evilmail.pro/api/temp-email",
bytes.NewBufferString(`{"ttlMinutes": 30}`))
req.Header.Set("X-API-Key", os.Getenv("EVILMAIL_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
var r struct {
Data struct {
Email string `json:"email"`
SessionToken string `json:"sessionToken"`
} `json:"data"`
}
json.NewDecoder(resp.Body).Decode(&r)
fmt.Println("Inbox ready:", r.Data.Email)
}Spin up temp mail in Go in a few lines: EvilMail's disposable email API lets you create throwaway inboxes, poll for incoming messages, and extract OTP codes straight from your test suite or CI pipeline. Instead of babysitting a real mailbox or scraping a web UI, you hit plain HTTP endpoints with net/http and decode the JSON — no third-party SDK, no headless browser. It's built for Go email verification testing, signup-flow smoke tests, and any workflow where you need a real, receiving address on demand.
Why use temp mail in Go
Automated signup testing
Register a fresh disposable email in Go for every end-to-end test run so accounts never collide. Each inbox is real and receiving, so your registration flow behaves exactly as it does in production.
OTP and email verification
Poll the inbox, grab the confirmation mail, and regex out the 6-digit code — all in one Go routine. Perfect for testing verification and two-factor flows without a human in the loop.
CI/CD pipelines
Because it's just net/http and an API key from an env var, the same code runs locally and in GitHub Actions or GitLab CI. No SMTP server, no mailbox credentials to rotate.
Load and multi-account testing
Create many independent inboxes concurrently with goroutines to simulate hundreds of users signing up at once. Each session token isolates one mailbox, so parallel tests stay clean.
The flow — Go temp mail in 3 calls
Create a disposable inbox
// createInbox spins up a disposable EvilMail inbox and
// returns its address plus the session token used to poll it.
func createInbox(key string) (email, token string, err error) {
body := bytes.NewBufferString(`{"ttlMinutes": 30}`)
req, err := http.NewRequest("POST",
"https://evilmail.pro/api/temp-email", body)
if err != nil {
return "", "", err
}
req.Header.Set("X-API-Key", key)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", "", err
}
defer resp.Body.Close()
var r struct {
Data struct {
Email string `json:"email"`
SessionToken string `json:"sessionToken"`
} `json:"data"`
}
if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
return "", "", err
}
return r.Data.Email, r.Data.SessionToken, nil
}Poll until the email arrives
// Message mirrors one row from the inbox listing.
type Message struct {
UID int `json:"uid"`
From string `json:"from"`
Subject string `json:"subject"`
}
// waitForMessage polls the inbox ~20 times, 3s apart, until at
// least one message lands, then returns the first one.
func waitForMessage(key, token string) (Message, error) {
url := "https://evilmail.pro/api/temp-email/" + token
for i := 0; i < 20; i++ {
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("X-API-Key", key)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return Message{}, err
}
var r struct {
Data struct {
Messages []Message `json:"messages"`
} `json:"data"`
}
json.NewDecoder(resp.Body).Decode(&r)
resp.Body.Close()
if len(r.Data.Messages) > 0 {
return r.Data.Messages[0], nil
}
time.Sleep(3 * time.Second) // wait, then retry
}
return Message{}, fmt.Errorf("timed out waiting for email")
}Read the message & extract the code
// otpRe matches a standalone 6-digit verification code.
var otpRe = regexp.MustCompile(`\b(\d{6})\b`)
// readCode fetches a message body and pulls the 6-digit OTP.
func readCode(key, token string, uid int) (string, error) {
url := fmt.Sprintf(
"https://evilmail.pro/api/message/%d?token=%s", uid, token)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("X-API-Key", key)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
var r struct {
Data struct {
Text string `json:"text"`
HTML string `json:"html"`
} `json:"data"`
}
json.NewDecoder(resp.Body).Decode(&r)
// Regex over the plain-text body (fall back to HTML).
m := otpRe.FindStringSubmatch(r.Data.Text)
if m == nil {
return "", fmt.Errorf("no 6-digit code found")
}
return m[1], nil
}Go temp mail — FAQ
Q1How do I get a temp mail address in Go?−
Send a POST request to https://evilmail.pro/api/temp-email with your X-API-Key header and a JSON body like {"ttlMinutes": 30}. The response contains data.email (the address) and data.sessionToken (used to poll that inbox). The createInbox function above does exactly this with net/http and encoding/json — no SDK required.
Q2Can I use this for automated testing?+
Yes, that's the primary use case. The whole flow is plain HTTP, so it drops straight into Go test files, CI jobs, or load scripts. Read the API key from an environment variable such as EVILMAIL_KEY, create an inbox per test, and tear it down when the TTL expires. You can create many inboxes concurrently with goroutines for parallel tests.
Q3How do I extract the OTP from an email?+
After polling returns a message, GET https://evilmail.pro/api/message/{uid}?token={sessionToken} to fetch its body. Then run a regexp over data.text (or data.html). A standalone 6-digit code matches the pattern \b(\d{6})\b — regexp.MustCompile it once and use FindStringSubmatch to capture the digits, as shown in readCode.
Q4Do I need an API key, and are there rate limits?+
Yes — every request must send your key in the X-API-Key header, and message reads also require it. Never hard-code the key; load it from an env var. Rate limits are applied per key and are generous enough for normal test and CI usage; if you're running heavy load tests, add a small backoff between calls (the poll loop already sleeps 3s between attempts).
Q5How long does the inbox live?+
The inbox lifetime is set by the ttlMinutes value you pass when creating it — for example 30 minutes. Once the TTL elapses, the inbox and its messages are purged and the session token stops returning mail, so create a fresh inbox for each run rather than reusing an old token.
Temp mail in other languages
One API key. Disposable inboxes at scale.
Create unlimited throwaway addresses, poll them over HTTP, and pull verification codes straight into your tests and CI. Free to start; custom domains and higher limits on paid plans.

