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 }