package tempinbox
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"regexp"
"time"
)
const base = "https://tempinbox.dev"
type Inbox struct {
Address string `json:"address"`
JWT string `json:"jwt"`
}
type Mail struct {
UUID string
Subject string
Raw string
}
func CreateInbox() (*Inbox, error) {
res, err := http.Post(base+"/api/new_address", "application/json",
bytes.NewBufferString("{}"))
if err != nil {
return nil, err
}
defer res.Body.Close()
var inbox Inbox
return &inbox, json.NewDecoder(res.Body).Decode(&inbox)
}
func WaitForMail(jwt string, timeout time.Duration) (*Mail, error) {
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
var list struct {
Results []struct {
UUID string `json:"uuid"`
} `json:"results"`
}
if err := getJSON("/api/mails?limit=1&offset=0", jwt, &list); err != nil {
return nil, err
}
if len(list.Results) > 0 {
var full struct {
UUID string `json:"uuid"`
Raw string `json:"raw"`
Metadata string `json:"metadata"`
}
if err := getJSON("/api/mail/"+list.Results[0].UUID, jwt, &full); err != nil {
return nil, err
}
var meta struct {
Subject string `json:"subject"`
}
_ = json.Unmarshal([]byte(full.Metadata), &meta) // metadata is a JSON string
return &Mail{UUID: full.UUID, Subject: meta.Subject, Raw: full.Raw}, nil
}
time.Sleep(2500 * time.Millisecond)
}
return nil, fmt.Errorf("no email received within %s", timeout)
}
var otpRe = regexp.MustCompile(`\b\d{6}\b`)
func ExtractOTP(raw string) (string, error) {
if m := otpRe.FindString(raw); m != "" {
return m, nil
}
return "", errors.New("no 6-digit OTP found")
}
func getJSON(path, jwt string, v any) error {
req, _ := http.NewRequest("GET", base+path, nil)
req.Header.Set("Authorization", "Bearer "+jwt)
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
return json.NewDecoder(res.Body).Decode(v)
}