golang轻量级可配置多线程模拟SMTP服务器插件smtpmock的使用
Golang轻量级可配置多线程模拟SMTP服务器插件smtpmock的使用
smtpmock是一个用Go编写的轻量级可配置多线程模拟SMTP服务器,它符合RFC 2821和RFC 5321规范的最小要求,可以模拟任何SMTP服务器行为用于测试环境。
主要特性
- 可配置的多线程RFC兼容SMTP服务器
- 实现最小命令集,根据RFC规范响应命令并为消息添加有效的接收头
- 能够为每个SMTP命令配置行为
- 开箱即用的默认设置,只需配置你需要的部分
- 能够覆盖之前的SMTP命令
- 快速失败场景(当命令不一致或失败时关闭客户端会话)
- 多接收者支持(在一个会话中配置多个RCPT TO命令接收)
- 多消息接收支持
- 服务器活动日志记录
- 支持优雅/强制关闭SMTP模拟服务器
- 零运行时依赖
安装
安装smtpmock:
go get github.com/mocktools/go-smtp-mock/v2
go install github.com/mocktools/go-smtp-mock/v2
在代码中导入smtpmock依赖:
package main
import smtpmock "github.com/mocktools/go-smtp-mock/v2"
使用示例
在Golang生态系统中使用
配置服务器
server := smtpmock.New(smtpmock.ConfigurationAttr{
// 服务器行为配置
HostAddress: "[::]", // 服务器运行的主机地址,默认为"127.0.0.1"
PortNumber: 2525, // 服务器绑定的端口号,未指定时会动态分配
LogToStdout: true, // 启用/禁用标准输出日志,默认为false
LogServerActivity: true, // 启用/禁用服务器活动日志,默认为false
SessionTimeout: 42, // 会话超时时间,默认为30秒
ShutdownTimeout: 5, // 优雅关闭超时时间,默认为1秒
// SMTP命令处理行为配置
IsCmdFailFast: true, // 启用快速失败场景,默认为false
MultipleRcptto: true, // 启用多RCPT TO接收,默认为false
MultipleMessageReceiving: true, // 启用多消息接收,默认为false
// 黑名单和响应延迟配置
BlacklistedHeloDomains: []string{"example1.com", "example2.com"},
BlacklistedMailfromEmails: []string{"bot@olo.com", "robot@molo.com"},
ResponseDelayHelo: 2, // HELO响应延迟秒数
ResponseDelayMailfrom: 2, // MAIL FROM响应延迟秒数
// 自定义消息
MsgGreeting: "msgGreeting", // 自定义服务器欢迎消息
MsgInvalidCmd: "msgInvalidCmd", // 自定义无效命令消息
MsgHeloReceived: "msgHeloReceived", // 自定义HELO接收消息
})
服务器操作示例
package main
import (
"fmt"
"net"
"net/smtp"
"time"
smtpmock "github.com/mocktools/go-smtp-mock/v2"
)
func main() {
// 创建服务器实例
server := smtpmock.New(smtpmock.ConfigurationAttr{
LogToStdout: true,
LogServerActivity: true,
})
// 启动服务器
if err := server.Start(); err != nil {
fmt.Println(err)
}
// 获取服务器地址和端口
hostAddress, portNumber := "127.0.0.1", server.PortNumber()
// 创建SMTP客户端连接
address := fmt.Sprintf("%s:%d", hostAddress, portNumber)
timeout := time.Duration(2) * time.Second
connection, _ := net.DialTimeout("tcp", address, timeout)
client, _ := smtp.NewClient(connection, hostAddress)
client.Hello("example.com")
client.Quit()
client.Close()
// 获取服务器消息
messages := server.Messages()
fmt.Printf("Received messages: %+v\n", messages)
// 停止服务器
if err := server.Stop(); err != nil {
fmt.Println(err)
}
}
使用自定义日志器
package main
import (
"bytes"
"fmt"
smtpmock "github.com/mocktools/go-smtp-mock/v2"
)
// 自定义日志器实现
type customLogger struct {
out *bytes.Buffer
err *bytes.Buffer
}
func (logger *customLogger) InfoActivity(message string) {
logger.out.WriteString(message)
}
func (logger *customLogger) Info(message string) {
logger.out.WriteString(message)
}
func (logger *customLogger) Warning(message string) {
logger.out.WriteString(message)
}
func (logger *customLogger) Error(message string) {
logger.err.WriteString(message)
}
func main() {
server := smtpmock.New(smtpmock.ConfigurationAttr{
LogToStdout: true,
LogServerActivity: true,
})
// 设置自定义日志器
outBuf := &bytes.Buffer{}
errBuf := &bytes.Buffer{}
server.WithLogger(&customLogger{
out: outBuf,
err: errBuf,
})
// 启动和停止服务器
if err := server.Start(); err != nil {
fmt.Println(err)
}
if err := server.Stop(); err != nil {
fmt.Println(err)
}
}
在Ruby生态系统中使用
在Ruby生态系统中,smtpmock可以作为smtp_mock
gem使用,它是smtpmock二进制文件的灵活Ruby包装器。
安装和使用示例:
gem install smtp_mock
bundle exec smtp_mock -i ~
Ruby代码示例:
require 'smtp_mock'
# 启动服务器并配置
smtp_mock_server = SmtpMock.start_server(not_registered_emails: %w[user@olo.com user@molo.com])
# 获取服务器端口
smtp_mock_server.port # => 55640
# 停止服务器
smtp_mock_server.stop! # => true
在任何生态系统中使用
你可以将smtpmock作为二进制文件使用。下载预编译的二进制文件后,使用以下命令启动服务器:
curl -sL https://raw.githubusercontent.com/mocktools/go-smtp-mock/master/script/download.sh | bash
./smtpmock -port=2525 -log
已实现的SMTP命令
id | 命令 | 可序列化 | 可用参数 | 使用示例 |
---|---|---|---|---|
1 | HELO | 否 | 域名, localhost, IP地址 | HELO example.com |
1 | EHLO | 否 | 域名, localhost, IP地址 | EHLO example.com |
2 | MAIL FROM | 是 | 邮箱地址, <邮箱地址> | MAIL FROM: user@domain.com |
3 | RCPT TO | 是 | 邮箱地址, <邮箱地址> | RCPT TO: user@domain.com |
4 | DATA | 是 | - | DATA |
5 | RSET | 是 | - | RSET |
6 | NOOP | 否 | - | NOOP |
7 | QUIT | 否 | - | QUIT |
贡献
欢迎在GitHub上提交错误报告和拉取请求。请遵循贡献者行为准则和我们的贡献指南。
许可证
此Go包是根据MIT许可证条款提供的开源软件。
更多关于golang轻量级可配置多线程模拟SMTP服务器插件smtpmock的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang轻量级可配置多线程模拟SMTP服务器插件smtpmock的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang轻量级可配置多线程SMTP模拟服务器 - smtpmock
smtpmock是一个轻量级的Golang库,用于模拟SMTP服务器行为,非常适合测试电子邮件发送功能的场景。下面我将详细介绍其使用方法和示例代码。
主要特性
- 轻量级且易于配置
- 支持多线程处理
- 可模拟各种SMTP响应
- 支持验证接收的邮件内容
- 提供丰富的钩子函数
安装
go get github.com/mocktools/go-smtp-mock/v2
基础使用示例
package main
import (
"fmt"
"log"
"time"
"github.com/mocktools/go-smtp-mock/v2"
)
func main() {
// 创建SMTP模拟服务器
server := smtpmock.New(smtpmock.ConfigurationAttr{
HostAddress: "127.0.0.1",
PortNumber: 2525,
LogToStdout: true,
LogServerActivity: true,
})
// 启动服务器
if err := server.Start(); err != nil {
log.Fatal(err)
}
// 模拟邮件发送测试代码可以在这里运行
fmt.Println("SMTP Mock Server is running on 127.0.0.1:2525")
// 保持服务器运行
time.Sleep(5 * time.Minute)
// 停止服务器
if err := server.Stop(); err != nil {
log.Fatal(err)
}
}
高级配置示例
package main
import (
"fmt"
"log"
"time"
"github.com/mocktools/go-smtp-mock/v2"
)
func main() {
// 创建具有详细配置的SMTP模拟服务器
server := smtpmock.New(smtpmock.ConfigurationAttr{
HostAddress: "127.0.0.1",
PortNumber: 2525,
LogToStdout: true,
LogServerActivity: true,
MultipleMessageReceiving: true, // 允许接收多条消息
ResponseDelay: 1, // 1秒延迟响应
SessionTimeout: 30, // 30秒会话超时
BlacklistedHeloDomains: []string{"spam.com"}, // 黑名单域名
BlacklistedMailfromEmails: []string{"spammer@example.com"}, // 黑名单发件人
BlacklistedRcpttoEmails: []string{"victim@example.com"}, // 黑名单收件人
})
// 添加消息接收钩子
server.AddOnNewMessageHook(func(message *smtpmock.Message) {
fmt.Printf("Received new message from: %s\n", message.Mailfrom)
fmt.Printf("Subject: %s\n", message.MsgHeaders["Subject"])
fmt.Printf("Body: %s\n", message.MsgData)
})
// 启动服务器
if err := server.Start(); err != nil {
log.Fatal(err)
}
fmt.Println("Advanced SMTP Mock Server is running on 127.0.0.1:2525")
// 保持服务器运行
time.Sleep(10 * time.Minute)
// 停止服务器
if err := server.Stop(); err != nil {
log.Fatal(err)
}
}
测试用例示例
package main_test
import (
"net/smtp"
"testing"
"time"
"github.com/mocktools/go-smtp-mock/v2"
"github.com/stretchr/testify/assert"
)
func TestSMTPSending(t *testing.T) {
// 创建测试服务器
server := smtpmock.New(smtpmock.ConfigurationAttr{
HostAddress: "127.0.0.1",
PortNumber: 5870,
LogToStdout: false,
LogServerActivity: false,
})
// 启动服务器
if err := server.Start(); err != nil {
t.Fatal(err)
}
defer server.Stop()
// 模拟发送邮件
client, err := smtp.Dial("127.0.0.1:5870")
assert.NoError(t, err)
err = client.Mail("sender@example.com")
assert.NoError(t, err)
err = client.Rcpt("recipient@example.com")
assert.NoError(t, err)
wc, err := client.Data()
assert.NoError(t, err)
_, err = wc.Write([]byte("Subject: Test\n\nHello World"))
assert.NoError(t, err)
err = wc.Close()
assert.NoError(t, err)
err = client.Quit()
assert.NoError(t, err)
// 等待服务器处理
time.Sleep(100 * time.Millisecond)
// 验证接收到的消息
messages := server.Messages()
assert.Equal(t, 1, len(messages))
msg := messages[0]
assert.Equal(t, "sender@example.com", msg.Mailfrom)
assert.Equal(t, []string{"recipient@example.com"}, msg.Rcptto)
assert.Contains(t, msg.MsgData, "Hello World")
}
自定义响应
package main
import (
"fmt"
"log"
"github.com/mocktools/go-smtp-mock/v2"
)
func main() {
server := smtpmock.New(smtpmock.ConfigurationAttr{
HostAddress: "127.0.0.1",
PortNumber: 2525,
})
// 自定义EHLO响应
server.SetEhloResponse("example.com", "250-mock-server.example.com\n250-PIPELINING\n250-SIZE 10240000\n250-ENHANCEDSTATUSCODES\n250-8BITMIME\n250-DSN\n250 SMTPUTF8")
// 自定义MAIL FROM响应
server.SetMailfromResponse("250 2.1.0 Sender OK")
// 自定义RCPT TO响应
server.SetRcpttoResponse("250 2.1.5 Recipient OK")
// 自定义DATA响应
server.SetDataResponse("354 End data with <CR><LF>.<CR><LF>")
// 自定义消息接收后的响应
server.SetDataReceivedResponse("250 2.0.0 OK: queued as ABC123")
if err := server.Start(); err != nil {
log.Fatal(err)
}
fmt.Println("Customized SMTP Mock Server is running on 127.0.0.1:2525")
// 保持服务器运行
select {}
}
总结
smtpmock是一个功能强大且灵活的SMTP模拟服务器,特别适合以下场景:
- 单元测试中模拟邮件发送
- 开发环境替代真实SMTP服务器
- 测试邮件发送失败的各种情况
- 验证邮件内容和格式
通过上述示例代码,您可以快速集成smtpmock到您的测试流程中,它提供了丰富的配置选项和钩子函数,可以满足大多数SMTP测试需求。