Documentation ¶
Overview ¶
Package msmtpd is framework for building Enchanced/Simple Mail Transfer Protocol daemons including inbound, outbound servers, smtp proxies, spamtraps, honeypots and everything that talks SMTP
Example ¶
// set main server context ctx, cancel := context.WithCancel(context.TODO()) defer cancel() // configure logger logger := DefaultLogger{ Logger: log.Default(), Level: TraceLevel, } // configure server server := Server{ Hostname: "mx.example.org", WelcomeMessage: "mx.example.org ESMTP ready.", // limits ReadTimeout: time.Minute, WriteTimeout: time.Minute, DataTimeout: 3 * time.Minute, MaxConnections: 10, MaxMessageSize: 32 * 1024 * 1014, // 32 Mbytes MaxRecipients: 10, // you can configure DNS resolver being used for application Resolver: net.DefaultResolver, // can make things faster, but various HELO/EHLO checks will not work SkipResolvingPTR: false, // enable xclient extension, use with care! https://www.postfix.org/XCLIENT_README.html EnableXCLIENT: false, // enable proxy support, like Haraka allows for HaProxy https://haraka.github.io/core/HAProxy EnableProxyProtocol: false, // if you plan to make server listen TLS or use StartTLS command, here // you can configure it and require all sensitive data to be transferred via // encrypted channel TLSConfig: nil, ForceTLS: false, // plug your custom logger here Logger: &logger, // main context of server and its cancel function Context: ctx, Cancel: cancel, // ConnectionCheckers are called when client performed TCP connection ConnectionCheckers: []ConnectionChecker{ func(tr *Transaction) error { tr.LogInfo("Client connects from %s...", tr.Addr.String()) return nil }, }, // HeloCheckers are called when client tries to perform HELO/EHLO HeloCheckers: []HelloChecker{ func(tr *Transaction) error { tr.LogInfo("Client HELO is %s", tr.HeloName) return nil }, func(tr *Transaction) error { if tr.HeloName != "localhost" { tr.Hate(1) // i do not like being irritated } else { tr.SetFlag("localhost") } return nil }, }, // SenderCheckers are called when client provides MAIL FROM to define who sends email message SenderCheckers: []SenderChecker{ func(tr *Transaction) error { tr.LogInfo("Somebody called %s tries to send message...", tr.MailFrom) return nil }, }, // RecipientCheckers are called each time client provides RCPT TO // in order to define for whom to send email message RecipientCheckers: []RecipientChecker{ func(tr *Transaction, recipient *mail.Address) error { if strings.HasPrefix(recipient.Address, "info@") { return ErrorSMTP{ Code: 535, Message: "Just stop it, please", } } return nil }, }, // DataCheckers are called on message body to ensure it is properly formatted ham email // message according to RFC 5322 and RFC 6532. DataCheckers: []DataChecker{ func(tr *Transaction) error { if tr.Parsed.Header.Get("X-Priority") == "" { return ErrorSMTP{ Code: 535, Message: "Please, provide priority for your message!", } } // Add header to message tr.AddHeader("Something", "interesting") return nil }, }, // DataHandlers do actual message delivery to persistent storage DataHandlers: []DataHandler{ func(tr *Transaction) error { tr.LogInfo("We pretend we deliver %v bytes of message somehow", len(tr.Body)) // set float64 fact about transaction tr.Incr("size", float64(len(tr.Body))) return ErrServiceNotAvailable }, }, // CloseHandlers are called when client closes connection, they can be used // to, for example, record connection data in database or save metrics CloseHandlers: []CloseHandler{ func(tr *Transaction) error { tr.LogInfo("Closing connection. Karma is %d", tr.Karma()) // reading string fact subject, found := tr.GetFact(SubjectFact) if found { tr.LogInfo("Subject %s", subject) } // reading float64 counter size, found := tr.GetCounter("size") if found { tr.LogInfo("Body size is %v", size) } // reading boolean flag present if tr.IsFlagSet("localhost") { tr.LogInfo("Transaction is send from localhost") } return nil // error means nothing here, to be honest }, }, } // start http endpoint for metrics scrapping. // Format explained here: https://prometheus.io/docs/instrumenting/exposition_formats/ go func() { pmErr := server.StartPrometheusScrapperEndpoint(":3000", "/metrics") if pmErr != nil { log.Fatalf("%s : while starting metrics scrapper endpoint", pmErr) } }() // Actually, start server on 25th port err := server.ListenAndServe(":25") if err != nil { log.Fatalf("%s : while starting server on %s", err, server.Address()) }
Output:
Index ¶
- Constants
- Variables
- func AuthenticatorForTestsThatAlwaysFails(tr *Transaction, username, password string) error
- func AuthenticatorForTestsThatAlwaysWorks(tr *Transaction, username, password string) error
- func RunTestServerWithTLS(t *testing.T, server *Server) (addr string, closer func())
- func RunTestServerWithoutTLS(t *testing.T, server *Server) (addr string, closer func())
- type AuthenticatorFunc
- type CheckerFunc
- type CloseHandler
- type ConnectionChecker
- type DataChecker
- type DataHandler
- type DefaultLogger
- func (d *DefaultLogger) Debugf(transaction *Transaction, format string, args ...any)
- func (d *DefaultLogger) Errorf(transaction *Transaction, format string, args ...any)
- func (d *DefaultLogger) Fatalf(transaction *Transaction, format string, args ...any)
- func (d *DefaultLogger) Infof(transaction *Transaction, format string, args ...any)
- func (d *DefaultLogger) Tracef(transaction *Transaction, format string, args ...any)
- func (d *DefaultLogger) Warnf(transaction *Transaction, format string, args ...any)
- type ErrorSMTP
- type HelloChecker
- type Logger
- type LoggerLevel
- type Protocol
- type RecipientChecker
- type SenderChecker
- type Server
- func (srv *Server) Address() net.Addr
- func (srv *Server) GetActiveTransactionsCount() int32
- func (srv *Server) GetBytesRead() uint64
- func (srv *Server) GetBytesWritten() uint64
- func (srv *Server) GetFailedTransactionsCount() uint64
- func (srv *Server) GetSuccessfulTransactionsCount() uint64
- func (srv *Server) GetTransactionsCount() uint64
- func (srv *Server) ListenAndServe(addr string) error
- func (srv *Server) ResetCounters()
- func (srv *Server) Serve(l net.Listener) error
- func (srv *Server) Shutdown(wait bool) error
- func (srv *Server) StartPrometheusScrapperEndpoint(address, path string) (err error)
- func (srv *Server) Wait() error
- type TestLogger
- func (tl *TestLogger) Debugf(transaction *Transaction, format string, args ...any)
- func (tl *TestLogger) Errorf(transaction *Transaction, format string, args ...any)
- func (tl *TestLogger) Fatalf(transaction *Transaction, format string, args ...any)
- func (tl *TestLogger) Infof(transaction *Transaction, format string, args ...any)
- func (tl *TestLogger) Tracef(transaction *Transaction, format string, args ...any)
- func (tl *TestLogger) Warnf(transaction *Transaction, format string, args ...any)
- type Transaction
- func (t *Transaction) AddHeader(name, value string)
- func (t *Transaction) AddReceivedLine()
- func (t *Transaction) Context() context.Context
- func (t *Transaction) GetCounter(key string) (val float64, found bool)
- func (t *Transaction) GetFact(name string) (value string, found bool)
- func (t *Transaction) Hate(delta int) (newVal int)
- func (t *Transaction) Incr(key string, delta float64) (newVal float64)
- func (t *Transaction) IsFlagSet(name string) bool
- func (t *Transaction) Karma() int
- func (t *Transaction) LogDebug(format string, args ...any)
- func (t *Transaction) LogError(err error, desc string)
- func (t *Transaction) LogFatal(err error, desc string)
- func (t *Transaction) LogInfo(format string, args ...any)
- func (t *Transaction) LogTrace(format string, args ...any)
- func (t *Transaction) LogWarn(format string, args ...any)
- func (t *Transaction) Love(delta int) (newVal int)
- func (t *Transaction) Resolver() *net.Resolver
- func (t *Transaction) SetFact(name, value string)
- func (t *Transaction) SetFlag(name string)
- func (t *Transaction) UnsetFlag(name string)
Examples ¶
Constants ¶
const SubjectFact = "subject"
SubjectFact is default name for fact key to store message Subject as string
Variables ¶
var ErrAuthenticationCredentialsInvalid = ErrorSMTP{
Code: 535,
Message: "Authentication credentials are invalid.",
}
ErrAuthenticationCredentialsInvalid means SMTP credentials are invalid
var ErrServerClosed = errors.New("smtp: Server closed")
ErrServerClosed is returned by the Server's Serve and ListenAndServe, methods after a call to shut down.
var ErrServiceDoesNotAcceptEmail = ErrorSMTP{
Code: 521,
Message: "Server does not accept mail. Do not retry delivery, please. It will fail.",
}
ErrServiceDoesNotAcceptEmail means server will not perform this SMTP transaction, even if your try to retry it
var ErrServiceNotAvailable = ErrorSMTP{
Code: 421,
Message: "Service not available. Try again later, please.",
}
ErrServiceNotAvailable means server cannot perform this SMTP transaction and it should be retried later
var TLSVersions = map[uint16]string{ tls.VersionSSL30: "SSL3.0", tls.VersionTLS10: "TLS1.0", tls.VersionTLS11: "TLS1.1", tls.VersionTLS12: "TLS1.2", tls.VersionTLS13: "TLS1.3", }
TLSVersions is used to pretty print TLS protocol version being used
Functions ¶
func AuthenticatorForTestsThatAlwaysFails ¶
func AuthenticatorForTestsThatAlwaysFails(tr *Transaction, username, password string) error
AuthenticatorForTestsThatAlwaysFails should not be used for production
func AuthenticatorForTestsThatAlwaysWorks ¶
func AuthenticatorForTestsThatAlwaysWorks(tr *Transaction, username, password string) error
AuthenticatorForTestsThatAlwaysWorks should not be used for production
func RunTestServerWithTLS ¶
RunTestServerWithTLS runs test server for unit tests with TLS support and cert for localhost
Types ¶
type AuthenticatorFunc ¶
type AuthenticatorFunc func(transaction *Transaction, username, password string) error
AuthenticatorFunc is signature of function used to handle authentication
type CheckerFunc ¶
type CheckerFunc func(transaction *Transaction) error
CheckerFunc are signature of functions used in checks for client issuing HELO/EHLO, MAIL FROM, DATA commands Note that we can store counters and Facts in Transaction, in order to extract and reuse it in the future.
type CloseHandler ¶
type CloseHandler CheckerFunc
CloseHandler is called when server terminates SMTP session, it can be used for, for example, storing Karma or reporting statistics
type ConnectionChecker ¶
type ConnectionChecker CheckerFunc
ConnectionChecker are called when tcp connection are established, if they return non-null error, connection is terminated
type DataChecker ¶
type DataChecker CheckerFunc
DataChecker is called when client provided message body, and we need to ensure it is sane. It is good place to use RSPAMD and other message body validators here
type DataHandler ¶
type DataHandler CheckerFunc
DataHandler is called when client provided message body, it was checked by all DataChecker functions, and we need to deliver message to LMTP or 3rd party SMTP server.
type DefaultLogger ¶
type DefaultLogger struct { *log.Logger Level LoggerLevel }
DefaultLogger is logger by default using standard library logger as backend https://pkg.go.dev/log
func (*DefaultLogger) Debugf ¶
func (d *DefaultLogger) Debugf(transaction *Transaction, format string, args ...any)
Debugf sends DebugLevel message
func (*DefaultLogger) Errorf ¶
func (d *DefaultLogger) Errorf(transaction *Transaction, format string, args ...any)
Errorf sends ErrorLevel message
func (*DefaultLogger) Fatalf ¶
func (d *DefaultLogger) Fatalf(transaction *Transaction, format string, args ...any)
Fatalf sends FatalLevel message and stops application with exit code 1
func (*DefaultLogger) Infof ¶
func (d *DefaultLogger) Infof(transaction *Transaction, format string, args ...any)
Infof sends InfoLevel message
func (*DefaultLogger) Tracef ¶
func (d *DefaultLogger) Tracef(transaction *Transaction, format string, args ...any)
Tracef sends TraceLevel message
func (*DefaultLogger) Warnf ¶
func (d *DefaultLogger) Warnf(transaction *Transaction, format string, args ...any)
Warnf sends WarnLevel message
type HelloChecker ¶
type HelloChecker CheckerFunc
HelloChecker is called after client provided HELO/EHLO greeting, returned errors are send to client as ErrorSMTP responses
type Logger ¶
type Logger interface { Tracef(transaction *Transaction, format string, args ...any) Debugf(transaction *Transaction, format string, args ...any) Infof(transaction *Transaction, format string, args ...any) Warnf(transaction *Transaction, format string, args ...any) Errorf(transaction *Transaction, format string, args ...any) Fatalf(transaction *Transaction, format string, args ...any) }
Logger is interface all Server loggers must satisfy
type LoggerLevel ¶
type LoggerLevel uint8
LoggerLevel describes logging level like JournalD has by https://github.com/coreos/go-systemd/blob/main/journal/journal.go See for inspiration https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
const DebugLevel LoggerLevel = 7
DebugLevel is used when we log information that is diagnostically helpful to people more than just developers (IT, sysadmins, etc.).
const ErrorLevel LoggerLevel = 3
ErrorLevel is used for any error which is fatal to the operation, but not the service or application (can't open a required file, missing data, etc.). These errors will force user (administrator, or direct user) intervention.
const FatalLevel LoggerLevel = 2
FatalLevel is used for any error that is forcing a shutdown of the service or application to prevent data loss (or further data loss).
const InfoLevel LoggerLevel = 6
InfoLevel is used when we log generally useful information to log (service start/stop, configuration assumptions, etc). This is information we always want to be available but we usually don't care about under normal circumstances. This is my out-of-the-box config level.
const TraceLevel LoggerLevel = 8
TraceLevel is used when we record very verbose message like SMTP protocol raw data being sent/received
const WarnLevel LoggerLevel = 4
WarnLevel is used when we log anything that can potentially cause application oddities, but for which we are automatically recovering. Such as switching from a primary to backup server, retrying an operation, missing secondary data, etc.
func (LoggerLevel) String ¶
func (ll LoggerLevel) String() string
type RecipientChecker ¶
type RecipientChecker func(transaction *Transaction, recipient *mail.Address) error
RecipientChecker is called for each RCPT TO client provided, if they return null error, recipient is added to Transaction.RcptTo, else returned errors are send to client as ErrorSMTP responses
type SenderChecker ¶
type SenderChecker CheckerFunc
SenderChecker is called after client provided MAIL FROM, returned errors are send // to client as ErrorSMTP responses
type Server ¶
type Server struct { // Hostname is how we name ourselves, default is "localhost.localdomain" Hostname string // WelcomeMessage sets initial server banner. (default: "<hostname> ESMTP ready.") WelcomeMessage string // ReadTimeout is socket timeout for read operations. (default: 60s) ReadTimeout time.Duration // WriteTimeout is socket timeout for write operations. (default: 60s) WriteTimeout time.Duration // DataTimeout Socket timeout for DATA command (default: 5m) DataTimeout time.Duration // MaxConnections sets maximum number of concurrent connections, use -1 to disable. (default: 100) MaxConnections int // MaxMessageSize, default is 10240000 bytes MaxMessageSize int // MaxRecipients are limit for RCPT TO calls for each envelope. (default: 100) MaxRecipients int // Resolver is net.Resolver used by server and plugins to resolve remote resources against DNS servers Resolver *net.Resolver // SkipResolvingPTR disables resolving reverse/point DNS records of connecting IP address, // it can be useful in various DNS checks, but it reduces performance due to quite // expensive and slow DNS calls. By default resolving PTR records is enabled SkipResolvingPTR bool // ConnectionCheckers are called when TCP connection is started, if any of connection // checkers returns error, connection is closed, which is reported as ErrorSMTP being send to // client before connection is terminated ConnectionCheckers []ConnectionChecker // HeloCheckers are called after client send HELO/EHLO commands // If any of HeloCheckers returns error, it will be reported as HELO/EHLO command response, // and HELO command will be considered erroneous. HeloCheckers []HelloChecker // SenderCheckers are called when client issues MAIL FROM command // If any of SenderCheckers returns error, it will be reported as MAIL FROM command response, // and command will be considered erroneous. SenderCheckers []SenderChecker // RecipientCheckers are called every time client issues RCPT TO command // 1st argument is Transaction, 2nd one - RCPT TO payload // If any of RecipientCheckers returns error, it will be reported as RCPT TO command response // and command will be considered erroneous. RecipientCheckers []RecipientChecker // Authenticator, while being not nil, enables PLAIN/LOGIN authentication, // only available after STARTTLS. Variable can be left empty for no authentication support. // If Authenticator returns error, authentication will be considered erroneous. Authenticator func(transaction *Transaction, username, password string) error // DataCheckers are functions called to check message body before passing it // to DataHandlers for delivery. If left empty, body is not checked. It is worth // mentioning that message body is parsed according to RFC 5322 to ensure mandatory // headers From and Date are present, and important ones do not have duplicates. // If any of data checkers returns error, it will be reported as DATA // command response and command will be considered erroneous. DataCheckers []DataChecker // DataHandlers are functions to process message body after DATA command. // Can be left empty for a NOOP server. // If any of DataHandlers returns error, it will be reported as DATA // command response and command will be considered erroneous. DataHandlers []DataHandler // CloseHandlers are called after connection is closed. They can be used to, for example, // update counters, save connection metadata into persistent storage like Karma plugin does, // or it can even issue shell command to blacklist remote IP by firewall CloseHandlers []CloseHandler // EnableXCLIENT enables XClient command support (disabled by default, since it is security risk) EnableXCLIENT bool // EnableProxyProtocol enables Proxy command support (disabled by default, since it is security risk) EnableProxyProtocol bool // HideTransactionHeader hides transaction header HideTransactionHeader bool // TLSConfig is used both for STARTTLS and operation over TLS channel TLSConfig *tls.Config // ForceTLS requires connections to be encrypted ForceTLS bool // Logger is interface being used as protocol/plugin/errors logger Logger Logger // Tracer is OpenTelemetry tracer which starts spans for every Transaction Tracer trace.Tracer // Context is main context in which server is started Context context.Context // Cancel cancels main server Context Cancel context.CancelFunc // contains filtered or unexported fields }
Server defines the parameters for running the SMTP server
func (*Server) GetActiveTransactionsCount ¶
GetActiveTransactionsCount returns number of active transactions this server is processing
func (*Server) GetBytesRead ¶
GetBytesRead returns number of bytes written
func (*Server) GetBytesWritten ¶
GetBytesWritten returns number of bytes written
func (*Server) GetFailedTransactionsCount ¶ added in v1.1.0
GetFailedTransactionsCount returns number of failed transactions this server processed
func (*Server) GetSuccessfulTransactionsCount ¶ added in v1.1.0
GetSuccessfulTransactionsCount returns number of successful transactions this server processed
func (*Server) GetTransactionsCount ¶
GetTransactionsCount returns number of all transactions this server processed
func (*Server) ListenAndServe ¶
ListenAndServe starts the SMTP server and listens on the address provided
func (*Server) Shutdown ¶
Shutdown instructs the server to shut down, starting by closing the associated listener. If wait is true, it will wait for the shutdown to complete. If wait is false, Wait must be called afterwards.
func (*Server) StartPrometheusScrapperEndpoint ¶
StartPrometheusScrapperEndpoint starts prometheus scrapper endpoint with data in this format https://prometheus.io/docs/instrumenting/exposition_formats/
type TestLogger ¶
TestLogger is logger being used only in unit tests
func (*TestLogger) Debugf ¶
func (tl *TestLogger) Debugf(transaction *Transaction, format string, args ...any)
Debugf records debug level message
func (*TestLogger) Errorf ¶
func (tl *TestLogger) Errorf(transaction *Transaction, format string, args ...any)
Errorf records error level message
func (*TestLogger) Fatalf ¶
func (tl *TestLogger) Fatalf(transaction *Transaction, format string, args ...any)
Fatalf records fatal level message and fails test
func (*TestLogger) Infof ¶
func (tl *TestLogger) Infof(transaction *Transaction, format string, args ...any)
Infof records info level message
func (*TestLogger) Tracef ¶
func (tl *TestLogger) Tracef(transaction *Transaction, format string, args ...any)
Tracef records trace level message
func (*TestLogger) Warnf ¶
func (tl *TestLogger) Warnf(transaction *Transaction, format string, args ...any)
Warnf records warning level message
type Transaction ¶
type Transaction struct { // ID is unique transaction identificator ID string `json:"id"` // StartedAt depicts moment when transaction was initiated StartedAt time.Time // ServerName depicts how out smtp server names itself ServerName string // Addr depicts network address of remote client Addr net.Addr // PTRs are DNS PTR record is exactly the opposite of the 'A' record, which provides the IP address associated with a // domain name. PTRs []string // TLS Connection details, if encryption is enabled // Ptrs are DNS pointer record which provides the domain name associated with an IP address. TLS *tls.ConnectionState // Encrypted means connection is encrypted by TLS Encrypted bool // Secured means TLS handshake succeeded Secured bool // Logger is logging system inherited from server Logger Logger // HeloName is how client introduced himself via HELO/EHLO command HeloName string // Protocol used, SMTP or ESMTP Protocol Protocol // Username as provided by via authorization process command Username string // Password from authentication, if authenticated Password string // MailFrom stores address from which this message is originated as client says via `MAIL FROM:` MailFrom mail.Address // RcptTo stores addresses for which this message should be delivered as client says via `RCPT TO:` RcptTo []mail.Address // Body stores unparsed message body Body []byte // Parsed stores parsed message body Parsed *mail.Message // Aliases are actual users addresses used by delivery plugins Aliases []mail.Address // Span is OpenTelemetry span being used in transaction Span trace.Span // contains filtered or unexported fields }
Transaction used to handle all SMTP protocol interactions with client
func (*Transaction) AddHeader ¶
func (t *Transaction) AddHeader(name, value string)
AddHeader adds header to the Transaction.Parsed, and to the Transaction.Body, so, it should be called before AddReceivedLine, since it adds header to the top
func (*Transaction) AddReceivedLine ¶
func (t *Transaction) AddReceivedLine()
AddReceivedLine prepends a Received header to the Transaction.Body
func (*Transaction) Context ¶
func (t *Transaction) Context() context.Context
Context returns transaction context, which is canceled when transaction is closed
func (*Transaction) GetCounter ¶
func (t *Transaction) GetCounter(key string) (val float64, found bool)
GetCounter returns counter value
func (*Transaction) GetFact ¶
func (t *Transaction) GetFact(name string) (value string, found bool)
GetFact returns string fact from Transaction.facts
func (*Transaction) Hate ¶
func (t *Transaction) Hate(delta int) (newVal int)
Hate grants bad points to karma, restricting message to enter Paradise for SMTP transactions, aka dovecot server socket for accepting messages via SMTP
func (*Transaction) Incr ¶
func (t *Transaction) Incr(key string, delta float64) (newVal float64)
Incr increments transaction counter
func (*Transaction) IsFlagSet ¶
func (t *Transaction) IsFlagSet(name string) bool
IsFlagSet returns true, if flag is set
func (*Transaction) Karma ¶
func (t *Transaction) Karma() int
Karma returns current transaction karma
func (*Transaction) LogDebug ¶
func (t *Transaction) LogDebug(format string, args ...any)
LogDebug is used to send debug level message to server logger
func (*Transaction) LogError ¶
func (t *Transaction) LogError(err error, desc string)
LogError is used to send error level message to server logger. This function marks OpenTelemetry Transaction's span as erroneous one
func (*Transaction) LogFatal ¶
func (t *Transaction) LogFatal(err error, desc string)
LogFatal is used to send error level message to server logger
func (*Transaction) LogInfo ¶
func (t *Transaction) LogInfo(format string, args ...any)
LogInfo is used to send info level message to server logger
func (*Transaction) LogTrace ¶
func (t *Transaction) LogTrace(format string, args ...any)
LogTrace is used to send trace level message to server logger
func (*Transaction) LogWarn ¶
func (t *Transaction) LogWarn(format string, args ...any)
LogWarn is used to send warning level message to server logger
func (*Transaction) Love ¶
func (t *Transaction) Love(delta int) (newVal int)
Love grants good points to karma, promising message to enter Paradise for SMTP transactions, aka dovecot server socket for accepting messages via SMTP
func (*Transaction) Resolver ¶
func (t *Transaction) Resolver() *net.Resolver
Resolver returns net.Resolver being used for this transaction
func (*Transaction) SetFact ¶
func (t *Transaction) SetFact(name, value string)
SetFact sets string parameter Transaction.facts
func (*Transaction) SetFlag ¶
func (t *Transaction) SetFlag(name string)
SetFlag set flag enabled for transaction
func (*Transaction) UnsetFlag ¶
func (t *Transaction) UnsetFlag(name string)
UnsetFlag unsets boolean flag from transaction
Source Files ¶
- address.go
- command.go
- constants.go
- doc.go
- error.go
- helpers.go
- logger.go
- server.go
- server_counters.go
- test_helpers.go
- transaction.go
- transaction_auth.go
- transaction_data.go
- transaction_handler.go
- transaction_headers.go
- transaction_helo.go
- transaction_io.go
- transaction_logging.go
- transaction_mailfrom.go
- transaction_proxy.go
- transaction_rcpt_to.go
- transaction_resolver.go
- transaction_startTLS.go
- transaction_xclient.go