mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-22 13:50:49 +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" />
|
||||
</component>
|
||||
<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$/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$/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$/mailmsg.go" beforeDir="false" afterPath="$PROJECT_DIR$/mailmsg.go" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
|
@ -97,7 +96,8 @@
|
|||
<MESSAGE value="Progress" />
|
||||
<MESSAGE value="Implemented SMTP AUTH" />
|
||||
<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 name="VgoProject">
|
||||
<integration-enabled>true</integration-enabled>
|
||||
|
|
|
@ -16,6 +16,7 @@ mail and SMTP related tasks.
|
|||
Some of the features of this library:
|
||||
* [X] Only Standard Library dependant
|
||||
* [X] Modern, idiotmatic Go
|
||||
* [X] Sane and secure defaults
|
||||
* [X] SSL/TLS support
|
||||
* [X] StartTLS support with different policies
|
||||
* [X] Makes use of contexts for a better control flow and timeout/cancelation handling
|
||||
|
|
60
client.go
60
client.go
|
@ -12,11 +12,17 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// Defaults
|
||||
const (
|
||||
// DefaultPort is the default connection port cto the SMTP server
|
||||
const DefaultPort = 25
|
||||
DefaultPort = 25
|
||||
|
||||
// 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
|
||||
type Client struct {
|
||||
|
@ -84,8 +90,8 @@ func NewClient(h string, o ...Option) (*Client, error) {
|
|||
cto: DefaultTimeout,
|
||||
host: h,
|
||||
port: DefaultPort,
|
||||
tlspolicy: TLSMandatory,
|
||||
tlsconfig: &tls.Config{ServerName: h},
|
||||
tlspolicy: DefaultTLSPolicy,
|
||||
}
|
||||
|
||||
// Set default HELO/EHLO hostname
|
||||
|
@ -257,28 +263,9 @@ func (c *Client) DialWithContext(pc context.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
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 {
|
||||
if err := c.tls(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, c.enc = c.sc.TLSConnectionState()
|
||||
}
|
||||
|
||||
if err := c.auth(); err != nil {
|
||||
return err
|
||||
|
@ -333,6 +320,33 @@ func (c *Client) checkConn() error {
|
|||
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
|
||||
func (c *Client) auth() error {
|
||||
if err := c.checkConn(); err != nil {
|
||||
|
|
|
@ -24,6 +24,7 @@ func main() {
|
|||
m.ToIgnoreInvalid("test@test.de", "foo@bar.de", "blubb@blah.com")
|
||||
m.CcIgnoreInvalid("cc@test.de", "bar.de", "cc@blah.com")
|
||||
m.BccIgnoreInvalid("bcc@test.de", "bcc@blah.com")
|
||||
m.SetHeader("Foo", "bar")
|
||||
m.SetMessageID()
|
||||
m.SetDate()
|
||||
m.SetBulk()
|
||||
|
|
10
header.go
10
header.go
|
@ -8,6 +8,12 @@ type AddrHeader string
|
|||
|
||||
// List of common generic header field names
|
||||
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
|
||||
// See: https://www.rfc-editor.org/rfc/rfc822#section-5.1
|
||||
HeaderDate Header = "Date"
|
||||
|
@ -16,6 +22,10 @@ const (
|
|||
// See: https://www.rfc-editor.org/rfc/rfc1036#section-2.1.5
|
||||
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 Header = "Precedence"
|
||||
|
||||
|
|
Loading…
Reference in a new issue