go-mail/client_120.go
Winni Neessen 63d8cef8ca
Refactor DSN handling from client.go to smtp.go
This PR refactors the the DSN (RFC 1891) SMTP client handling, that was introduced in f4cdc61dd0.

While most of the Client options stay the same, the whole workaround logic for the SMTP client has been removed and added as part of the SMTP client instead.

This was we got rid of the Client's own `mail()`, `rcpt()`, `dsnRcpt()`, `dsnMail()` methods as well as the copies of the `cmd()` and `validateLine()` methods. The Client is now using the proper `Mail()` and `Rcpt()` methods of the SMTP client instead.
2023-01-18 10:30:06 +01:00

110 lines
3 KiB
Go

// SPDX-FileCopyrightText: 2022-2023 The go-mail Authors
//
// SPDX-License-Identifier: MIT
//go:build go1.20
// +build go1.20
package mail
import (
"errors"
"strings"
)
// Send sends out the mail message
func (c *Client) Send(ml ...*Msg) (rerr error) {
if err := c.checkConn(); err != nil {
rerr = &SendError{Reason: ErrConnCheck, errlist: []error{err}, isTemp: isTempError(err)}
return
}
for _, m := range ml {
m.sendError = nil
if m.encoding == NoEncoding {
if ok, _ := c.sc.Extension("8BITMIME"); !ok {
m.sendError = &SendError{Reason: ErrNoUnencoded, isTemp: false}
rerr = errors.Join(rerr, m.sendError)
continue
}
}
f, err := m.GetSender(false)
if err != nil {
m.sendError = &SendError{Reason: ErrGetSender, errlist: []error{err}, isTemp: isTempError(err)}
rerr = errors.Join(rerr, m.sendError)
continue
}
rl, err := m.GetRecipients()
if err != nil {
m.sendError = &SendError{Reason: ErrGetRcpts, errlist: []error{err}, isTemp: isTempError(err)}
rerr = errors.Join(rerr, m.sendError)
continue
}
if c.dsn {
if c.dsnmrtype != "" {
c.sc.SetDSNMailReturnOption(string(c.dsnmrtype))
}
}
if err := c.sc.Mail(f); err != nil {
m.sendError = &SendError{Reason: ErrSMTPMailFrom, errlist: []error{err}, isTemp: isTempError(err)}
rerr = errors.Join(rerr, m.sendError)
if reserr := c.sc.Reset(); reserr != nil {
rerr = errors.Join(rerr, reserr)
}
continue
}
failed := false
rse := &SendError{}
rse.errlist = make([]error, 0)
rse.rcpt = make([]string, 0)
rno := strings.Join(c.dsnrntype, ",")
c.sc.SetDSNRcptNotifyOption(rno)
for _, r := range rl {
if err := c.sc.Rcpt(r); err != nil {
rse.Reason = ErrSMTPRcptTo
rse.errlist = append(rse.errlist, err)
rse.rcpt = append(rse.rcpt, r)
rse.isTemp = isTempError(err)
failed = true
}
}
if failed {
if reserr := c.sc.Reset(); reserr != nil {
rerr = errors.Join(rerr, reserr)
}
m.sendError = rse
rerr = errors.Join(rerr, m.sendError)
continue
}
w, err := c.sc.Data()
if err != nil {
m.sendError = &SendError{Reason: ErrSMTPData, errlist: []error{err}, isTemp: isTempError(err)}
rerr = errors.Join(rerr, m.sendError)
continue
}
_, err = m.WriteTo(w)
if err != nil {
m.sendError = &SendError{Reason: ErrWriteContent, errlist: []error{err}, isTemp: isTempError(err)}
rerr = errors.Join(rerr, m.sendError)
continue
}
if err := w.Close(); err != nil {
m.sendError = &SendError{Reason: ErrSMTPDataClose, errlist: []error{err}, isTemp: isTempError(err)}
rerr = errors.Join(rerr, m.sendError)
continue
}
if err := c.Reset(); err != nil {
m.sendError = &SendError{Reason: ErrSMTPReset, errlist: []error{err}, isTemp: isTempError(err)}
rerr = errors.Join(rerr, m.sendError)
continue
}
if err := c.checkConn(); err != nil {
m.sendError = &SendError{Reason: ErrConnCheck, errlist: []error{err}, isTemp: isTempError(err)}
rerr = errors.Join(rerr, m.sendError)
}
}
return
}