mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-12 17:02:55 +01:00
Calling it a day...
This commit is contained in:
parent
57ebb171c5
commit
98d7982738
5 changed files with 55 additions and 29 deletions
|
@ -4,13 +4,12 @@
|
||||||
<option name="autoReloadType" value="ALL" />
|
<option name="autoReloadType" value="ALL" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="b79e8e7a-d892-4ce4-8bf4-f9e45415b803" name="Changes" comment="Better context and connection handling">
|
<list default="true" id="b79e8e7a-d892-4ce4-8bf4-f9e45415b803" name="Changes" comment="Lots of cleanups and refactoring">
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/client.go" beforeDir="false" afterPath="$PROJECT_DIR$/client.go" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/client.go" beforeDir="false" afterPath="$PROJECT_DIR$/client.go" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/cmd/main.go" beforeDir="false" afterPath="$PROJECT_DIR$/cmd/main.go" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/cmd/main.go" beforeDir="false" afterPath="$PROJECT_DIR$/cmd/main.go" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/header.go" beforeDir="false" afterPath="$PROJECT_DIR$/header.go" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/header.go" beforeDir="false" afterPath="$PROJECT_DIR$/header.go" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/mailmsg.go" beforeDir="false" afterPath="$PROJECT_DIR$/mailmsg.go" afterDir="false" />
|
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
@ -97,7 +96,8 @@
|
||||||
<MESSAGE value="Progress" />
|
<MESSAGE value="Progress" />
|
||||||
<MESSAGE value="Implemented SMTP AUTH" />
|
<MESSAGE value="Implemented SMTP AUTH" />
|
||||||
<MESSAGE value="Better context and connection handling" />
|
<MESSAGE value="Better context and connection handling" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value="Better context and connection handling" />
|
<MESSAGE value="Lots of cleanups and refactoring" />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="Lots of cleanups and refactoring" />
|
||||||
</component>
|
</component>
|
||||||
<component name="VgoProject">
|
<component name="VgoProject">
|
||||||
<integration-enabled>true</integration-enabled>
|
<integration-enabled>true</integration-enabled>
|
||||||
|
|
|
@ -16,6 +16,7 @@ mail and SMTP related tasks.
|
||||||
Some of the features of this library:
|
Some of the features of this library:
|
||||||
* [X] Only Standard Library dependant
|
* [X] Only Standard Library dependant
|
||||||
* [X] Modern, idiotmatic Go
|
* [X] Modern, idiotmatic Go
|
||||||
|
* [X] Sane and secure defaults
|
||||||
* [X] SSL/TLS support
|
* [X] SSL/TLS support
|
||||||
* [X] StartTLS support with different policies
|
* [X] StartTLS support with different policies
|
||||||
* [X] Makes use of contexts for a better control flow and timeout/cancelation handling
|
* [X] Makes use of contexts for a better control flow and timeout/cancelation handling
|
||||||
|
|
66
client.go
66
client.go
|
@ -12,11 +12,17 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultPort is the default connection port cto the SMTP server
|
// Defaults
|
||||||
const DefaultPort = 25
|
const (
|
||||||
|
// DefaultPort is the default connection port cto the SMTP server
|
||||||
|
DefaultPort = 25
|
||||||
|
|
||||||
// DefaultTimeout is the default connection timeout
|
// DefaultTimeout is the default connection timeout
|
||||||
const DefaultTimeout = time.Second * 30
|
DefaultTimeout = time.Second * 15
|
||||||
|
|
||||||
|
// DefaultTLSPolicy is the default STARTTLS policy
|
||||||
|
DefaultTLSPolicy = TLSMandatory
|
||||||
|
)
|
||||||
|
|
||||||
// Client is the SMTP client struct
|
// Client is the SMTP client struct
|
||||||
type Client struct {
|
type Client struct {
|
||||||
|
@ -84,8 +90,8 @@ func NewClient(h string, o ...Option) (*Client, error) {
|
||||||
cto: DefaultTimeout,
|
cto: DefaultTimeout,
|
||||||
host: h,
|
host: h,
|
||||||
port: DefaultPort,
|
port: DefaultPort,
|
||||||
tlspolicy: TLSMandatory,
|
|
||||||
tlsconfig: &tls.Config{ServerName: h},
|
tlsconfig: &tls.Config{ServerName: h},
|
||||||
|
tlspolicy: DefaultTLSPolicy,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set default HELO/EHLO hostname
|
// Set default HELO/EHLO hostname
|
||||||
|
@ -257,27 +263,8 @@ func (c *Client) DialWithContext(pc context.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.ssl && c.tlspolicy != NoTLS {
|
if err := c.tls(); err != nil {
|
||||||
est := false
|
return err
|
||||||
st, _ := c.sc.Extension("STARTTLS")
|
|
||||||
if c.tlspolicy == TLSMandatory {
|
|
||||||
est = true
|
|
||||||
if !st {
|
|
||||||
return fmt.Errorf("STARTTLS mode set to: %q, but target host does not support STARTTLS",
|
|
||||||
c.tlspolicy)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if c.tlspolicy == TLSOpportunistic {
|
|
||||||
if st {
|
|
||||||
est = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if est {
|
|
||||||
if err := c.sc.StartTLS(c.tlsconfig); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, c.enc = c.sc.TLSConnectionState()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.auth(); err != nil {
|
if err := c.auth(); err != nil {
|
||||||
|
@ -333,6 +320,33 @@ func (c *Client) checkConn() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tls tries to make sure that the STARTTLS requirements are satisfied
|
||||||
|
func (c *Client) tls() error {
|
||||||
|
if !c.ssl && c.tlspolicy != NoTLS {
|
||||||
|
est := false
|
||||||
|
st, _ := c.sc.Extension("STARTTLS")
|
||||||
|
if c.tlspolicy == TLSMandatory {
|
||||||
|
est = true
|
||||||
|
if !st {
|
||||||
|
return fmt.Errorf("STARTTLS mode set to: %q, but target host does not support STARTTLS",
|
||||||
|
c.tlspolicy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.tlspolicy == TLSOpportunistic {
|
||||||
|
if st {
|
||||||
|
est = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if est {
|
||||||
|
if err := c.sc.StartTLS(c.tlsconfig); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, c.enc = c.sc.TLSConnectionState()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// auth will try to perform SMTP AUTH if requested
|
// auth will try to perform SMTP AUTH if requested
|
||||||
func (c *Client) auth() error {
|
func (c *Client) auth() error {
|
||||||
if err := c.checkConn(); err != nil {
|
if err := c.checkConn(); err != nil {
|
||||||
|
|
|
@ -24,6 +24,7 @@ func main() {
|
||||||
m.ToIgnoreInvalid("test@test.de", "foo@bar.de", "blubb@blah.com")
|
m.ToIgnoreInvalid("test@test.de", "foo@bar.de", "blubb@blah.com")
|
||||||
m.CcIgnoreInvalid("cc@test.de", "bar.de", "cc@blah.com")
|
m.CcIgnoreInvalid("cc@test.de", "bar.de", "cc@blah.com")
|
||||||
m.BccIgnoreInvalid("bcc@test.de", "bcc@blah.com")
|
m.BccIgnoreInvalid("bcc@test.de", "bcc@blah.com")
|
||||||
|
m.SetHeader("Foo", "bar")
|
||||||
m.SetMessageID()
|
m.SetMessageID()
|
||||||
m.SetDate()
|
m.SetDate()
|
||||||
m.SetBulk()
|
m.SetBulk()
|
||||||
|
|
10
header.go
10
header.go
|
@ -8,6 +8,12 @@ type AddrHeader string
|
||||||
|
|
||||||
// List of common generic header field names
|
// List of common generic header field names
|
||||||
const (
|
const (
|
||||||
|
// HeaderContentLang is the "Content-Language" header
|
||||||
|
HeaderContentLang Header = "Content-Language"
|
||||||
|
|
||||||
|
// HeaderContentType is the "Content-Type" header
|
||||||
|
HeaderContentType Header = "Content-Type"
|
||||||
|
|
||||||
// HeaderDate represents the "Date" field
|
// HeaderDate represents the "Date" field
|
||||||
// See: https://www.rfc-editor.org/rfc/rfc822#section-5.1
|
// See: https://www.rfc-editor.org/rfc/rfc822#section-5.1
|
||||||
HeaderDate Header = "Date"
|
HeaderDate Header = "Date"
|
||||||
|
@ -16,6 +22,10 @@ const (
|
||||||
// See: https://www.rfc-editor.org/rfc/rfc1036#section-2.1.5
|
// See: https://www.rfc-editor.org/rfc/rfc1036#section-2.1.5
|
||||||
HeaderMessageID Header = "Message-ID"
|
HeaderMessageID Header = "Message-ID"
|
||||||
|
|
||||||
|
// HeaderMIMEVersion represents the "MIME-Version" field as per RFC 2045
|
||||||
|
// See: https://datatracker.ietf.org/doc/html/rfc2045#section-4
|
||||||
|
HeaderMIMEVersion Header = "MIME-Version"
|
||||||
|
|
||||||
// HeaderPrecedence is the "Precedence" genHeader field
|
// HeaderPrecedence is the "Precedence" genHeader field
|
||||||
HeaderPrecedence Header = "Precedence"
|
HeaderPrecedence Header = "Precedence"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue