README.md
1# go-smtp
2
3[![GoDoc](https://godoc.org/github.com/emersion/go-smtp?status.svg)](https://godoc.org/github.com/emersion/go-smtp)
4[![builds.sr.ht status](https://builds.sr.ht/~emersion/go-smtp.svg)](https://builds.sr.ht/~emersion/go-smtp?)
5[![codecov](https://codecov.io/gh/emersion/go-smtp/branch/master/graph/badge.svg)](https://codecov.io/gh/emersion/go-smtp)
6
7An ESMTP client and server library written in Go.
8
9## Features
10
11* ESMTP client & server implementing [RFC 5321](https://tools.ietf.org/html/rfc5321)
12* Support for SMTP [AUTH](https://tools.ietf.org/html/rfc4954) and [PIPELINING](https://tools.ietf.org/html/rfc2920)
13* UTF-8 support for subject and message
14* [LMTP](https://tools.ietf.org/html/rfc2033) support
15
16## Usage
17
18### Client
19
20```go
21package main
22
23import (
24 "log"
25 "strings"
26
27 "github.com/emersion/go-sasl"
28 "github.com/emersion/go-smtp"
29)
30
31func main() {
32 // Set up authentication information.
33 auth := sasl.NewPlainClient("", "user@example.com", "password")
34
35 // Connect to the server, authenticate, set the sender and recipient,
36 // and send the email all in one step.
37 to := []string{"recipient@example.net"}
38 msg := strings.NewReader("To: recipient@example.net\r\n" +
39 "Subject: discount Gophers!\r\n" +
40 "\r\n" +
41 "This is the email body.\r\n")
42 err := smtp.SendMail("mail.example.com:25", auth, "sender@example.org", to, msg)
43 if err != nil {
44 log.Fatal(err)
45 }
46}
47```
48
49If you need more control, you can use `Client` instead.
50
51### Server
52
53```go
54package main
55
56import (
57 "errors"
58 "io"
59 "io/ioutil"
60 "log"
61 "time"
62
63 "github.com/emersion/go-smtp"
64)
65
66// The Backend implements SMTP server methods.
67type Backend struct{}
68
69// Login handles a login command with username and password.
70func (bkd *Backend) Login(state *smtp.ConnectionState, username, password string) (smtp.Session, error) {
71 if username != "username" || password != "password" {
72 return nil, errors.New("Invalid username or password")
73 }
74 return &Session{}, nil
75}
76
77// AnonymousLogin requires clients to authenticate using SMTP AUTH before sending emails
78func (bkd *Backend) AnonymousLogin(state *smtp.ConnectionState) (smtp.Session, error) {
79 return nil, smtp.ErrAuthRequired
80}
81
82// A Session is returned after successful login.
83type Session struct{}
84
85func (s *Session) Mail(from string) error {
86 log.Println("Mail from:", from)
87 return nil
88}
89
90func (s *Session) Rcpt(to string) error {
91 log.Println("Rcpt to:", to)
92 return nil
93}
94
95func (s *Session) Data(r io.Reader) error {
96 if b, err := ioutil.ReadAll(r); err != nil {
97 return err
98 } else {
99 log.Println("Data:", string(b))
100 }
101 return nil
102}
103
104func (s *Session) Reset() {}
105
106func (s *Session) Logout() error {
107 return nil
108}
109
110func main() {
111 be := &Backend{}
112
113 s := smtp.NewServer(be)
114
115 s.Addr = ":1025"
116 s.Domain = "localhost"
117 s.ReadTimeout = 10 * time.Second
118 s.WriteTimeout = 10 * time.Second
119 s.MaxMessageBytes = 1024 * 1024
120 s.MaxRecipients = 50
121 s.AllowInsecureAuth = true
122
123 log.Println("Starting server at", s.Addr)
124 if err := s.ListenAndServe(); err != nil {
125 log.Fatal(err)
126 }
127}
128```
129
130You can use the server manually with `telnet`:
131```
132$ telnet localhost 1025
133EHLO localhost
134AUTH PLAIN
135AHVzZXJuYW1lAHBhc3N3b3Jk
136MAIL FROM:<root@nsa.gov>
137RCPT TO:<root@gchq.gov.uk>
138DATA
139Hey <3
140.
141```
142
143## Licence
144
145MIT
146