package email import ( "fmt" "net/smtp" "os" "strings" "sync" "time" ) var ( global *Emailer mu sync.RWMutex ) type Emailer struct { mode string filePath string host string port string username string password string } type Email struct { From string To []string Subject string Body string } // Init initializes the global emailer with the provided settings func Init(mode, filePath, host, port, username, password string) error { mu.Lock() defer mu.Unlock() emailer := &Emailer{ mode: mode, filePath: filePath, host: host, port: port, username: username, password: password, } if err := emailer.validate(); err != nil { return err } global = emailer return nil } // Get returns the global emailer instance (thread-safe) func Get() *Emailer { mu.RLock() defer mu.RUnlock() if global == nil { panic("email not initialized - call Init first") } return global } // Send sends an email using the configured method (thread-safe) func Send(email Email) error { emailer := Get() mu.RLock() defer mu.RUnlock() switch emailer.mode { case "file": return emailer.sendToFile(email) case "smtp": return emailer.sendViaSMTP(email) default: return fmt.Errorf("invalid email mode: %s", emailer.mode) } } func (e *Emailer) validate() error { if e.mode != "file" && e.mode != "smtp" { return fmt.Errorf("mode must be 'file' or 'smtp'") } if e.mode == "smtp" { if e.host == "" || e.username == "" || e.password == "" { return fmt.Errorf("smtp mode requires host, username, and password") } } if e.mode == "file" && e.filePath == "" { return fmt.Errorf("file mode requires filePath") } return nil } func (e *Emailer) sendToFile(email Email) error { content := fmt.Sprintf(`--- EMAIL --- Time: %s From: %s To: %s Subject: %s %s --- END EMAIL --- `, time.Now().Format(time.RFC3339), email.From, strings.Join(email.To, ", "), email.Subject, email.Body) f, err := os.OpenFile(e.filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return err } defer f.Close() _, err = f.WriteString(content) return err } func (e *Emailer) sendViaSMTP(email Email) error { auth := smtp.PlainAuth("", e.username, e.password, e.host) msg := fmt.Sprintf("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s", email.From, strings.Join(email.To, ", "), email.Subject, email.Body, ) addr := e.host + ":" + e.port return smtp.SendMail(addr, auth, email.From, email.To, []byte(msg)) }