GoLang SMTP server and client implementation
- Go 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
Go check / check-go (push) Successful in 35s
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [github.com/emersion/go-sasl](https://github.com/emersion/go-sasl) | require | digest | `e73c9f7` → `b788ff2` | --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xNC42IiwidXBkYXRlZEluVmVyIjoiNDQuMTQuNiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Reviewed-on: #2 |
||
| .forgejo/workflows | ||
| backendutil | ||
| .gitignore | ||
| backend.go | ||
| client.go | ||
| client_test.go | ||
| conn.go | ||
| data.go | ||
| example_test.go | ||
| go.mod | ||
| go.sum | ||
| lengthlimit_reader.go | ||
| LICENSE | ||
| lmtp_server_test.go | ||
| logger.go | ||
| parse.go | ||
| README.md | ||
| renovate.json | ||
| server.go | ||
| server_test.go | ||
| smtp.go | ||
gosmtp 📬
An ESMTP client and server library written in Go. (Originally forked from https://github.com/emersion/go-smtp)
Features
- ESMTP client & server implementing RFC 5321
- Support for SMTP AUTH and PIPELINING
- UTF-8 support for subject and message
- LMTP support
Usage
Client
package main
import (
"log"
"strings"
"github.com/emersion/go-sasl"
"git.foxden.network/FoxDen/gosmtp"
)
func main() {
// Setup authentication information.
auth := sasl.NewPlainClient("", "user@example.com", "password")
// Connect to the server, authenticate, set the sender and recipient,
// and send the email all in one step.
to := []string{"recipient@example.net"}
msg := strings.NewReader("To: recipient@example.net\r\n" +
"Subject: discount Gophers!\r\n" +
"\r\n" +
"This is the email body.\r\n")
err := smtp.SendMail("mail.example.com:25", auth, "sender@example.org", to, msg)
if err != nil {
log.Fatal(err)
}
}
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:
package main
import (
"log"
"strings"
"git.foxden.network/FoxDen/gosmtp"
)
func main() {
// Setup an unencrypted connection to a local mail server.
c, err := smtp.Dial("localhost:25")
if err != nil {
return err
}
defer c.Close()
// Set the sender and recipient, and send the email all in one step.
to := []string{"recipient@example.net"}
msg := strings.NewReader("To: recipient@example.net\r\n" +
"Subject: discount Gophers!\r\n" +
"\r\n" +
"This is the email body.\r\n")
err := c.SendMail("sender@example.org", to, msg)
if err != nil {
log.Fatal(err)
}
}
Server
package main
import (
"errors"
"io"
"log"
"time"
"git.foxden.network/FoxDen/gosmtp"
)
// The Backend implements SMTP server methods.
type Backend struct{}
func (bkd *Backend) NewSession(_ *smtp.Conn) (smtp.Session, error) {
return &Session{}, nil
}
// A Session is returned after EHLO.
type Session struct{}
func (s *Session) AuthPlain(username, password string) error {
if username != "username" || password != "password" {
return errors.New("invalid username or password")
}
return nil
}
func (s *Session) Mail(from string, opts *smtp.MailOptions) error {
log.Println("Mail from:", from)
return nil
}
func (s *Session) Rcpt(to string) error {
log.Println("Rcpt to:", to)
return nil
}
func (s *Session) Data(r io.Reader) error {
if b, err := io.ReadAll(r); err != nil {
return err
} else {
log.Println("Data:", string(b))
}
return nil
}
func (s *Session) Reset() {}
func (s *Session) Logout() error {
return nil
}
func main() {
be := &Backend{}
s := smtp.NewServer(be)
s.Addr = ":1025"
s.Domain = "localhost"
s.ReadTimeout = 10 * time.Second
s.WriteTimeout = 10 * time.Second
s.MaxMessageBytes = 1024 * 1024
s.MaxRecipients = 50
s.AllowInsecureAuth = true
log.Println("Starting server at", s.Addr)
if err := s.ListenAndServe(); err != nil {
log.Fatal(err)
}
}
You can use the server manually with telnet:
$ telnet localhost 1025
EHLO localhost
AUTH PLAIN
AHVzZXJuYW1lAHBhc3N3b3Jk
MAIL FROM:<root@nsa.gov>
RCPT TO:<root@gchq.gov.uk>
DATA
Hey <3
.
Relationship with net/smtp
The Go standard library provides a SMTP client implementation in net/smtp.
However net/smtp is frozen: it's not getting any new features. go-smtp
provides a server implementation and a number of client improvements.
Licence
MIT