|
@@ -22,6 +22,9 @@ const (
|
|
ClassPermanentFailure = 5
|
|
ClassPermanentFailure = 5
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+// space char
|
|
|
|
+const SP = " "
|
|
|
|
+
|
|
// class is a type for ClassSuccess, ClassTransientFailure and ClassPermanentFailure constants
|
|
// class is a type for ClassSuccess, ClassTransientFailure and ClassPermanentFailure constants
|
|
type class int
|
|
type class int
|
|
|
|
|
|
@@ -118,39 +121,39 @@ var (
|
|
type Responses struct {
|
|
type Responses struct {
|
|
|
|
|
|
// The 500's
|
|
// The 500's
|
|
- FailLineTooLong string
|
|
|
|
- FailNestedMailCmd string
|
|
|
|
- FailNoSenderDataCmd string
|
|
|
|
- FailNoRecipientsDataCmd string
|
|
|
|
- FailUnrecognizedCmd string
|
|
|
|
- FailMaxUnrecognizedCmd string
|
|
|
|
- FailReadLimitExceededDataCmd string
|
|
|
|
- FailMessageSizeExceeded string
|
|
|
|
- FailReadErrorDataCmd string
|
|
|
|
- FailPathTooLong string
|
|
|
|
- FailInvalidAddress string
|
|
|
|
- FailLocalPartTooLong string
|
|
|
|
- FailDomainTooLong string
|
|
|
|
- FailBackendNotRunning string
|
|
|
|
- FailBackendTransaction string
|
|
|
|
- FailBackendTimeout string
|
|
|
|
- FailRcptCmd string
|
|
|
|
|
|
+ FailLineTooLong *Response
|
|
|
|
+ FailNestedMailCmd *Response
|
|
|
|
+ FailNoSenderDataCmd *Response
|
|
|
|
+ FailNoRecipientsDataCmd *Response
|
|
|
|
+ FailUnrecognizedCmd *Response
|
|
|
|
+ FailMaxUnrecognizedCmd *Response
|
|
|
|
+ FailReadLimitExceededDataCmd *Response
|
|
|
|
+ FailMessageSizeExceeded *Response
|
|
|
|
+ FailReadErrorDataCmd *Response
|
|
|
|
+ FailPathTooLong *Response
|
|
|
|
+ FailInvalidAddress *Response
|
|
|
|
+ FailLocalPartTooLong *Response
|
|
|
|
+ FailDomainTooLong *Response
|
|
|
|
+ FailBackendNotRunning *Response
|
|
|
|
+ FailBackendTransaction *Response
|
|
|
|
+ FailBackendTimeout *Response
|
|
|
|
+ FailRcptCmd *Response
|
|
|
|
|
|
// The 400's
|
|
// The 400's
|
|
- ErrorTooManyRecipients string
|
|
|
|
- ErrorRelayDenied string
|
|
|
|
- ErrorShutdown string
|
|
|
|
|
|
+ ErrorTooManyRecipients *Response
|
|
|
|
+ ErrorRelayDenied *Response
|
|
|
|
+ ErrorShutdown *Response
|
|
|
|
|
|
// The 200's
|
|
// The 200's
|
|
- SuccessMailCmd string
|
|
|
|
- SuccessRcptCmd string
|
|
|
|
- SuccessResetCmd string
|
|
|
|
- SuccessVerifyCmd string
|
|
|
|
- SuccessNoopCmd string
|
|
|
|
- SuccessQuitCmd string
|
|
|
|
- SuccessDataCmd string
|
|
|
|
- SuccessStartTLSCmd string
|
|
|
|
- SuccessMessageQueued string
|
|
|
|
|
|
+ SuccessMailCmd *Response
|
|
|
|
+ SuccessRcptCmd *Response
|
|
|
|
+ SuccessResetCmd *Response
|
|
|
|
+ SuccessVerifyCmd *Response
|
|
|
|
+ SuccessNoopCmd *Response
|
|
|
|
+ SuccessQuitCmd *Response
|
|
|
|
+ SuccessDataCmd *Response
|
|
|
|
+ SuccessStartTLSCmd *Response
|
|
|
|
+ SuccessMessageQueued *Response
|
|
}
|
|
}
|
|
|
|
|
|
// Called automatically during package load to build up the Responses struct
|
|
// Called automatically during package load to build up the Responses struct
|
|
@@ -158,191 +161,195 @@ func init() {
|
|
|
|
|
|
Canned = Responses{}
|
|
Canned = Responses{}
|
|
|
|
|
|
- Canned.FailLineTooLong = (&Response{
|
|
|
|
|
|
+ Canned.FailLineTooLong = &Response{
|
|
EnhancedCode: InvalidCommand,
|
|
EnhancedCode: InvalidCommand,
|
|
BasicCode: 554,
|
|
BasicCode: 554,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
Comment: "Line too long.",
|
|
Comment: "Line too long.",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailNestedMailCmd = (&Response{
|
|
|
|
|
|
+ Canned.FailNestedMailCmd = &Response{
|
|
EnhancedCode: InvalidCommand,
|
|
EnhancedCode: InvalidCommand,
|
|
BasicCode: 503,
|
|
BasicCode: 503,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
Comment: "Error: nested MAIL command",
|
|
Comment: "Error: nested MAIL command",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.SuccessMailCmd = (&Response{
|
|
|
|
|
|
+ Canned.SuccessMailCmd = &Response{
|
|
EnhancedCode: OtherAddressStatus,
|
|
EnhancedCode: OtherAddressStatus,
|
|
Class: ClassSuccess,
|
|
Class: ClassSuccess,
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.SuccessRcptCmd = (&Response{
|
|
|
|
|
|
+ Canned.SuccessRcptCmd = &Response{
|
|
EnhancedCode: DestinationMailboxAddressValid,
|
|
EnhancedCode: DestinationMailboxAddressValid,
|
|
Class: ClassSuccess,
|
|
Class: ClassSuccess,
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
Canned.SuccessResetCmd = Canned.SuccessMailCmd
|
|
Canned.SuccessResetCmd = Canned.SuccessMailCmd
|
|
- Canned.SuccessNoopCmd = (&Response{
|
|
|
|
|
|
+
|
|
|
|
+ Canned.SuccessNoopCmd = &Response{
|
|
EnhancedCode: OtherStatus,
|
|
EnhancedCode: OtherStatus,
|
|
Class: ClassSuccess,
|
|
Class: ClassSuccess,
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.SuccessVerifyCmd = (&Response{
|
|
|
|
|
|
+ Canned.SuccessVerifyCmd = &Response{
|
|
EnhancedCode: OtherOrUndefinedProtocolStatus,
|
|
EnhancedCode: OtherOrUndefinedProtocolStatus,
|
|
BasicCode: 252,
|
|
BasicCode: 252,
|
|
Class: ClassSuccess,
|
|
Class: ClassSuccess,
|
|
Comment: "Cannot verify user",
|
|
Comment: "Cannot verify user",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.ErrorTooManyRecipients = (&Response{
|
|
|
|
|
|
+ Canned.ErrorTooManyRecipients = &Response{
|
|
EnhancedCode: TooManyRecipients,
|
|
EnhancedCode: TooManyRecipients,
|
|
BasicCode: 452,
|
|
BasicCode: 452,
|
|
Class: ClassTransientFailure,
|
|
Class: ClassTransientFailure,
|
|
Comment: "Too many recipients",
|
|
Comment: "Too many recipients",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.ErrorRelayDenied = (&Response{
|
|
|
|
|
|
+ Canned.ErrorRelayDenied = &Response{
|
|
EnhancedCode: BadDestinationMailboxAddress,
|
|
EnhancedCode: BadDestinationMailboxAddress,
|
|
BasicCode: 454,
|
|
BasicCode: 454,
|
|
Class: ClassTransientFailure,
|
|
Class: ClassTransientFailure,
|
|
- Comment: "Error: Relay access denied: ",
|
|
|
|
- }).String()
|
|
|
|
|
|
+ Comment: "Error: Relay access denied:",
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.SuccessQuitCmd = (&Response{
|
|
|
|
|
|
+ Canned.SuccessQuitCmd = &Response{
|
|
EnhancedCode: OtherStatus,
|
|
EnhancedCode: OtherStatus,
|
|
BasicCode: 221,
|
|
BasicCode: 221,
|
|
Class: ClassSuccess,
|
|
Class: ClassSuccess,
|
|
Comment: "Bye",
|
|
Comment: "Bye",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailNoSenderDataCmd = (&Response{
|
|
|
|
|
|
+ Canned.FailNoSenderDataCmd = &Response{
|
|
EnhancedCode: InvalidCommand,
|
|
EnhancedCode: InvalidCommand,
|
|
BasicCode: 503,
|
|
BasicCode: 503,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
Comment: "Error: No sender",
|
|
Comment: "Error: No sender",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailNoRecipientsDataCmd = (&Response{
|
|
|
|
|
|
+ Canned.FailNoRecipientsDataCmd = &Response{
|
|
EnhancedCode: InvalidCommand,
|
|
EnhancedCode: InvalidCommand,
|
|
BasicCode: 503,
|
|
BasicCode: 503,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
Comment: "Error: No recipients",
|
|
Comment: "Error: No recipients",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.SuccessDataCmd = "354 Enter message, ending with '.' on a line by itself"
|
|
|
|
|
|
+ Canned.SuccessDataCmd = &Response{
|
|
|
|
+ BasicCode: 354,
|
|
|
|
+ Comment: "354 Enter message, ending with '.' on a line by itself",
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.SuccessStartTLSCmd = (&Response{
|
|
|
|
|
|
+ Canned.SuccessStartTLSCmd = &Response{
|
|
EnhancedCode: OtherStatus,
|
|
EnhancedCode: OtherStatus,
|
|
BasicCode: 220,
|
|
BasicCode: 220,
|
|
Class: ClassSuccess,
|
|
Class: ClassSuccess,
|
|
Comment: "Ready to start TLS",
|
|
Comment: "Ready to start TLS",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailUnrecognizedCmd = (&Response{
|
|
|
|
|
|
+ Canned.FailUnrecognizedCmd = &Response{
|
|
EnhancedCode: InvalidCommand,
|
|
EnhancedCode: InvalidCommand,
|
|
BasicCode: 554,
|
|
BasicCode: 554,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
Comment: "Unrecognized command",
|
|
Comment: "Unrecognized command",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailMaxUnrecognizedCmd = (&Response{
|
|
|
|
|
|
+ Canned.FailMaxUnrecognizedCmd = &Response{
|
|
EnhancedCode: InvalidCommand,
|
|
EnhancedCode: InvalidCommand,
|
|
BasicCode: 554,
|
|
BasicCode: 554,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
Comment: "Too many unrecognized commands",
|
|
Comment: "Too many unrecognized commands",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.ErrorShutdown = (&Response{
|
|
|
|
|
|
+ Canned.ErrorShutdown = &Response{
|
|
EnhancedCode: OtherOrUndefinedMailSystemStatus,
|
|
EnhancedCode: OtherOrUndefinedMailSystemStatus,
|
|
BasicCode: 421,
|
|
BasicCode: 421,
|
|
Class: ClassTransientFailure,
|
|
Class: ClassTransientFailure,
|
|
Comment: "Server is shutting down. Please try again later. Sayonara!",
|
|
Comment: "Server is shutting down. Please try again later. Sayonara!",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailReadLimitExceededDataCmd = (&Response{
|
|
|
|
|
|
+ Canned.FailReadLimitExceededDataCmd = &Response{
|
|
EnhancedCode: SyntaxError,
|
|
EnhancedCode: SyntaxError,
|
|
BasicCode: 550,
|
|
BasicCode: 550,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
- Comment: "Error: ",
|
|
|
|
- }).String()
|
|
|
|
|
|
+ Comment: "Error:",
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailMessageSizeExceeded = (&Response{
|
|
|
|
|
|
+ Canned.FailMessageSizeExceeded = &Response{
|
|
EnhancedCode: SyntaxError,
|
|
EnhancedCode: SyntaxError,
|
|
BasicCode: 550,
|
|
BasicCode: 550,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
- Comment: "Error: ",
|
|
|
|
- }).String()
|
|
|
|
|
|
+ Comment: "Error:",
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailReadErrorDataCmd = (&Response{
|
|
|
|
|
|
+ Canned.FailReadErrorDataCmd = &Response{
|
|
EnhancedCode: OtherOrUndefinedMailSystemStatus,
|
|
EnhancedCode: OtherOrUndefinedMailSystemStatus,
|
|
BasicCode: 451,
|
|
BasicCode: 451,
|
|
Class: ClassTransientFailure,
|
|
Class: ClassTransientFailure,
|
|
- Comment: "Error: ",
|
|
|
|
- }).String()
|
|
|
|
|
|
+ Comment: "Error:",
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailPathTooLong = (&Response{
|
|
|
|
|
|
+ Canned.FailPathTooLong = &Response{
|
|
EnhancedCode: InvalidCommandArguments,
|
|
EnhancedCode: InvalidCommandArguments,
|
|
BasicCode: 550,
|
|
BasicCode: 550,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
Comment: "Path too long",
|
|
Comment: "Path too long",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailInvalidAddress = (&Response{
|
|
|
|
|
|
+ Canned.FailInvalidAddress = &Response{
|
|
EnhancedCode: InvalidCommandArguments,
|
|
EnhancedCode: InvalidCommandArguments,
|
|
BasicCode: 501,
|
|
BasicCode: 501,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
Comment: "Invalid address",
|
|
Comment: "Invalid address",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailLocalPartTooLong = (&Response{
|
|
|
|
|
|
+ Canned.FailLocalPartTooLong = &Response{
|
|
EnhancedCode: InvalidCommandArguments,
|
|
EnhancedCode: InvalidCommandArguments,
|
|
BasicCode: 550,
|
|
BasicCode: 550,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
Comment: "Local part too long, cannot exceed 64 characters",
|
|
Comment: "Local part too long, cannot exceed 64 characters",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailDomainTooLong = (&Response{
|
|
|
|
|
|
+ Canned.FailDomainTooLong = &Response{
|
|
EnhancedCode: InvalidCommandArguments,
|
|
EnhancedCode: InvalidCommandArguments,
|
|
BasicCode: 550,
|
|
BasicCode: 550,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
Comment: "Domain cannot exceed 255 characters",
|
|
Comment: "Domain cannot exceed 255 characters",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailBackendNotRunning = (&Response{
|
|
|
|
|
|
+ Canned.FailBackendNotRunning = &Response{
|
|
EnhancedCode: OtherOrUndefinedProtocolStatus,
|
|
EnhancedCode: OtherOrUndefinedProtocolStatus,
|
|
BasicCode: 554,
|
|
BasicCode: 554,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
- Comment: "Transaction failed - backend not running ",
|
|
|
|
- }).String()
|
|
|
|
|
|
+ Comment: "Transaction failed - backend not running",
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailBackendTransaction = (&Response{
|
|
|
|
|
|
+ Canned.FailBackendTransaction = &Response{
|
|
EnhancedCode: OtherOrUndefinedProtocolStatus,
|
|
EnhancedCode: OtherOrUndefinedProtocolStatus,
|
|
BasicCode: 554,
|
|
BasicCode: 554,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
- Comment: "Error: ",
|
|
|
|
- }).String()
|
|
|
|
|
|
+ Comment: "Error:",
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.SuccessMessageQueued = (&Response{
|
|
|
|
|
|
+ Canned.SuccessMessageQueued = &Response{
|
|
EnhancedCode: OtherStatus,
|
|
EnhancedCode: OtherStatus,
|
|
BasicCode: 250,
|
|
BasicCode: 250,
|
|
Class: ClassSuccess,
|
|
Class: ClassSuccess,
|
|
- Comment: "OK : queued as ",
|
|
|
|
- }).String()
|
|
|
|
|
|
+ Comment: "OK: queued as",
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailBackendTimeout = (&Response{
|
|
|
|
|
|
+ Canned.FailBackendTimeout = &Response{
|
|
EnhancedCode: OtherOrUndefinedProtocolStatus,
|
|
EnhancedCode: OtherOrUndefinedProtocolStatus,
|
|
BasicCode: 554,
|
|
BasicCode: 554,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
Comment: "Error: transaction timeout",
|
|
Comment: "Error: transaction timeout",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- Canned.FailRcptCmd = (&Response{
|
|
|
|
|
|
+ Canned.FailRcptCmd = &Response{
|
|
EnhancedCode: BadDestinationMailboxAddress,
|
|
EnhancedCode: BadDestinationMailboxAddress,
|
|
BasicCode: 550,
|
|
BasicCode: 550,
|
|
Class: ClassPermanentFailure,
|
|
Class: ClassPermanentFailure,
|
|
Comment: "User unknown in local recipient table",
|
|
Comment: "User unknown in local recipient table",
|
|
- }).String()
|
|
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -409,6 +416,7 @@ type Response struct {
|
|
Class class
|
|
Class class
|
|
// Comment is optional
|
|
// Comment is optional
|
|
Comment string
|
|
Comment string
|
|
|
|
+ cached string
|
|
}
|
|
}
|
|
|
|
|
|
// it looks like this ".5.4"
|
|
// it looks like this ".5.4"
|
|
@@ -428,6 +436,14 @@ func (e EnhancedStatusCode) String() string {
|
|
// String returns a custom Response as a string
|
|
// String returns a custom Response as a string
|
|
func (r *Response) String() string {
|
|
func (r *Response) String() string {
|
|
|
|
|
|
|
|
+ if r.cached != "" {
|
|
|
|
+ return r.cached
|
|
|
|
+ }
|
|
|
|
+ if r.EnhancedCode == "" {
|
|
|
|
+ r.cached = r.Comment
|
|
|
|
+ return r.Comment
|
|
|
|
+ }
|
|
|
|
+
|
|
basicCode := r.BasicCode
|
|
basicCode := r.BasicCode
|
|
comment := r.Comment
|
|
comment := r.Comment
|
|
if len(comment) == 0 && r.BasicCode == 0 {
|
|
if len(comment) == 0 && r.BasicCode == 0 {
|
|
@@ -447,8 +463,8 @@ func (r *Response) String() string {
|
|
if r.BasicCode == 0 {
|
|
if r.BasicCode == 0 {
|
|
basicCode = getBasicStatusCode(e)
|
|
basicCode = getBasicStatusCode(e)
|
|
}
|
|
}
|
|
-
|
|
|
|
- return fmt.Sprintf("%d %s %s", basicCode, e.String(), comment)
|
|
|
|
|
|
+ r.cached = fmt.Sprintf("%d %s %s", basicCode, e.String(), comment)
|
|
|
|
+ return r.cached
|
|
}
|
|
}
|
|
|
|
|
|
// getBasicStatusCode gets the basic status code from codeMap, or fallback code if not mapped
|
|
// getBasicStatusCode gets the basic status code from codeMap, or fallback code if not mapped
|