Skip to content
Snippets Groups Projects
Select Git revision
  • 82eece008c0e648892ef07998c93dd66f32a1bf6
  • master default protected
  • v0.2.2
  • v0.2.1
  • v0.2.0
5 results

target-init-standard.mk

Blame
  • runnable-mail.go 4.19 KiB
    // Copyright 2023 schukai GmbH
    // SPDX-License-Identifier: AGPL-3.0
    
    package jobqueue
    
    import (
    	"context"
    	"fmt"
    	"net/smtp"
    	"sync"
    )
    
    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
    }
    
    func (m *MailResult) GetResult() string {
    	return fmt.Sprintf("Sent: %t\n\nServerReply: %s\n\nSmtpStatusCode: %d", m.Sent, m.ServerReply, m.SmtpStatusCode)
    }
    
    func (m *MailResult) GetError() (string, int) {
    	if !m.Sent {
    		return fmt.Sprintf("Sent: %t\n\nServerReply: %s\n\nSmtpStatusCode: %d", m.Sent, m.ServerReply, m.SmtpStatusCode), 1
    	}
    	return "", 0
    }
    
    type MailRunnable struct {
    	To       string
    	From     string
    	Subject  string
    	Body     string
    	Server   string
    	Port     string
    	Username string
    	Password string
    	Headers  map[string]string
    	mu       sync.Mutex
    }
    
    func (m *MailRunnable) Run(_ context.Context) (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
    }
    
    func (m *MailRunnable) GetType() string {
    	return "mail"
    }
    
    func (m *MailRunnable) GetPersistence() RunnableImport {
    	m.mu.Lock()
    	defer m.mu.Unlock()
    
    	data := JSONMap{
    		"to":       m.To,
    		"from":     m.From,
    		"subject":  m.Subject,
    		"body":     m.Body,
    		"server":   m.Server,
    		"port":     m.Port,
    		"username": m.Username,
    		"password": m.Password,
    		"headers":  m.Headers,
    	}
    
    	return RunnableImport{
    		Type: m.GetType(),
    		Data: data,
    	}
    }