diff --git a/go.mod b/go.mod index ce4861e3f..d5897ed80 100644 --- a/go.mod +++ b/go.mod @@ -78,7 +78,7 @@ require ( github.com/thejerf/suture/v4 v4.0.2 github.com/tus/tusd v1.12.1 github.com/urfave/cli/v2 v2.25.7 - github.com/xhit/go-simple-mail/v2 v2.15.0 + github.com/xhit/go-simple-mail/v2 v2.16.0 go-micro.dev/v4 v4.9.0 go.etcd.io/bbolt v1.3.7 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.1-0.20230608065455-5cc3715df180 diff --git a/go.sum b/go.sum index bbb5b15d5..7e41b8342 100644 --- a/go.sum +++ b/go.sum @@ -1843,8 +1843,8 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xhit/go-simple-mail/v2 v2.15.0 h1:qMXeqcZErUW/Dw6EXxmPuxHzVI8MdxWnEnu2xcisohU= -github.com/xhit/go-simple-mail/v2 v2.15.0/go.mod h1:b7P5ygho6SYE+VIqpxA6QkYfv4teeyG4MKqB3utRu98= +github.com/xhit/go-simple-mail/v2 v2.16.0 h1:ouGy/Ww4kuaqu2E2UrDw7SvLaziWTB60ICLkIkNVccA= +github.com/xhit/go-simple-mail/v2 v2.16.0/go.mod h1:b7P5ygho6SYE+VIqpxA6QkYfv4teeyG4MKqB3utRu98= github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= diff --git a/vendor/github.com/xhit/go-simple-mail/v2/README.md b/vendor/github.com/xhit/go-simple-mail/v2/README.md index 54b58c977..e7f00ec87 100644 --- a/vendor/github.com/xhit/go-simple-mail/v2/README.md +++ b/vendor/github.com/xhit/go-simple-mail/v2/README.md @@ -78,6 +78,8 @@ Go Simple Mail supports: - Support add a List-Unsubscribe header (since v2.11.0) - Support to add a DKIM signarure (since v2.11.0) - Support to send using custom connection, ideal for proxy (since v2.15.0) +- Support Delivery Status Notification (DSN) (since v2.16.0) +- Support text/x-amp-html content type body (since v2.16.0) ## Documentation @@ -203,6 +205,9 @@ func main() { // add inline email.Attach(&mail.File{FilePath: "/path/to/image.png", Name:"Gopher.png", Inline: true}) + // also you can set Delivery Status Notification (DSN) (only is set when server supports DSN) + email.SetDSN([]mail.DSN{mail.SUCCESS, mail.FAILURE}, false) + // you can add dkim signature to the email. // to add dkim, you need a private key already created one. if privateKey != "" { diff --git a/vendor/github.com/xhit/go-simple-mail/v2/email.go b/vendor/github.com/xhit/go-simple-mail/v2/email.go index c590edc07..33acf337e 100644 --- a/vendor/github.com/xhit/go-simple-mail/v2/email.go +++ b/vendor/github.com/xhit/go-simple-mail/v2/email.go @@ -18,22 +18,24 @@ import ( // Email represents an email message. type Email struct { - from string - sender string - replyTo string - returnPath string - recipients []string - headers textproto.MIMEHeader - parts []part - attachments []*File - inlines []*File - Charset string - Encoding encoding - Error error - SMTPServer *smtpClient - DkimMsg string - AllowDuplicateAddress bool - AddBccToHeader bool + from string + sender string + replyTo string + returnPath string + recipients []string + headers textproto.MIMEHeader + parts []part + attachments []*File + inlines []*File + Charset string + Encoding encoding + Error error + SMTPServer *smtpClient + DkimMsg string + AllowDuplicateAddress bool + AddBccToHeader bool + preserveOriginalRecipient bool + dsn []DSN } /* @@ -59,10 +61,13 @@ type SMTPServer struct { // SMTPClient represents a SMTP Client for send email type SMTPClient struct { - mu sync.Mutex - Client *smtpClient - KeepAlive bool - SendTimeout time.Duration + mu sync.Mutex + Client *smtpClient + SendTimeout time.Duration + KeepAlive bool + hasDSNExt bool + preserveOriginalRecipient bool + dsn []DSN } // part represents the different content parts of an email body. @@ -122,9 +127,11 @@ const ( TextHTML // TextCalendar sets body type to text/calendar in message body TextCalendar + // TextAMP sets body type to text/x-amp-html in message body + TextAMP ) -var contentTypes = [...]string{"text/plain", "text/html", "text/calendar"} +var contentTypes = [...]string{"text/plain", "text/html", "text/calendar", "text/x-amp-html"} func (contentType ContentType) string() string { return contentTypes[contentType] @@ -158,6 +165,34 @@ func (at AuthType) String() string { } } +/* + DSN notifications + +- 'NEVER' under no circumstances a DSN must be returned to the sender. If you use NEVER all other notifications will be ignored. + +- 'SUCCESS' will notify you when your mail has arrived at its destination. + +- 'FAILURE' will arrive if an error occurred during delivery. + +- 'DELAY' will notify you if there is an unusual delay in delivery, but the actual delivery's outcome (success or failure) is not yet decided. + +see https://tools.ietf.org/html/rfc3461 See section 4.1 for more information about NOTIFY +*/ +type DSN int + +const ( + NEVER DSN = iota + FAILURE + DELAY + SUCCESS +) + +var dsnTypes = [...]string{"NEVER", "FAILURE", "DELAY", "SUCCESS"} + +func (dsn DSN) String() string { + return dsnTypes[dsn] +} + // NewMSG creates a new email. It uses UTF-8 by default. All charsets: http://webcheatsheet.com/HTML/character_sets_list.php func NewMSG() *Email { email := &Email{ @@ -384,18 +419,18 @@ func addAddress(addressList []string, address string, allowDuplicateAddress bool return append(addressList, address), nil } -type priority int +type Priority int const ( - // PriorityLow sets the email priority to Low - PriorityLow priority = iota - // PriorityHigh sets the email priority to High + // PriorityLow sets the email Priority to Low + PriorityLow Priority = iota + // PriorityHigh sets the email Priority to High PriorityHigh ) -// SetPriority sets the email message priority. Use with +// SetPriority sets the email message Priority. Use with // either "High" or "Low". -func (email *Email) SetPriority(priority priority) *Email { +func (email *Email) SetPriority(priority Priority) *Email { if email.Error != nil { return email } @@ -613,6 +648,20 @@ func (email *Email) AddAlternativeData(contentType ContentType, body []byte) *Em return email } +// SetDSN sets the delivery status notification list, only is set when SMTP server supports DSN extension +// +// To preserve the original recipient of an email message, for example, if it is forwarded to another address, set preserveOriginalRecipient to true +func (email *Email) SetDSN(dsn []DSN, preserveOriginalRecipient bool) *Email { + if email.Error != nil { + return email + } + + email.dsn = dsn + email.preserveOriginalRecipient = preserveOriginalRecipient + + return email +} + // GetFrom returns the sender of the email, if any func (email *Email) GetFrom() string { from := email.returnPath @@ -710,6 +759,9 @@ func (email *Email) SendEnvelopeFrom(from string, client *SMTPClient) error { msg = email.GetMessage() } + client.dsn = email.dsn + client.preserveOriginalRecipient = email.preserveOriginalRecipient + return send(from, email.recipients, msg, client) } @@ -864,10 +916,13 @@ func (server *SMTPServer) Connect() (*SMTPClient, error) { } } + _, hasDSN := c.ext["DSN"] + return &SMTPClient{ Client: c, KeepAlive: server.KeepAlive, SendTimeout: server.SendTimeout, + hasDSNExt: hasDSN, }, server.validateAuth(c) } @@ -965,9 +1020,31 @@ func sendMailProcess(from string, to []string, msg string, c *SMTPClient) error return err } + var dsn string + var dsnSet bool + + if c.hasDSNExt && len(c.dsn) > 0 { + dsn = " NOTIFY=" + if hasNeverDSN(c.dsn) { + dsn += NEVER.String() + } else { + dsn += strings.Join(dsnToString(c.dsn), ",") + } + + if c.preserveOriginalRecipient { + dsn += " ORCPT=rfc822;" + } + + dsnSet = true + } + // Set the recipients for _, address := range to { - if err := c.Client.rcpt(address); err != nil { + if dsnSet && c.preserveOriginalRecipient { + dsn += address + } + + if err := c.Client.rcpt(address, dsn); err != nil { return err } } @@ -1001,3 +1078,20 @@ func checkKeepAlive(client *SMTPClient) { client.Close() } } + +func hasNeverDSN(dsnList []DSN) bool { + for i := range dsnList { + if dsnList[i] == NEVER { + return true + } + } + return false +} + +func dsnToString(dsnList []DSN) []string { + dsnString := make([]string, len(dsnList)) + for i := range dsnList { + dsnString[i] = dsnList[i].String() + } + return dsnString +} diff --git a/vendor/github.com/xhit/go-simple-mail/v2/smtp.go b/vendor/github.com/xhit/go-simple-mail/v2/smtp.go index b2187f3f0..41d136f6d 100644 --- a/vendor/github.com/xhit/go-simple-mail/v2/smtp.go +++ b/vendor/github.com/xhit/go-simple-mail/v2/smtp.go @@ -244,11 +244,11 @@ func (c *smtpClient) mail(from string, extArgs ...map[string]string) error { // rcpt issues a RCPT command to the server using the provided email address. // A call to Rcpt must be preceded by a call to Mail and may be followed by // a Data call or another Rcpt call. -func (c *smtpClient) rcpt(to string) error { +func (c *smtpClient) rcpt(to, dsn string) error { if err := validateLine(to); err != nil { return err } - _, _, err := c.cmd(25, "RCPT TO:<%s>", to) + _, _, err := c.cmd(25, "RCPT TO:<%s>%s", to, dsn) return err } diff --git a/vendor/modules.txt b/vendor/modules.txt index 8c99b3dba..2e52b0a79 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1689,7 +1689,7 @@ github.com/xeipuuv/gojsonpointer # github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 ## explicit github.com/xeipuuv/gojsonreference -# github.com/xhit/go-simple-mail/v2 v2.15.0 +# github.com/xhit/go-simple-mail/v2 v2.16.0 ## explicit; go 1.13 github.com/xhit/go-simple-mail/v2 # github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e