Golang为何没有原生SMTP服务器功能?
Golang为何没有原生SMTP服务器功能? 我们有 net/http 包,并且我看到还有一个 net/smtp 包,但这似乎只是一个 SMTP 客户端。难道没有原生的 SMTP 服务器可以用来发送电子邮件吗?
此致
承接这个话题,构建SMTP服务器也是一件非常罕见的事情。
几乎所有使用Go语言的人都会在某个阶段构建某种类型的Web服务器。而几乎没有人会使用Go语言去构建SMTP服务器。因此前者被纳入标准库是合理的,但后者则不然。
更多关于Golang为何没有原生SMTP服务器功能?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
SMTP客户端用于发送电子邮件。SMTP服务器则负责接收电子邮件(当然之后可能还会继续转发这些邮件)。
构建SMTP服务器是一项极其庞大的工程,这其中有诸多原因,其中很多都与垃圾邮件和滥用行为相关。标准库中并未提供SMTP服务器。
一般来说,您并不需要SMTP服务器。如果确实需要,请安装现有且备受推崇的解决方案。您绝对不应该尝试自行构建SMTP服务器。
同意Jon的观点,这里有几个用Go语言编写的SMTP服务器,适合追求新潮的人士))
flashmob/go-guerrilla
go-guerrilla - 用Golang编写的迷你SMTP服务器
toorop/tmail
tmail - Golang SMTP服务器
emersion/go-smtp
go-smtp - 📤 用Go编写的SMTP客户端和服务器库
chrj/smtpd
smtpd - Go SMTP服务器库
Go语言标准库中的net/smtp包确实只提供了SMTP客户端功能,而没有内置SMTP服务器实现。这主要是由于以下几个原因:
- 设计哲学:Go语言标准库专注于提供网络协议的基础构建块,而不是完整的应用服务器
- 复杂性:完整的SMTP服务器需要处理认证、队列管理、TLS、反垃圾邮件等复杂功能
- 使用场景:大多数应用只需要发送邮件(客户端功能),而非接收邮件
不过,你可以使用第三方库来构建SMTP服务器。以下是一个使用github.com/flashmob/go-fastcgi-server的简单示例:
package main
import (
"fmt"
"log"
"net"
"strings"
)
type SMTPHandler struct{}
func (h *SMTPHandler) Handle(conn net.Conn) {
defer conn.Close()
// 发送欢迎消息
conn.Write([]byte("220 localhost ESMTP Go SMTP Server\r\n"))
buf := make([]byte, 1024)
for {
n, err := conn.Read(buf)
if err != nil {
break
}
cmd := strings.TrimSpace(string(buf[:n]))
fmt.Printf("Received: %s\n", cmd)
switch {
case strings.HasPrefix(cmd, "HELO"), strings.HasPrefix(cmd, "EHLO"):
conn.Write([]byte("250 Hello\r\n"))
case strings.HasPrefix(cmd, "MAIL FROM"):
conn.Write([]byte("250 OK\r\n"))
case strings.HasPrefix(cmd, "RCPT TO"):
conn.Write([]byte("250 OK\r\n"))
case strings.HasPrefix(cmd, "DATA"):
conn.Write([]byte("354 End data with <CR><LF>.<CR><LF>\r\n"))
case cmd == ".":
conn.Write([]byte("250 OK: Message accepted\r\n"))
case strings.HasPrefix(cmd, "QUIT"):
conn.Write([]byte("221 Bye\r\n"))
return
default:
conn.Write([]byte("500 Command not recognized\r\n"))
}
}
}
func main() {
listener, err := net.Listen("tcp", ":2525")
if err != nil {
log.Fatal(err)
}
defer listener.Close()
handler := &SMTPHandler{}
for {
conn, err := listener.Accept()
if err != nil {
log.Printf("Accept error: %v", err)
continue
}
go handler.Handle(conn)
}
}
对于生产环境,推荐使用更成熟的第三方SMTP服务器库,如:
github.com/flashmob/go-guerrillagithub.com/emersion/go-smtp
以下是使用github.com/emersion/go-smtp的示例:
package main
import (
"log"
"github.com/emersion/go-smtp"
)
type Backend struct{}
func (bkd *Backend) NewSession(_ *smtp.Conn) (smtp.Session, error) {
return &Session{}, nil
}
type Session struct{}
func (s *Session) AuthPlain(username, password string) error {
return nil
}
func (s *Session) Mail(from string, opts *smtp.MailOptions) error {
return nil
}
func (s *Session) Rcpt(to string, opts *smtp.RcptOptions) error {
return nil
}
func (s *Session) Data(r io.Reader) error {
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 SMTP server at :1025")
log.Fatal(s.ListenAndServe())
}
这些第三方库提供了完整的SMTP服务器实现,包括认证、TLS支持等高级功能。

