mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-23 14:10:50 +01:00
Compare commits
No commits in common. "8ee37abca2f15097e1a8315f2ee94b4cb0a50478" and "a747f5f74c1dc0cea206a189975acae33288f6be" have entirely different histories.
8ee37abca2
...
a747f5f74c
9 changed files with 100 additions and 91 deletions
2
.github/workflows/codecov.yml
vendored
2
.github/workflows/codecov.yml
vendored
|
@ -39,7 +39,7 @@ jobs:
|
||||||
go: ['1.20', '1.21', '1.22', '1.23']
|
go: ['1.20', '1.21', '1.22', '1.23']
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
|
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
|
|
8
.github/workflows/codeql-analysis.yml
vendored
8
.github/workflows/codeql-analysis.yml
vendored
|
@ -45,7 +45,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
|
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ jobs:
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7
|
uses: github/codeql-action/init@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
|
@ -65,7 +65,7 @@ jobs:
|
||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7
|
uses: github/codeql-action/autobuild@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 https://git.io/JvXDl
|
# 📚 https://git.io/JvXDl
|
||||||
|
@ -79,4 +79,4 @@ jobs:
|
||||||
# make release
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7
|
uses: github/codeql-action/analyze@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6
|
||||||
|
|
2
.github/workflows/dependency-review.yml
vendored
2
.github/workflows/dependency-review.yml
vendored
|
@ -21,7 +21,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
|
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
|
|
2
.github/workflows/golangci-lint.yml
vendored
2
.github/workflows/golangci-lint.yml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
|
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
|
|
2
.github/workflows/govulncheck.yml
vendored
2
.github/workflows/govulncheck.yml
vendored
|
@ -14,7 +14,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
|
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
- name: Run govulncheck
|
- name: Run govulncheck
|
||||||
|
|
2
.github/workflows/reuse.yml
vendored
2
.github/workflows/reuse.yml
vendored
|
@ -14,7 +14,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
|
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
|
|
4
.github/workflows/scorecards.yml
vendored
4
.github/workflows/scorecards.yml
vendored
|
@ -35,7 +35,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
|
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
|
@ -75,6 +75,6 @@ jobs:
|
||||||
|
|
||||||
# Upload the results to GitHub's code scanning dashboard.
|
# Upload the results to GitHub's code scanning dashboard.
|
||||||
- name: "Upload to code-scanning"
|
- name: "Upload to code-scanning"
|
||||||
uses: github/codeql-action/upload-sarif@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7
|
uses: github/codeql-action/upload-sarif@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
|
|
2
.github/workflows/sonarqube.yml
vendored
2
.github/workflows/sonarqube.yml
vendored
|
@ -27,7 +27,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
|
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
|
||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
|
|
167
client_120.go
167
client_120.go
|
@ -24,87 +24,96 @@ func (c *Client) Send(messages ...*Msg) (returnErr error) {
|
||||||
returnErr = errors.Join(errs...)
|
returnErr = errors.Join(errs...)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for id, message := range messages {
|
for msgid, message := range messages {
|
||||||
if sendErr := c.sendSingleMsg(message); sendErr != nil {
|
message.sendError = nil
|
||||||
messages[id].sendError = sendErr
|
if message.encoding == NoEncoding {
|
||||||
errs = append(errs, sendErr)
|
if ok, _ := c.smtpClient.Extension("8BITMIME"); !ok {
|
||||||
|
message.sendError = &SendError{Reason: ErrNoUnencoded, isTemp: false}
|
||||||
|
errs = append(errs, message.sendError)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
from, err := message.GetSender(false)
|
||||||
|
if err != nil {
|
||||||
|
message.sendError = &SendError{Reason: ErrGetSender, errlist: []error{err}, isTemp: isTempError(err),
|
||||||
|
affectedMsg: messages[msgid]}
|
||||||
|
errs = append(errs, message.sendError)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rcpts, err := message.GetRecipients()
|
||||||
|
if err != nil {
|
||||||
|
message.sendError = &SendError{Reason: ErrGetRcpts, errlist: []error{err}, isTemp: isTempError(err),
|
||||||
|
affectedMsg: messages[msgid]}
|
||||||
|
errs = append(errs, message.sendError)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.dsn {
|
||||||
|
if c.dsnmrtype != "" {
|
||||||
|
c.smtpClient.SetDSNMailReturnOption(string(c.dsnmrtype))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = c.smtpClient.Mail(from); err != nil {
|
||||||
|
message.sendError = &SendError{Reason: ErrSMTPMailFrom, errlist: []error{err}, isTemp: isTempError(err)}
|
||||||
|
errs = append(errs, message.sendError)
|
||||||
|
if resetSendErr := c.smtpClient.Reset(); resetSendErr != nil {
|
||||||
|
errs = append(errs, resetSendErr)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
failed := false
|
||||||
|
rcptSendErr := &SendError{}
|
||||||
|
rcptSendErr.errlist = make([]error, 0)
|
||||||
|
rcptSendErr.rcpt = make([]string, 0)
|
||||||
|
rcptNotifyOpt := strings.Join(c.dsnrntype, ",")
|
||||||
|
c.smtpClient.SetDSNRcptNotifyOption(rcptNotifyOpt)
|
||||||
|
for _, rcpt := range rcpts {
|
||||||
|
if err = c.smtpClient.Rcpt(rcpt); err != nil {
|
||||||
|
rcptSendErr.Reason = ErrSMTPRcptTo
|
||||||
|
rcptSendErr.errlist = append(rcptSendErr.errlist, err)
|
||||||
|
rcptSendErr.rcpt = append(rcptSendErr.rcpt, rcpt)
|
||||||
|
rcptSendErr.isTemp = isTempError(err)
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if failed {
|
||||||
|
if resetSendErr := c.smtpClient.Reset(); resetSendErr != nil {
|
||||||
|
errs = append(errs, resetSendErr)
|
||||||
|
}
|
||||||
|
message.sendError = rcptSendErr
|
||||||
|
errs = append(errs, message.sendError)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
writer, err := c.smtpClient.Data()
|
||||||
|
if err != nil {
|
||||||
|
message.sendError = &SendError{Reason: ErrSMTPData, errlist: []error{err}, isTemp: isTempError(err)}
|
||||||
|
errs = append(errs, message.sendError)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
_, err = message.WriteTo(writer)
|
||||||
|
if err != nil {
|
||||||
|
message.sendError = &SendError{Reason: ErrWriteContent, errlist: []error{err}, isTemp: isTempError(err)}
|
||||||
|
errs = append(errs, message.sendError)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
message.isDelivered = true
|
||||||
|
|
||||||
|
if err = writer.Close(); err != nil {
|
||||||
|
message.sendError = &SendError{Reason: ErrSMTPDataClose, errlist: []error{err}, isTemp: isTempError(err)}
|
||||||
|
errs = append(errs, message.sendError)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = c.Reset(); err != nil {
|
||||||
|
message.sendError = &SendError{Reason: ErrSMTPReset, errlist: []error{err}, isTemp: isTempError(err)}
|
||||||
|
errs = append(errs, message.sendError)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err = c.checkConn(); err != nil {
|
||||||
|
message.sendError = &SendError{Reason: ErrConnCheck, errlist: []error{err}, isTemp: isTempError(err)}
|
||||||
|
errs = append(errs, message.sendError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendSingleMsg sends out a single message and returns an error if the transmission/delivery fails.
|
|
||||||
// It is invoked by the public Send methods
|
|
||||||
func (c *Client) sendSingleMsg(message *Msg) error {
|
|
||||||
if message.encoding == NoEncoding {
|
|
||||||
if ok, _ := c.smtpClient.Extension("8BITMIME"); !ok {
|
|
||||||
return &SendError{Reason: ErrNoUnencoded, isTemp: false}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
from, err := message.GetSender(false)
|
|
||||||
if err != nil {
|
|
||||||
return &SendError{Reason: ErrGetSender, errlist: []error{err}, isTemp: isTempError(err),
|
|
||||||
affectedMsg: message}
|
|
||||||
}
|
|
||||||
rcpts, err := message.GetRecipients()
|
|
||||||
if err != nil {
|
|
||||||
return &SendError{Reason: ErrGetRcpts, errlist: []error{err}, isTemp: isTempError(err),
|
|
||||||
affectedMsg: message}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.dsn {
|
|
||||||
if c.dsnmrtype != "" {
|
|
||||||
c.smtpClient.SetDSNMailReturnOption(string(c.dsnmrtype))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err = c.smtpClient.Mail(from); err != nil {
|
|
||||||
retError := &SendError{Reason: ErrSMTPMailFrom, errlist: []error{err}, isTemp: isTempError(err)}
|
|
||||||
if resetSendErr := c.smtpClient.Reset(); resetSendErr != nil {
|
|
||||||
retError.errlist = append(retError.errlist, resetSendErr)
|
|
||||||
}
|
|
||||||
return retError
|
|
||||||
}
|
|
||||||
failed := false
|
|
||||||
rcptSendErr := &SendError{}
|
|
||||||
rcptSendErr.errlist = make([]error, 0)
|
|
||||||
rcptSendErr.rcpt = make([]string, 0)
|
|
||||||
rcptNotifyOpt := strings.Join(c.dsnrntype, ",")
|
|
||||||
c.smtpClient.SetDSNRcptNotifyOption(rcptNotifyOpt)
|
|
||||||
for _, rcpt := range rcpts {
|
|
||||||
if err = c.smtpClient.Rcpt(rcpt); err != nil {
|
|
||||||
rcptSendErr.Reason = ErrSMTPRcptTo
|
|
||||||
rcptSendErr.errlist = append(rcptSendErr.errlist, err)
|
|
||||||
rcptSendErr.rcpt = append(rcptSendErr.rcpt, rcpt)
|
|
||||||
rcptSendErr.isTemp = isTempError(err)
|
|
||||||
failed = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if failed {
|
|
||||||
if resetSendErr := c.smtpClient.Reset(); resetSendErr != nil {
|
|
||||||
rcptSendErr.errlist = append(rcptSendErr.errlist, resetSendErr)
|
|
||||||
}
|
|
||||||
return rcptSendErr
|
|
||||||
}
|
|
||||||
writer, err := c.smtpClient.Data()
|
|
||||||
if err != nil {
|
|
||||||
return &SendError{Reason: ErrSMTPData, errlist: []error{err}, isTemp: isTempError(err)}
|
|
||||||
}
|
|
||||||
_, err = message.WriteTo(writer)
|
|
||||||
if err != nil {
|
|
||||||
return &SendError{Reason: ErrWriteContent, errlist: []error{err}, isTemp: isTempError(err)}
|
|
||||||
}
|
|
||||||
message.isDelivered = true
|
|
||||||
|
|
||||||
if err = writer.Close(); err != nil {
|
|
||||||
return &SendError{Reason: ErrSMTPDataClose, errlist: []error{err}, isTemp: isTempError(err)}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = c.Reset(); err != nil {
|
|
||||||
return &SendError{Reason: ErrSMTPReset, errlist: []error{err}, isTemp: isTempError(err)}
|
|
||||||
}
|
|
||||||
if err = c.checkConn(); err != nil {
|
|
||||||
return &SendError{Reason: ErrConnCheck, errlist: []error{err}, isTemp: isTempError(err)}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue