129 lines
4.7 KiB
Go
129 lines
4.7 KiB
Go
// SPDX-FileCopyrightText: Copyright (c) The go-mail Authors
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package smtp
|
|
|
|
import (
|
|
"net/textproto"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
// ResponseErrorHandler provides custom handling for SMTP response errors.
|
|
//
|
|
// This interface defines a method for handling SMTP responses that do not comply with expected
|
|
// formats or behaviors. It is useful for implementing retry logic, logging, or protocol-specific
|
|
// error handling logic. It injects itself into the smtp.Client and is called whenever a server
|
|
// response does fail.
|
|
//
|
|
// Parameters:
|
|
// - host: The hostname of the SMTP server that this ResponseErrorHandler should handle
|
|
// - command: The SMTP command that triggered the error.
|
|
// - conn: The textproto.Conn to the SMTP server.
|
|
// - err: The error received from the SMTP server.
|
|
//
|
|
// Returns:
|
|
// - An error indicating the outcome of the error handling logic.
|
|
type ResponseErrorHandler interface {
|
|
HandleError(host, command string, conn *textproto.Conn, err error) error
|
|
}
|
|
|
|
// DefaultErrorHandler implements ResponseErrorHandler by returning the original error.
|
|
//
|
|
// This handler provides a default implementation of the ResponseErrorHandler interface,
|
|
// where no custom error processing is performed. It simply returns the original error
|
|
// received from the SMTP server.
|
|
//
|
|
// Returns:
|
|
// - The original error passed to the handler.
|
|
type DefaultErrorHandler struct{}
|
|
|
|
// HandleError satisfies the ResponseErrorHandler interface for the DefaultErrorHandler type
|
|
func (d *DefaultErrorHandler) HandleError(_, _ string, _ *textproto.Conn, err error) error {
|
|
return err
|
|
}
|
|
|
|
// HandlerKey uniquely identifies a host-command pair for handler mapping.
|
|
//
|
|
// This struct is used to associate a specific SMTP host and command combination with
|
|
// a ResponseErrorHandler. It enables mapping and retrieval of handlers based on
|
|
// the source of the error.
|
|
type HandlerKey struct {
|
|
Host string
|
|
Command string
|
|
}
|
|
|
|
// ErrorHandlerRegistry manages custom error handlers for SMTP host-command pairs.
|
|
//
|
|
// This struct stores mappings between HandlerKey values and corresponding
|
|
// ResponseErrorHandler implementations. It supports concurrent access and provides
|
|
// a fallback default handler when no specific match is found.
|
|
type ErrorHandlerRegistry struct {
|
|
mu sync.RWMutex
|
|
handlers map[HandlerKey]ResponseErrorHandler
|
|
defaultHandler ResponseErrorHandler
|
|
}
|
|
|
|
// NewErrorHandlerRegistry creates a new ErrorHandlerRegistry instance.
|
|
//
|
|
// This function initializes an ErrorHandlerRegistry with an empty handler map and
|
|
// assigns a DefaultErrorHandler as the fallback handler.
|
|
//
|
|
// Returns:
|
|
// - A pointer to the newly constructed ErrorHandlerRegistry.
|
|
func NewErrorHandlerRegistry() *ErrorHandlerRegistry {
|
|
return &ErrorHandlerRegistry{
|
|
handlers: make(map[HandlerKey]ResponseErrorHandler),
|
|
defaultHandler: &DefaultErrorHandler{}, // Set the default handler
|
|
}
|
|
}
|
|
|
|
// RegisterHandler associates a custom handler with a specific host and command.
|
|
//
|
|
// This method registers a ResponseErrorHandler for the given SMTP host and command
|
|
// combination. It ensures thread-safe access to the internal handler map.
|
|
//
|
|
// Parameters:
|
|
// - host: The SMTP server hostname.
|
|
// - command: The SMTP command to associate with the handler.
|
|
// - handler: The ResponseErrorHandler to register.
|
|
func (r *ErrorHandlerRegistry) RegisterHandler(host, command string, handler ResponseErrorHandler) {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
r.handlers[HandlerKey{Host: strings.ToLower(host), Command: strings.ToLower(command)}] = handler
|
|
}
|
|
|
|
// GetHandler retrieves the handler for a given host and command.
|
|
//
|
|
// This method returns the ResponseErrorHandler registered for the specified SMTP host
|
|
// and command. If no handler is found, it returns the default handler.
|
|
//
|
|
// Parameters:
|
|
// - host: The SMTP server hostname.
|
|
// - command: The SMTP command to look up.
|
|
//
|
|
// Returns:
|
|
// - The corresponding ResponseErrorHandler, or the default handler if none is registered.
|
|
func (r *ErrorHandlerRegistry) GetHandler(host, command string) ResponseErrorHandler {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
if handler, ok := r.handlers[HandlerKey{Host: strings.ToLower(host), Command: strings.ToLower(command)}]; ok {
|
|
return handler
|
|
}
|
|
return r.defaultHandler
|
|
}
|
|
|
|
// SetDefaultHandler overrides the default ResponseErrorHandler.
|
|
//
|
|
// This method sets a new default handler to be used when no specific handler is
|
|
// registered for a host and command combination. It ensures thread-safe access.
|
|
//
|
|
// Parameters:
|
|
// - handler: The new default ResponseErrorHandler to assign.
|
|
func (r *ErrorHandlerRegistry) SetDefaultHandler(handler ResponseErrorHandler) {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
r.defaultHandler = handler
|
|
}
|