fscan/plugins/services/imap/connector.go
ZacharyZcR 4a3f281b6b refactor: 统一Plugins目录大小写为小写
- 将所有Plugins路径重命名为plugins
- 修复Git索引与实际文件系统大小写不一致问题
- 确保跨平台兼容性和路径一致性
2025-08-12 13:08:06 +08:00

133 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package imap
import (
"bufio"
"context"
"crypto/tls"
"fmt"
"io"
"net"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
"github.com/shadow1ng/fscan/plugins/base"
)
// IMAPConnection IMAP连接包装器
type IMAPConnection struct {
conn net.Conn
reader *bufio.Reader
target string
}
// IMAPConnector IMAP连接器实现
type IMAPConnector struct {
host string
port string
}
// NewIMAPConnector 创建IMAP连接器
func NewIMAPConnector() *IMAPConnector {
return &IMAPConnector{}
}
// Connect 连接到IMAP服务
func (c *IMAPConnector) Connect(ctx context.Context, info *common.HostInfo) (interface{}, error) {
c.host = info.Host
c.port = info.Ports
target := fmt.Sprintf("%s:%s", c.host, c.port)
// 根据端口选择连接类型
var conn net.Conn
var err error
if c.port == "993" {
// IMAPS端口使用TLS连接
tlsConfig := &tls.Config{
InsecureSkipVerify: true,
}
conn, err = common.WrapperTlsWithContext(ctx, "tcp", target, tlsConfig)
} else {
// IMAP端口使用普通连接
conn, err = common.WrapperTcpWithContext(ctx, "tcp", target)
}
if err != nil {
return nil, fmt.Errorf("IMAP连接失败: %v", err)
}
reader := bufio.NewReader(conn)
// 设置IMAP特殊超时默认超时时间 + 5秒
imapTimeout := time.Duration(common.Timeout+5) * time.Second
conn.SetReadDeadline(time.Now().Add(imapTimeout))
// 读取IMAP欢迎消息
if _, readErr := reader.ReadString('\n'); readErr != nil {
conn.Close()
return nil, fmt.Errorf("IMAP欢迎消息读取失败: %v", readErr)
}
return &IMAPConnection{
conn: conn,
reader: reader,
target: target,
}, nil
}
// Authenticate 认证
func (c *IMAPConnector) Authenticate(ctx context.Context, conn interface{}, cred *base.Credential) error {
imapConn, ok := conn.(*IMAPConnection)
if !ok {
return fmt.Errorf("无效的连接类型")
}
// 设置IMAP特殊超时默认超时时间 + 5秒
imapTimeout := time.Duration(common.Timeout+5) * time.Second
imapConn.conn.SetDeadline(time.Now().Add(imapTimeout))
// 发送LOGIN命令
loginCmd := fmt.Sprintf("a001 LOGIN \"%s\" \"%s\"\r\n", cred.Username, cred.Password)
_, err := imapConn.conn.Write([]byte(loginCmd))
if err != nil {
return fmt.Errorf("发送登录命令失败: %v", err)
}
// 读取认证响应
for {
select {
case <-ctx.Done():
return fmt.Errorf("IMAP认证超时: %v", ctx.Err())
default:
// 设置读取超时避免无限等待使用IMAP特殊超时
imapTimeout := time.Duration(common.Timeout+5) * time.Second
imapConn.conn.SetReadDeadline(time.Now().Add(imapTimeout))
response, err := imapConn.reader.ReadString('\n')
if err != nil {
if err == io.EOF {
return fmt.Errorf("IMAP认证失败")
}
return fmt.Errorf("读取响应失败: %v", err)
}
if strings.Contains(response, "a001 OK") {
return nil // 认证成功
}
if strings.Contains(response, "a001 NO") || strings.Contains(response, "a001 BAD") {
return fmt.Errorf("IMAP认证失败")
}
}
}
}
// Close 关闭连接
func (c *IMAPConnector) Close(conn interface{}) error {
if imapConn, ok := conn.(*IMAPConnection); ok && imapConn.conn != nil {
return imapConn.conn.Close()
}
return nil
}