Update method comments to include additional context and RFC references

Enhanced the comments for various methods in `msg.go`, `client.go`, `auth.go`, and `encoding.go` to provide more detailed explanations, context, and relevant RFC references. This improves the clarity and maintainability of the code by providing developers with a deeper understanding of each method's purpose and usage.
This commit is contained in:
Winni Neessen 2024-10-05 13:39:21 +02:00
parent c186cba2c2
commit 78e2857782
Signed by: wneessen
GPG key ID: 385AC9889632126E
4 changed files with 76 additions and 34 deletions

20
auth.go
View file

@ -20,6 +20,7 @@ const (
// //
// It was recommended to deprecate the standard in 20 November 2008. As an alternative it // It was recommended to deprecate the standard in 20 November 2008. As an alternative it
// recommends e.g. SCRAM or SASL Plain protected by TLS instead. // recommends e.g. SCRAM or SASL Plain protected by TLS instead.
//
// https://datatracker.ietf.org/doc/html/draft-ietf-sasl-crammd5-to-historic-00.html // https://datatracker.ietf.org/doc/html/draft-ietf-sasl-crammd5-to-historic-00.html
SMTPAuthCramMD5 SMTPAuthType = "CRAM-MD5" SMTPAuthCramMD5 SMTPAuthType = "CRAM-MD5"
@ -33,12 +34,14 @@ const (
// does not have an official RFC that could be followed. There is a spec by Microsoft and an // does not have an official RFC that could be followed. There is a spec by Microsoft and an
// IETF draft. The IETF draft is more lax than the MS spec, therefore we follow the I-D, which // IETF draft. The IETF draft is more lax than the MS spec, therefore we follow the I-D, which
// automatically matches the MS spec. // automatically matches the MS spec.
// https://msopenspecs.azureedge.net/files/MS-XLOGIN/%5bMS-XLOGIN%5d.pdf
// https://datatracker.ietf.org/doc/html/draft-murchison-sasl-login-00
// //
// Since the "LOGIN" SASL authentication mechansim transmits the username and password in // Since the "LOGIN" SASL authentication mechansim transmits the username and password in
// plaintext over the internet connection, we only allow this mechanism over a TLS secured // plaintext over the internet connection, we only allow this mechanism over a TLS secured
// connection. // connection.
//
// https://msopenspecs.azureedge.net/files/MS-XLOGIN/%5bMS-XLOGIN%5d.pdf
//
// https://datatracker.ietf.org/doc/html/draft-murchison-sasl-login-00
SMTPAuthLogin SMTPAuthType = "LOGIN" SMTPAuthLogin SMTPAuthType = "LOGIN"
// SMTPAuthNoAuth is equivalent to performing no authentication at all. It is a convenience // SMTPAuthNoAuth is equivalent to performing no authentication at all. It is a convenience
@ -47,11 +50,12 @@ const (
SMTPAuthNoAuth SMTPAuthType = "" SMTPAuthNoAuth SMTPAuthType = ""
// SMTPAuthPlain is the "PLAIN" authentication mechanism as described in RFC 4616. // SMTPAuthPlain is the "PLAIN" authentication mechanism as described in RFC 4616.
// https://datatracker.ietf.org/doc/html/rfc4616/
// //
// Since the "PLAIN" SASL authentication mechansim transmits the username and password in // Since the "PLAIN" SASL authentication mechansim transmits the username and password in
// plaintext over the internet connection, we only allow this mechanism over a TLS secured // plaintext over the internet connection, we only allow this mechanism over a TLS secured
// connection. // connection.
//
// https://datatracker.ietf.org/doc/html/rfc4616/
SMTPAuthPlain SMTPAuthType = "PLAIN" SMTPAuthPlain SMTPAuthType = "PLAIN"
// SMTPAuthXOAUTH2 is the "XOAUTH2" SASL authentication mechanism. // SMTPAuthXOAUTH2 is the "XOAUTH2" SASL authentication mechanism.
@ -59,16 +63,16 @@ const (
SMTPAuthXOAUTH2 SMTPAuthType = "XOAUTH2" SMTPAuthXOAUTH2 SMTPAuthType = "XOAUTH2"
// SMTPAuthSCRAMSHA1 is the "SCRAM-SHA-1" SASL authentication mechanism as described in RFC 5802. // SMTPAuthSCRAMSHA1 is the "SCRAM-SHA-1" SASL authentication mechanism as described in RFC 5802.
// https://datatracker.ietf.org/doc/html/rfc5802
// //
// SCRAM-SHA-1 is still considered secure for certain applications, particularly when used as part // SCRAM-SHA-1 is still considered secure for certain applications, particularly when used as part
// of a challenge-response authentication mechanism (as we use it). However, it is generally // of a challenge-response authentication mechanism (as we use it). However, it is generally
// recommended to prefer stronger alternatives like SCRAM-SHA-256(-PLUS), as SHA-1 has known // recommended to prefer stronger alternatives like SCRAM-SHA-256(-PLUS), as SHA-1 has known
// vulnerabilities in other contexts, although it remains effective in HMAC constructions. // vulnerabilities in other contexts, although it remains effective in HMAC constructions.
//
// https://datatracker.ietf.org/doc/html/rfc5802
SMTPAuthSCRAMSHA1 SMTPAuthType = "SCRAM-SHA-1" SMTPAuthSCRAMSHA1 SMTPAuthType = "SCRAM-SHA-1"
// SMTPAuthSCRAMSHA1PLUS is the "SCRAM-SHA-1-PLUS" SASL authentication mechanism as described in RFC 5802. // SMTPAuthSCRAMSHA1PLUS is the "SCRAM-SHA-1-PLUS" SASL authentication mechanism as described in RFC 5802.
// https://datatracker.ietf.org/doc/html/rfc5802
// //
// SCRAM-SHA-X-PLUS authentication require TLS channel bindings to protect against MitM attacks and // SCRAM-SHA-X-PLUS authentication require TLS channel bindings to protect against MitM attacks and
// to guarantee that the integrity of the transport layer is preserved throughout the authentication // to guarantee that the integrity of the transport layer is preserved throughout the authentication
@ -78,18 +82,22 @@ const (
// of a challenge-response authentication mechanism (as we use it). However, it is generally // of a challenge-response authentication mechanism (as we use it). However, it is generally
// recommended to prefer stronger alternatives like SCRAM-SHA-256(-PLUS), as SHA-1 has known // recommended to prefer stronger alternatives like SCRAM-SHA-256(-PLUS), as SHA-1 has known
// vulnerabilities in other contexts, although it remains effective in HMAC constructions. // vulnerabilities in other contexts, although it remains effective in HMAC constructions.
//
// https://datatracker.ietf.org/doc/html/rfc5802
SMTPAuthSCRAMSHA1PLUS SMTPAuthType = "SCRAM-SHA-1-PLUS" SMTPAuthSCRAMSHA1PLUS SMTPAuthType = "SCRAM-SHA-1-PLUS"
// SMTPAuthSCRAMSHA256 is the "SCRAM-SHA-256" SASL authentication mechanism as described in RFC 7677. // SMTPAuthSCRAMSHA256 is the "SCRAM-SHA-256" SASL authentication mechanism as described in RFC 7677.
//
// https://datatracker.ietf.org/doc/html/rfc7677 // https://datatracker.ietf.org/doc/html/rfc7677
SMTPAuthSCRAMSHA256 SMTPAuthType = "SCRAM-SHA-256" SMTPAuthSCRAMSHA256 SMTPAuthType = "SCRAM-SHA-256"
// SMTPAuthSCRAMSHA256PLUS is the "SCRAM-SHA-256-PLUS" SASL authentication mechanism as described in RFC 7677. // SMTPAuthSCRAMSHA256PLUS is the "SCRAM-SHA-256-PLUS" SASL authentication mechanism as described in RFC 7677.
// https://datatracker.ietf.org/doc/html/rfc7677
// //
// SCRAM-SHA-X-PLUS authentication require TLS channel bindings to protect against MitM attacks and // SCRAM-SHA-X-PLUS authentication require TLS channel bindings to protect against MitM attacks and
// to guarantee that the integrity of the transport layer is preserved throughout the authentication // to guarantee that the integrity of the transport layer is preserved throughout the authentication
// process. Therefore we only allow this mechansim over a TLS secured connection. // process. Therefore we only allow this mechansim over a TLS secured connection.
//
// https://datatracker.ietf.org/doc/html/rfc7677
SMTPAuthSCRAMSHA256PLUS SMTPAuthType = "SCRAM-SHA-256-PLUS" SMTPAuthSCRAMSHA256PLUS SMTPAuthType = "SCRAM-SHA-256-PLUS"
) )

View file

@ -44,26 +44,31 @@ const (
// DSNMailReturnHeadersOnly requests that only the message headers of the mail message are returned in // DSNMailReturnHeadersOnly requests that only the message headers of the mail message are returned in
// a DSN (Delivery Status Notification). // a DSN (Delivery Status Notification).
//
// https://datatracker.ietf.org/doc/html/rfc1891#section-5.3 // https://datatracker.ietf.org/doc/html/rfc1891#section-5.3
DSNMailReturnHeadersOnly DSNMailReturnOption = "HDRS" DSNMailReturnHeadersOnly DSNMailReturnOption = "HDRS"
// DSNMailReturnFull requests that the entire mail message is returned in any failed DSN // DSNMailReturnFull requests that the entire mail message is returned in any failed DSN
// (Delivery Status Notification) issued for this recipient. // (Delivery Status Notification) issued for this recipient.
//
// https://datatracker.ietf.org/doc/html/rfc1891/#section-5.3 // https://datatracker.ietf.org/doc/html/rfc1891/#section-5.3
DSNMailReturnFull DSNMailReturnOption = "FULL" DSNMailReturnFull DSNMailReturnOption = "FULL"
// DSNRcptNotifyNever indicates that no DSN (Delivery Status Notifications) should be sent for the // DSNRcptNotifyNever indicates that no DSN (Delivery Status Notifications) should be sent for the
// recipient under any condition. // recipient under any condition.
//
// https://datatracker.ietf.org/doc/html/rfc1891/#section-5.1 // https://datatracker.ietf.org/doc/html/rfc1891/#section-5.1
DSNRcptNotifyNever DSNRcptNotifyOption = "NEVER" DSNRcptNotifyNever DSNRcptNotifyOption = "NEVER"
// DSNRcptNotifySuccess indicates that the sender requests a DSN (Delivery Status Notification) if the // DSNRcptNotifySuccess indicates that the sender requests a DSN (Delivery Status Notification) if the
// message is successfully delivered. // message is successfully delivered.
//
// https://datatracker.ietf.org/doc/html/rfc1891/#section-5.1 // https://datatracker.ietf.org/doc/html/rfc1891/#section-5.1
DSNRcptNotifySuccess DSNRcptNotifyOption = "SUCCESS" DSNRcptNotifySuccess DSNRcptNotifyOption = "SUCCESS"
// DSNRcptNotifyFailure requests that a DSN (Delivery Status Notification) is issued if delivery of // DSNRcptNotifyFailure requests that a DSN (Delivery Status Notification) is issued if delivery of
// a message fails. // a message fails.
//
// https://datatracker.ietf.org/doc/html/rfc1891/#section-5.1 // https://datatracker.ietf.org/doc/html/rfc1891/#section-5.1
DSNRcptNotifyFailure DSNRcptNotifyOption = "FAILURE" DSNRcptNotifyFailure DSNRcptNotifyOption = "FAILURE"
@ -73,6 +78,7 @@ const (
// (as determined by the MTA at which the message is delayed), but the final delivery status (whether // (as determined by the MTA at which the message is delayed), but the final delivery status (whether
// successful or failure) cannot be determined. The absence of the DELAY keyword in a NOTIFY parameter // successful or failure) cannot be determined. The absence of the DELAY keyword in a NOTIFY parameter
// requests that a "delayed" DSN NOT be issued under any conditions. // requests that a "delayed" DSN NOT be issued under any conditions.
//
// https://datatracker.ietf.org/doc/html/rfc1891/#section-5.1 // https://datatracker.ietf.org/doc/html/rfc1891/#section-5.1
DSNRcptNotifyDelay DSNRcptNotifyOption = "DELAY" DSNRcptNotifyDelay DSNRcptNotifyOption = "DELAY"
) )
@ -87,11 +93,13 @@ type (
// DSNMailReturnOption is a type wrapper for a string and specifies the type of return content requested // DSNMailReturnOption is a type wrapper for a string and specifies the type of return content requested
// in a Delivery Status Notification (DSN). // in a Delivery Status Notification (DSN).
//
// https://datatracker.ietf.org/doc/html/rfc1891/ // https://datatracker.ietf.org/doc/html/rfc1891/
DSNMailReturnOption string DSNMailReturnOption string
// DSNRcptNotifyOption is a type wrapper for a string and specifies the notification options for a // DSNRcptNotifyOption is a type wrapper for a string and specifies the notification options for a
// recipient in DSNs. // recipient in DSNs.
//
// https://datatracker.ietf.org/doc/html/rfc1891/ // https://datatracker.ietf.org/doc/html/rfc1891/
DSNRcptNotifyOption string DSNRcptNotifyOption string
@ -167,6 +175,7 @@ type (
smtpClient *smtp.Client smtpClient *smtp.Client
// tlspolicy defines the TLSPolicy configuration the Client uses for the STARTTLS protocol. // tlspolicy defines the TLSPolicy configuration the Client uses for the STARTTLS protocol.
//
// https://datatracker.ietf.org/doc/html/rfc3207#section-2 // https://datatracker.ietf.org/doc/html/rfc3207#section-2
tlspolicy TLSPolicy tlspolicy TLSPolicy
@ -180,6 +189,7 @@ type (
user string user string
// useSSL indicates whether to use SSL/TLS encryption for network communication. // useSSL indicates whether to use SSL/TLS encryption for network communication.
//
// https://datatracker.ietf.org/doc/html/rfc8314 // https://datatracker.ietf.org/doc/html/rfc8314
useSSL bool useSSL bool
} }
@ -424,10 +434,11 @@ func WithPassword(password string) Option {
// WithDSN enables DSN (Delivery Status Notifications) for the Client as described in the RFC 1891. DSN // WithDSN enables DSN (Delivery Status Notifications) for the Client as described in the RFC 1891. DSN
// only work if the server supports them. // only work if the server supports them.
// https://datatracker.ietf.org/doc/html/rfc1891
// //
// By default we set DSNMailReturnOption to DSNMailReturnFull and DSNRcptNotifyOption to DSNRcptNotifySuccess // By default we set DSNMailReturnOption to DSNMailReturnFull and DSNRcptNotifyOption to DSNRcptNotifySuccess
// and DSNRcptNotifyFailure. // and DSNRcptNotifyFailure.
//
// https://datatracker.ietf.org/doc/html/rfc1891
func WithDSN() Option { func WithDSN() Option {
return func(c *Client) error { return func(c *Client) error {
c.requestDSN = true c.requestDSN = true
@ -439,9 +450,10 @@ func WithDSN() Option {
// WithDSNMailReturnType enables DSN (Delivery Status Notifications) for the Client as described in the // WithDSNMailReturnType enables DSN (Delivery Status Notifications) for the Client as described in the
// RFC 1891. DSN only work if the server supports them. // RFC 1891. DSN only work if the server supports them.
// https://datatracker.ietf.org/doc/html/rfc1891
// //
// It will set the DSNMailReturnOption to the provided value. // It will set the DSNMailReturnOption to the provided value.
//
// https://datatracker.ietf.org/doc/html/rfc1891
func WithDSNMailReturnType(option DSNMailReturnOption) Option { func WithDSNMailReturnType(option DSNMailReturnOption) Option {
return func(c *Client) error { return func(c *Client) error {
switch option { switch option {
@ -459,9 +471,10 @@ func WithDSNMailReturnType(option DSNMailReturnOption) Option {
// WithDSNRcptNotifyType enables DSN (Delivery Status Notifications) for the Client as described in the // WithDSNRcptNotifyType enables DSN (Delivery Status Notifications) for the Client as described in the
// RFC 1891. DSN only work if the server supports them. // RFC 1891. DSN only work if the server supports them.
// https://datatracker.ietf.org/doc/html/rfc1891
// //
// It will set the DSNRcptNotifyOption to the provided values. // It will set the DSNRcptNotifyOption to the provided values.
//
// https://datatracker.ietf.org/doc/html/rfc1891
func WithDSNRcptNotifyType(opts ...DSNRcptNotifyOption) Option { func WithDSNRcptNotifyType(opts ...DSNRcptNotifyOption) Option {
return func(c *Client) error { return func(c *Client) error {
var rcptOpts []string var rcptOpts []string

View file

@ -22,19 +22,24 @@ type MIMEType string
const ( const (
// EncodingB64 represents the Base64 encoding as specified in RFC 2045. // EncodingB64 represents the Base64 encoding as specified in RFC 2045.
//
// https://datatracker.ietf.org/doc/html/rfc2045#section-6.8 // https://datatracker.ietf.org/doc/html/rfc2045#section-6.8
EncodingB64 Encoding = "base64" EncodingB64 Encoding = "base64"
// EncodingQP represents the "quoted-printable" encoding as specified in RFC 2045. // EncodingQP represents the "quoted-printable" encoding as specified in RFC 2045.
//
// https://datatracker.ietf.org/doc/html/rfc2045#section-6.7 // https://datatracker.ietf.org/doc/html/rfc2045#section-6.7
EncodingQP Encoding = "quoted-printable" EncodingQP Encoding = "quoted-printable"
// EncodingUSASCII represents encoding with only US-ASCII characters (aka 7Bit) // EncodingUSASCII represents encoding with only US-ASCII characters (aka 7Bit)
//
// https://datatracker.ietf.org/doc/html/rfc2045#section-2.7 // https://datatracker.ietf.org/doc/html/rfc2045#section-2.7
EncodingUSASCII Encoding = "7bit" EncodingUSASCII Encoding = "7bit"
// NoEncoding represents 8-bit encoding for email messages as specified in RFC 6152. // NoEncoding represents 8-bit encoding for email messages as specified in RFC 6152.
//
// https://datatracker.ietf.org/doc/html/rfc2045#section-2.8 // https://datatracker.ietf.org/doc/html/rfc2045#section-2.8
//
// https://datatracker.ietf.org/doc/html/rfc6152 // https://datatracker.ietf.org/doc/html/rfc6152
NoEncoding Encoding = "8bit" NoEncoding Encoding = "8bit"
) )

66
msg.go
View file

@ -197,7 +197,9 @@ func WithEncoding(e Encoding) MsgOption {
// do not introduce new MIME versions; they refine or add features within the framework of MIME 1.0. // do not introduce new MIME versions; they refine or add features within the framework of MIME 1.0.
// Therefore there should be no reason to ever use this MsgOption. // Therefore there should be no reason to ever use this MsgOption.
// https://datatracker.ietf.org/doc/html/rfc1521 // https://datatracker.ietf.org/doc/html/rfc1521
//
// https://datatracker.ietf.org/doc/html/rfc2045 // https://datatracker.ietf.org/doc/html/rfc2045
//
// https://datatracker.ietf.org/doc/html/rfc2049 // https://datatracker.ietf.org/doc/html/rfc2049
func WithMIMEVersion(mv MIMEVersion) MsgOption { func WithMIMEVersion(mv MIMEVersion) MsgOption {
return func(m *Msg) { return func(m *Msg) {
@ -239,52 +241,68 @@ func WithNoDefaultUserAgent() MsgOption {
} }
} }
// SetCharset sets the encoding charset of the Msg // SetCharset sets or overrides the currently set encoding charset of the Msg.
func (m *Msg) SetCharset(c Charset) { func (m *Msg) SetCharset(c Charset) {
m.charset = c m.charset = c
} }
// SetEncoding sets the encoding of the Msg // SetEncoding sets or overrides the currently set Encoding of the Msg.
func (m *Msg) SetEncoding(e Encoding) { func (m *Msg) SetEncoding(e Encoding) {
m.encoding = e m.encoding = e
m.setEncoder() m.setEncoder()
} }
// SetBoundary sets the boundary of the Msg // SetBoundary sets or overrides the currently set boundary of the Msg.
//
// Note that by default we create random MIME boundaries. This should only be used if a specific boundary is
// required.
func (m *Msg) SetBoundary(b string) { func (m *Msg) SetBoundary(b string) {
m.boundary = b m.boundary = b
} }
// SetMIMEVersion sets the MIME version of the Msg // SetMIMEVersion sets or overrides the currently set MIME version of the Msg.
//
// Note that in the context of email, MIME Version 1.0 is the only officially standardized and supported
// version. While MIME has been updated and extended over time (via various RFCs), these updates and extensions
// do not introduce new MIME versions; they refine or add features within the framework of MIME 1.0.
// Therefore there should be no reason to ever use this MsgOption.
//
// https://datatracker.ietf.org/doc/html/rfc1521
//
// https://datatracker.ietf.org/doc/html/rfc2045
//
// https://datatracker.ietf.org/doc/html/rfc2049
func (m *Msg) SetMIMEVersion(mv MIMEVersion) { func (m *Msg) SetMIMEVersion(mv MIMEVersion) {
m.mimever = mv m.mimever = mv
} }
// SetPGPType sets the PGPType of the Msg // SetPGPType sets or overrides the currently set PGP type for the Msg, determining the encryption or
// signature method.
func (m *Msg) SetPGPType(t PGPType) { func (m *Msg) SetPGPType(t PGPType) {
m.pgptype = t m.pgptype = t
} }
// Encoding returns the currently set encoding of the Msg // Encoding returns the currently set Encoding of the Msg as string.
func (m *Msg) Encoding() string { func (m *Msg) Encoding() string {
return m.encoding.String() return m.encoding.String()
} }
// Charset returns the currently set charset of the Msg // Charset returns the currently set Charset of the Msg as string.
func (m *Msg) Charset() string { func (m *Msg) Charset() string {
return m.charset.String() return m.charset.String()
} }
// SetHeader sets a generic header field of the Msg // SetHeader sets a generic header field of the Msg.
// For adding address headers like "To:" or "From", see SetAddrHeader
// //
// Deprecated: This method only exists for compatibility reason. Please use SetGenHeader instead // Deprecated: This method only exists for compatibility reason. Please use SetGenHeader instead.
// For adding address headers like "To:" or "From", use SetAddrHeader instead.
func (m *Msg) SetHeader(header Header, values ...string) { func (m *Msg) SetHeader(header Header, values ...string) {
m.SetGenHeader(header, values...) m.SetGenHeader(header, values...)
} }
// SetGenHeader sets a generic header field of the Msg // SetGenHeader sets a generic header field of the Msg to the provided list of values.
// For adding address headers like "To:" or "From", see SetAddrHeader //
// Note: for adding email address related headers (like "To:" or "From") use SetAddrHeader instead.
func (m *Msg) SetGenHeader(header Header, values ...string) { func (m *Msg) SetGenHeader(header Header, values ...string) {
if m.genHeader == nil { if m.genHeader == nil {
m.genHeader = make(map[Header][]string) m.genHeader = make(map[Header][]string)
@ -295,26 +313,24 @@ func (m *Msg) SetGenHeader(header Header, values ...string) {
m.genHeader[header] = values m.genHeader[header] = values
} }
// SetHeaderPreformatted sets a generic header field of the Msg which content is // SetHeaderPreformatted sets a generic header field of the Msg, which content is already preformatted.
// already preformated.
// //
// Deprecated: This method only exists for compatibility reason. Please use // Deprecated: This method only exists for compatibility reason. Please use SetGenHeaderPreformatted instead.
// SetGenHeaderPreformatted instead
func (m *Msg) SetHeaderPreformatted(header Header, value string) { func (m *Msg) SetHeaderPreformatted(header Header, value string) {
m.SetGenHeaderPreformatted(header, value) m.SetGenHeaderPreformatted(header, value)
} }
// SetGenHeaderPreformatted sets a generic header field of the Msg which content is // SetGenHeaderPreformatted sets a generic header field of the Msg which content is already preformated.
// already preformated.
// //
// This method does not take a slice of values but only a single value. This is // This method does not take a slice of values but only a single value. The reason for this is that we do not
// due to the fact, that we do not perform any content alteration and expect the // perform any content alteration on these kind of headers and expect the user to have already taken care of
// user has already done so // any kind of formatting required for the header.
// //
// **Please note:** This method should be used only as a last resort. Since the // Note: This method should be used only as a last resort. Since the user is respondible for the formatting of
// user is respondible for the formating of the message header, go-mail cannot // the message header, we cannot guarantee any compliance with the RFC 2822. It is advised to use SetGenHeader
// guarantee the fully compliance with the RFC 2822. It is recommended to use // instead.
// SetGenHeader instead. //
// https://datatracker.ietf.org/doc/html/rfc2822
func (m *Msg) SetGenHeaderPreformatted(header Header, value string) { func (m *Msg) SetGenHeaderPreformatted(header Header, value string) {
if m.preformHeader == nil { if m.preformHeader == nil {
m.preformHeader = make(map[Header]string) m.preformHeader = make(map[Header]string)