Skip to content

imapclient v2.0.0-beta.4: cannot execute commands after Idle.Close() #668

@LilKirill00

Description

@LilKirill00

When trying to close Idle() the program goes into deadlock

log terminal: run.log
Line 43 is output and nothing works after it (49 lines are not output).

log imap: wireshark.log
As you can see, Done and Noop are executed and answered, but the terminal does not output OK IDLE done.

If you try to run idleCmd.Wait() after idleCmd.Close(), the program also goes into a deadlock as with any other command (for example, we took Noop()).
If you run return after idleCmd.Close(), then only then will you see OK IDLE done in the terminal.

package main

import (
	"crypto/tls"
	"log"
	"strconv"

	"github.com/emersion/go-imap/v2/imapclient"
)

func main() {
	// config
	const (
		Server   = "imap.mail.**"
		Port     = 993
		Login    = "************@mail.**"
		Password = "**********"
	)

	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)

	idleCmd := &imapclient.IdleCommand{}

	c := &imapclient.Client{}
	options := imapclient.Options{
		TLSConfig: &tls.Config{
			ServerName:         Server,
			InsecureSkipVerify: true,
		},
		DebugWriter: log.Writer(),
		UnilateralDataHandler: &imapclient.UnilateralDataHandler{
			Mailbox: func(data *imapclient.UnilateralDataMailbox) {
				if data.NumMessages != nil {
					log.Printf("[INFO] a new message has been received")

					log.Print("[DEBUG] idleCmd.Close 1")
					err := idleCmd.Close()
					if err != nil {
						log.Printf("failed 1 done Idle: %v", err)
						return
					}

					log.Print("[DEBUG] c.Noop.Wait")
					err = c.Noop().Wait()
					if err != nil {
						log.Printf("failed to noop: %v", err)
						return
					}
					log.Print("[DEBUG] c.Noop end")
				}
			},
		},
	}

	addr := Server + ":" + strconv.Itoa(Port)
	log.Print("[DEBUG] imapclient.DialTLS")
	c, err := imapclient.DialTLS(addr, &options)
	if err != nil {
		log.Printf("failed to dial IMAP server: %v", err)
		return
	}
	defer c.Close()

	log.Print("[DEBUG] c.Login")
	if err := c.Login(Login, Password).Wait(); err != nil {
		log.Printf("failed to login: %v", err)
		return
	}
	log.Print("[DEBUG] c.Select")
	if _, err := c.Select("INBOX", nil).Wait(); err != nil {
		log.Printf("failed to select INBOX: %v", err)
		return
	}

	// Start idling
	log.Print("[DEBUG] c.Idle")
	idleCmd, err = c.Idle()
	if err != nil {
		log.Printf("IDLE command failed: %v", err)
		return
	}
	defer idleCmd.Close()

	err = idleCmd.Wait()
	if err != nil {
		log.Printf("failed to idleCmd.Wait: %v", err)
		return
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions