Documentation ¶
Index ¶
- Constants
- Variables
- func ParseAuthPlainInitialRespone(initialResponse string) (authorizationIdentity string, authenticationIdenity string, password string, ...)
- func ReadUntill(delim byte, max int, r io.Reader) ([]byte, error)
- func SkipTillNewline(r io.Reader) error
- type Answer
- type Argument
- type AuthCmd
- type Cmd
- type DataCmd
- type DataReader
- type EhloCmd
- type ExpnCmd
- type HeloCmd
- type Id
- type InvalidCmd
- type MailAddress
- type MailCmd
- type MailMessage
- type MtaProtocol
- type MultiAnswer
- type NoopCmd
- type Protocol
- type QuitCmd
- type RcptCmd
- type RsetCmd
- type SMTPError
- type SamlCmd
- type SendCmd
- type SomlCmd
- type StartTlsCmd
- type State
- type StatusCode
- type UnknownCmd
- type User
- type VrfyCmd
Constants ¶
const ( MAX_DATA_LINE = 1000 MAX_CMD_LINE = 512 )
Variables ¶
var ( // 4yz Transient Negative Completion reply // The command was not accepted, and the requested action did not // occur. However, the error condition is temporary, and the action // may be requested again. The sender should return to the beginning // of the command sequence (if any). It is difficult to assign a // meaning to "transient" when two different sites (receiver- and // sender-SMTP agents) must agree on the interpretation. Each reply // in this category might have a different time value, but the SMTP // client SHOULD try again. A rule of thumb to determine whether a // reply fits into the 4yz or the 5yz category (see below) is that // replies are 4yz if they can be successful if repeated without any // change in command form or in properties of the sender or receiver // (that is, the command is repeated identically and the receiver // does not put up a new implementation). SMTPErrorTransientServiceNotAvailable = SMTPError{Status: 421, Message: "Service not available, closing transmission channel"} SMTPErrorTransientMailboxNotAvailable = SMTPError{Status: 450, Message: "Requested mail action not taken: mailbox unavailable"} SMTPErrorTransientLocalError = SMTPError{Status: 451, Message: "Requested action aborted: local error in processing"} SMTPErrorTransientInsufficientSystemStorage = SMTPError{Status: 452, Message: "Requested action not taken: insufficient system storage"} SMTPErrorTransientUnableToAccommodateParameters = SMTPError{Status: 455, Message: "Server unable to accommodate parameters"} // 5yz Permanent Negative Completion reply // The command was not accepted and the requested action did not // occur. The SMTP client SHOULD NOT repeat the exact request (in // the same sequence). Even some "permanent" error conditions can be // corrected, so the human user may want to direct the SMTP client to // reinitiate the command sequence by direct action at some point in // the future (e.g., after the spelling has been changed, or the user // has altered the account status). SMTPErrorPermanentSyntaxError = SMTPError{Status: 500, Message: "Syntax error, command unrecognized"} SMTPErrorPermanentSyntaxErrorInParameters = SMTPError{Status: 501, Message: "Syntax error in parameters or arguments"} SMTPErrorPermanentCommandNotImplemented = SMTPError{Status: 502, Message: "Command not implemented"} SMTPErrorPermanentBadSequence = SMTPError{Status: 503, Message: "Bad sequence of commands"} SMTPErrorPermanentParameterNotImplemented = SMTPError{Status: 504, Message: "Command parameter not implemented"} SMTPErrorPermanentMailboxNotAvailable = SMTPError{Status: 550, Message: "Requested action not taken: mailbox unavailable"} SMTPErrorPermanentUserNotLocal = SMTPError{Status: 551, Message: "User not local"} SMTPErrorPermanentExceededStorage = SMTPError{Status: 552, Message: "Requested mail action aborted: exceeded storage allocation"} SMTPErrorPermanentMailboxNameNotAllowed = SMTPError{Status: 553, Message: "Requested action not taken: mailbox name not allowed"} SMTPErrorPermanentTransactionFailed = SMTPError{Status: 554, Message: "Transaction failed"} SMTPErrorMailParametersNotImplemented = SMTPError{Status: 555, Message: "MAIL FROM/RCPT TO parameters not recognized or not implemented"} )
var ErrIncomplete = errors.New("Incomplete data")
ErrIncomplete Incomplete data error
var ErrLtl = errors.New("Line too long")
ErrLtl Line too long error
Functions ¶
func ParseAuthPlainInitialRespone ¶
func ParseAuthPlainInitialRespone(initialResponse string) (authorizationIdentity string, authenticationIdenity string, password string, err error)
ParseAuthPlainInitialRespone parses the base64 encoded initial response of an Auth PLAIN request
"The mechanism consists of a single message from the client to the server. The client sends the authorization identity (identity to login as), followed by a US-ASCII NulL character, followed by the authentication identity (identity whose password will be used), followed by a US-ASCII NulL character, followed by the clear-text password. The client may leave the authorization identity empty to indicate that it is the same as the authentication identity."
func ReadUntill ¶
ReadUntill reads untill delim is found or max bytes are read. If delim was found it returns nil as error. If delim wasn't found after max bytes, it returns ErrLtl.
func SkipTillNewline ¶
SkipTillNewline removes all data untill a newline is found.
Types ¶
type Answer ¶
type Answer struct { Status StatusCode Message string }
Answer A raw SMTP answer. Used to send a status code + message.
type DataCmd ¶
type DataCmd struct { Data []byte R DataReader }
type DataReader ¶
type DataReader struct {
// contains filtered or unexported fields
}
DataReader implements the reader that will read the data from a MAIL cmd
func NewDataReader ¶
func NewDataReader(br *bufio.Reader) *DataReader
type InvalidCmd ¶
InvalidCmd is a known command with invalid arguments or syntax
func (InvalidCmd) String ¶
func (c InvalidCmd) String() string
type MailAddress ¶
func ParseAddress ¶
func ParseAddress(rawAddress string) (MailAddress, error)
ParseAddress parses a string into a MailAddress.
func (*MailAddress) GetAddress ¶
func (address *MailAddress) GetAddress() string
GetAddress gets the full mail address.
func (*MailAddress) GetDomain ¶
func (address *MailAddress) GetDomain() string
GetDomain gets the domain part of a mail address. E.g the part after the @.
func (*MailAddress) GetLocal ¶
func (address *MailAddress) GetLocal() string
GetLocal gets the local part of a mail address. E.g the part before the @.
func (*MailAddress) String ¶
func (address *MailAddress) String() string
type MailCmd ¶
type MailCmd struct { From *MailAddress EightBitMIME bool }
type MailMessage ¶
func ReadMessage ¶
func ReadMessage(r io.Reader) (*MailMessage, error)
type MtaProtocol ¶
type MtaProtocol struct {
// contains filtered or unexported fields
}
func NewMtaProtocol ¶
func NewMtaProtocol(c net.Conn) *MtaProtocol
NewMtaProtocol Creates a protocol that works over a socket. the net.Conn parameter will be closed when done.
func (*MtaProtocol) Close ¶
func (p *MtaProtocol) Close()
func (*MtaProtocol) GetCmd ¶
func (p *MtaProtocol) GetCmd() (*Cmd, error)
func (*MtaProtocol) GetIP ¶
func (p *MtaProtocol) GetIP() net.IP
func (*MtaProtocol) GetState ¶
func (p *MtaProtocol) GetState() *State
func (*MtaProtocol) Send ¶
func (p *MtaProtocol) Send(c Cmd)
type MultiAnswer ¶
type MultiAnswer struct { Status StatusCode Messages []string }
MultiAnswer A multiline answer.
func (MultiAnswer) String ¶
func (c MultiAnswer) String() string
type Protocol ¶
type Protocol interface { // Send a SMTP command. Send(Cmd) // Receive a command(will block while waiting for it). // Returns an error if something wen't wrong. E.g line was too long. GetCmd() (*Cmd, error) // Close the connection. Close() // StartTls starts the tls handshake. StartTls(*tls.Config) error // GetIP gets the ip of the client. GetIP() net.IP // Get the state that belongs to this connection. GetState() *State }
Protocol Used as communication layer so we can easily switch between a real socket and a test implementation.
type RcptCmd ¶
type RcptCmd struct {
To *MailAddress
}
type SMTPError ¶
type SMTPError Answer
SMTPError describes an SMTP error with a Status and a Message list of SMTP errors: https://datatracker.ietf.org/doc/html/rfc5321#section-4.2.3
type StartTlsCmd ¶
type StartTlsCmd struct { }
func (StartTlsCmd) String ¶
func (c StartTlsCmd) String() string
type State ¶
type State struct { From *MailAddress To []*MailAddress Data []byte EightBitMIME bool Secure bool SessionId Id Ip net.IP Hostname string Authenticated bool User User }
State contains all the state for a single client
func (*State) AuthMatchesRcptAndMail ¶
Check whether the auth user is allowed to send from the MAIL FROM email address and to the RCPT TO address.
func (*State) CanReceiveData ¶
Checks the state if the client can send a DATA command.
func (*State) CanReceiveMail ¶
Checks the state if the client can send a MAIL command.
func (*State) CanReceiveRcpt ¶
Checks the state if the client can send a RCPT command.
type StatusCode ¶
type StatusCode uint32
const ( Ready StatusCode = 220 Closing StatusCode = 221 Ok StatusCode = 250 StartData StatusCode = 354 ShuttingDown StatusCode = 421 SyntaxError StatusCode = 500 SyntaxErrorParam StatusCode = 501 NotImplemented StatusCode = 502 BadSequence StatusCode = 503 AbortMail StatusCode = 552 NoValidRecipients StatusCode = 554 )
SMTP status codes
const ( AuthenticationSucceeded StatusCode = 235 EncodedString StatusCode = 334 PasswordTransitionNeeded StatusCode = 432 TemporaryAuthenticationFailure StatusCode = 454 AuthenticationExchangeLineTooLong StatusCode = 500 MalformedAuthInput StatusCode = 501 AuthCommandNotPermittedDuringMailTransaction StatusCode = 503 UnrecognizedAuthenticationType StatusCode = 504 AuthenticationRequired StatusCode = 530 AuthenticationMechanismTooWeak StatusCode = 534 AuthenticationCredentialsInvalid StatusCode = 535 EncryptionRequiredForRequestedAuthenticationMechanism StatusCode = 538 )
SMTP status codes for AUTH extension (RFC 4954)
type UnknownCmd ¶
UnknownCmd is a command that is none of the other commands. i.e. not implemented
func (UnknownCmd) String ¶
func (c UnknownCmd) String() string