package jobqueue import ( "fmt" "net/smtp" ) func NewMailRunnableFromMap(data map[string]interface{}) (*MailRunnable, error) { to, ok := data["to"].(string) if !ok { return nil, fmt.Errorf("%w: Invalid To: %v", ErrInvalidData, data["to"]) } from, ok := data["from"].(string) if !ok { return nil, fmt.Errorf("%w: Invalid From: %v", ErrInvalidData, data["from"]) } subject, ok := data["subject"].(string) if !ok { return nil, fmt.Errorf("%w: Invalid Subject: %v", ErrInvalidData, data["subject"]) } body, ok := data["l"].(string) if !ok { return nil, fmt.Errorf("%w: Invalid Body: %v", ErrInvalidData, data["body"]) } server, ok := data["server"].(string) if !ok { return nil, fmt.Errorf("%w: Invalid Server: %v", ErrInvalidData, data["server"]) } port, ok := data["port"].(string) if !ok { return nil, fmt.Errorf("%w: Invalid Port: %v", ErrInvalidData, data["port"]) } username, ok := data["username"].(string) if !ok { return nil, fmt.Errorf("%w: Invalid Username: %v", ErrInvalidData, data["username"]) } password, ok := data["password"].(string) if !ok { return nil, fmt.Errorf("%w: Invalid Password: %v", ErrInvalidData, data["password"]) } headers, ok := data["headers"].(map[string]string) if !ok { return nil, fmt.Errorf("%w: Invalid Headers: %v", ErrInvalidData, data["headers"]) } return &MailRunnable{ To: to, From: from, Subject: subject, Body: body, Server: server, Port: port, Username: username, Password: password, Headers: headers, }, nil } // MailResult is a result of a email type MailResult struct { Sent bool ServerReply string SmtpStatusCode uint } type MailRunnable struct { To string From string Subject string Body string Server string Port string Username string Password string Headers map[string]string } func (m *MailRunnable) Run() (RunResult[MailResult], error) { smtpServer := m.Server + ":" + m.Port // Connect to the remote SMTP server. client, err := smtp.Dial(smtpServer) if err != nil { return RunResult[MailResult]{Status: ResultStatusFailed}, err } if client != nil { defer client.Close() } if m.Username != "" && m.Password != "" { if err := client.Auth(smtp.PlainAuth("", m.Username, m.Password, m.Server)); err != nil { return RunResult[MailResult]{Status: ResultStatusFailed}, err } } // To && From. if err := client.Mail(m.From); err != nil { return RunResult[MailResult]{Status: ResultStatusFailed}, err } if err := client.Rcpt(m.To); err != nil { return RunResult[MailResult]{Status: ResultStatusFailed}, err } // Headers and Data. writer, err := client.Data() if err != nil { return RunResult[MailResult]{Status: ResultStatusFailed}, err } headers := "From: " + m.From + "\r\n" headers += "To: " + m.To + "\r\n" headers += "Subject: " + m.Subject + "\r\n" for key, value := range m.Headers { headers += key + ": " + value + "\r\n" } _, err = writer.Write([]byte(headers + "\r\n" + m.Body)) if err != nil { return RunResult[MailResult]{Status: ResultStatusFailed}, err } _ = writer.Close() // Quit and get the SMTP status code. smtpStatusCode, _ := client.Text.Cmd("QUIT") return RunResult[MailResult]{Status: ResultStatusSuccess, Data: MailResult{Sent: true, SmtpStatusCode: smtpStatusCode}}, nil }