Skip to content

Commit

Permalink
Adding low level SendMail function to Client.
Browse files Browse the repository at this point in the history
  • Loading branch information
petersanchez authored and emersion committed Nov 3, 2021
1 parent 62f6b38 commit ee233dd
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 22 deletions.
35 changes: 34 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,40 @@ func main() {
}
```

If you need more control, you can use `Client` instead.
If you need more control, you can use `Client` instead. For example, if you
want to send an email via a server without TLS or auth support, you can do
something like this:

```go
package main

import (
"log"
"strings"

"github.com/emersion/go-smtp"
)

func main() {
// Setup connection to mail server, return Client instance
c, err := smtp.Dial("mail.example.com:25")
if err != nil {
return err
}
defer c.Close()

// Set the sender and recipient, and send the email all in one step.
to := []string{"[email protected]"}
msg := strings.NewReader("To: [email protected]\r\n" +
"Subject: discount Gophers!\r\n" +
"\r\n" +
"This is the email body.\r\n")
err := c.SendMail("[email protected]", to, msg)
if err != nil {
log.Fatal(err)
}
}
```

### Server

Expand Down
63 changes: 42 additions & 21 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,46 @@ func (c *Client) LMTPData(statusCb func(rcpt string, status *SMTPError)) (io.Wri
return &dataCloser{c, c.Text.DotWriter(), statusCb}, nil
}

// SendMail will use an existing connection to send an email from
// address from, to addresses to, with message r.
//
// This function does not start TLS, nor does it perform authentication. Use
// StartTLS and Auth before-hand if desirable.
//
// The addresses in the to parameter are the SMTP RCPT addresses.
//
// The r parameter should be an RFC 822-style email with headers
// first, a blank line, and then the message body. The lines of r
// should be CRLF terminated. The r headers should usually include
// fields such as "From", "To", "Subject", and "Cc". Sending "Bcc"
// messages is accomplished by including an email address in the to
// parameter but not including it in the r headers.
func (c *Client) SendMail(from string, to []string, r io.Reader) error {
var err error

if err = c.Mail(from, nil); err != nil {
return err
}
for _, addr := range to {
if err = c.Rcpt(addr); err != nil {
return err
}
}
w, err := c.Data()
if err != nil {
return err
}
_, err = io.Copy(w, r)
if err != nil {
return err
}
err = w.Close()
if err != nil {
return err
}
return c.Quit()
}

var testHookStartTLS func(*tls.Config) // nil, except for tests

// SendMail connects to the server at addr, switches to TLS, authenticates with
Expand Down Expand Up @@ -539,6 +579,7 @@ func SendMail(addr string, a sasl.Client, from string, to []string, r io.Reader)
return err
}
defer c.Close()

if err = c.hello(); err != nil {
return err
}
Expand All @@ -556,27 +597,7 @@ func SendMail(addr string, a sasl.Client, from string, to []string, r io.Reader)
return err
}
}
if err = c.Mail(from, nil); err != nil {
return err
}
for _, addr := range to {
if err = c.Rcpt(addr); err != nil {
return err
}
}
w, err := c.Data()
if err != nil {
return err
}
_, err = io.Copy(w, r)
if err != nil {
return err
}
err = w.Close()
if err != nil {
return err
}
return c.Quit()
return c.SendMail(from, to, r)
}

// Extension reports whether an extension is support by the server.
Expand Down

0 comments on commit ee233dd

Please sign in to comment.