diff --git a/email.go b/email.go index 69186ac..b29f487 100644 --- a/email.go +++ b/email.go @@ -12,6 +12,7 @@ import ( "net/mail" "net/textproto" "path/filepath" + "strconv" "time" ) @@ -970,8 +971,15 @@ func send(from string, to []string, msg string, client *SMTPClient) error { } func sendMailProcess(from string, to []string, msg string, c *smtpClient) error { + + cmdArgs := make(map[string]string) + + if _, ok := c.ext["SIZE"]; ok { + cmdArgs["SIZE"] = strconv.Itoa(len(msg)) + } + // Set the sender - if err := c.mail(from); err != nil { + if err := c.mail(from, cmdArgs); err != nil { return err } diff --git a/smtp.go b/smtp.go index 30ba1cf..e9a38bb 100644 --- a/smtp.go +++ b/smtp.go @@ -8,6 +8,7 @@ // SMTPUTF8 RFC 6531 // AUTH RFC 2554 // STARTTLS RFC 3207 +// SIZE RFC 1870 // Additional extensions may be handled by clients using smtp.go in golang source code or pull request Go Simple Mail // smtp.go file is a modification of smtp golang package what is frozen and is not accepting new features. @@ -206,7 +207,14 @@ func (c *smtpClient) authenticate(a auth) error { // If the server supports the SMTPUTF8 extension, Mail adds the // SMTPUTF8 parameter. // This initiates a mail transaction and is followed by one or more Rcpt calls. -func (c *smtpClient) mail(from string) error { +func (c *smtpClient) mail(from string, extArgs ...map[string]string) error { + var args []interface{} + var extMap map[string]string + + if len(extArgs) > 0 { + extMap = extArgs[0] + } + if err := validateLine(from); err != nil { return err } @@ -221,8 +229,15 @@ func (c *smtpClient) mail(from string) error { if _, ok := c.ext["SMTPUTF8"]; ok { cmdStr += " SMTPUTF8" } + if _, ok := c.ext["SIZE"]; ok { + if extMap["SIZE"] != "" { + cmdStr += " SIZE=%s" + args = append(args, extMap["SIZE"]) + } + } } - _, _, err := c.cmd(250, cmdStr, from) + args = append([]interface{}{from}, args...) + _, _, err := c.cmd(250, cmdStr, args...) return err } diff --git a/smtp_test.go b/smtp_test.go index ac331aa..54feead 100644 --- a/smtp_test.go +++ b/smtp_test.go @@ -397,6 +397,52 @@ QUIT } }) + t.Run("ehlo size", func(t *testing.T) { + const ( + basicServer = `250-mx.google.com at your service +250-SIZE 35651584 +250 user@gmail.com OK; can accommodate 500000 byte message +250 Sender OK +221 Goodbye +` + + basicClient = `EHLO localhost +MAIL FROM: SIZE=50000 +QUIT +` + ) + + c, bcmdbuf, cmdbuf := faker(basicServer) + cmdArgs := make(map[string]string) + + if err := c.hi("localhost"); err != nil { + t.Fatalf("EHLO failed: %s", err) + } + if ok, _ := c.extension("SIZE"); !ok { + t.Fatalf("Should support SIZE") + } + if ok, _ := c.extension("SMTPUTF8"); ok { + t.Fatalf("Shouldn't support SMTPUTF8") + } + + if ok, _ := c.extension("SIZE"); ok { + cmdArgs["SIZE"] = "50000" + } + if err := c.mail("user@gmail.com", cmdArgs); err != nil { + t.Fatalf("MAIL FROM failed: %s", err) + } + if err := c.quit(); err != nil { + t.Fatalf("QUIT failed: %s", err) + } + + bcmdbuf.Flush() + actualcmds := cmdbuf.String() + client := strings.Join(strings.Split(basicClient, "\n"), "\r\n") + if client != actualcmds { + t.Fatalf("Got:\n%s\nExpected:\n%s", actualcmds, client) + } + }) + t.Run("ehlo 8bitmime", func(t *testing.T) { const ( basicServer = `250-mx.google.com at your service