Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions imapclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,11 @@ func (c *Client) Mailbox() *SelectedMailbox {
return c.mailbox
}

// Closed returns a channel that is closed when the connection is closed.
func (c *Client) Closed() <-chan struct{} {
return c.decCh
}

// Close immediately closes the connection.
func (c *Client) Close() error {
c.mutex.Lock()
Expand Down
37 changes: 37 additions & 0 deletions imapclient/connection_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package imapclient_test

import (
"testing"
"time"

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

// TestClient_Closed tests that the Closed() channel is closed when the
// connection is explicitly closed via Close().
func TestClient_Closed(t *testing.T) {
client, server := newClientServerPair(t, imap.ConnStateAuthenticated)
defer server.Close()

closedCh := client.Closed()
if closedCh == nil {
t.Fatal("Closed() returned nil channel")
}

select {
case <-closedCh:
t.Fatal("Closed() channel closed before calling Close()")
default: // Expected
}

if err := client.Close(); err != nil {
t.Fatalf("Close() = %v", err)
}

select {
case <-closedCh:
t.Log("Closed() channel properly closed after Close()")
case <-time.After(2 * time.Second):
t.Fatal("Closed() channel not closed after Close()")
}
}
22 changes: 22 additions & 0 deletions imapclient/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,3 +378,25 @@ func ExampleClient_Authenticate_oauth() {
log.Fatalf("authentication failed: %v", err)
}
}

func ExampleClient_Closed() {
c, err := imapclient.DialTLS("mail.example.org:993", nil)
if err != nil {
log.Fatalf("failed to dial IMAP server: %v", err)
}
defer c.Close()

if err := c.Login("root", "asdf").Wait(); err != nil {
log.Fatalf("failed to login: %v", err)
}

// Monitor the connection in a separate goroutine.
go func() {
<-c.Closed()
log.Println("Connection has been closed")
}()

if _, err := c.Select("INBOX", nil).Wait(); err != nil {
log.Fatalf("failed to select INBOX: %v", err)
}
}