jstedfast/MailKit · error · ServiceNotConnectedException

The ImapClient is not connected.

Error message

The ImapClient is not connected.

What it means

MailKit throws ServiceNotConnectedException from ImapFolder.CheckState whenever a folder operation is queued while the owning ImapClient has no active TCP/TLS connection to the IMAP server. CheckState is the gate for every folder command (open, close, create, rename, delete, subscribe), so this error means the command was issued before Connect/Authenticate or after the connection dropped.

Solutions

  1. Check ImapClient.IsConnected before issuing folder operations and reconnect (Connect + Authenticate) if false, then re-open the folder.
  2. Wrap the operation in try/catch for ServiceNotConnectedException and implement a reconnect-and-retry loop.
  3. If operations happen after long idle, keep the connection alive with ImapClient.NoOp() on a timer or reconnect per unit of work.
  4. Ensure Connect() and Authenticate() complete without exception before obtaining/using folder references.
  5. Create a fresh ImapClient per worker instead of sharing one across threads/outages.

Example fix

// before
var folder = client.GetFolder("INBOX");
folder.Open(FolderAccess.ReadWrite);

// after
if (!client.IsConnected)
{
    client.Connect(host, port, SecureSocketOptions.Auto);
    client.Authenticate(user, password);
}
var folder = client.GetFolder("INBOX");
folder.Open(FolderAccess.ReadWrite);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!client.IsConnected) { client.Connect(host, port, SecureSocketOptions.Auto); client.Authenticate(user, pass); }

Type guard

bool CanUseFolder(ImapClient c) => c != null && c.IsConnected && c.IsAuthenticated;

Try / catch

try { folder.Open(FolderAccess.ReadWrite); } catch (ServiceNotConnectedException) { Reconnect(); folder.Open(FolderAccess.ReadWrite); }

Prevention

When it happens

Trigger: Calling ImapFolder.Open/Close/Create/Rename/Delete/Subscribe (or any API that queues those commands) before ImapClient.Connect() succeeds, after ImapClient.Disconnect(), or after the underlying socket was closed by the server/network so Engine.IsConnected is false.

Common situations: Using a cached ImapFolder or ImapClient across a long idle period where the server dropped the connection (RFC auto-logout); forgetting Connect in a code path (e.g. a background job reusing a stale client); connecting on one thread and using folders after the connection was lost.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15). Data as JSON: /api/errors/50ba917a0effbe6a. Report an issue: GitHub.

Appendix: source

Thrown at MailKit/Net/Imap/ImapFolder.cs:163

			case FolderFeature.Annotations: return AnnotationAccess != AnnotationAccess.None;
			case FolderFeature.Metadata: return (Engine.Capabilities & ImapCapabilities.Metadata) != 0;
			case FolderFeature.ModSequences: return supportsModSeq;
			case FolderFeature.QuickResync: return Engine.QResyncEnabled;
			case FolderFeature.Quotas: return (Engine.Capabilities & ImapCapabilities.Quota) != 0;
			case FolderFeature.Sorting: return (Engine.Capabilities & ImapCapabilities.Sort) != 0;
			case FolderFeature.Threading: return (Engine.Capabilities & ImapCapabilities.Thread) != 0;
			case FolderFeature.UTF8: return Engine.UTF8Enabled;
			default: return false;
			}
		}

		void CheckState (bool open, bool rw)
		{
			if (Engine.IsDisposed)
				throw new ObjectDisposedException (nameof (ImapClient));

			if (!Engine.IsConnected)
				throw new ServiceNotConnectedException ("The ImapClient is not connected.");

			if (Engine.State < ImapEngineState.Authenticated)
				throw new ServiceNotAuthenticatedException ("The ImapClient is not authenticated.");

			if (open) {
				var access = rw ? FolderAccess.ReadWrite : FolderAccess.ReadOnly;

				if (!IsOpen || Access < access)
					throw new FolderNotOpenException (FullName, access);
			}
		}

		void CheckAllowIndexes ()
		{
			// Indexes ("Message Sequence Numbers" or MSNs in the RFCs) and * are not stable while MessageNew/MessageExpunge is registered for SELECTED and therefore should not be used
			// https://tools.ietf.org/html/rfc5465#section-5.2
			if (Engine.NotifySelectedNewExpunge)
				throw new InvalidOperationException ("Indexes and '*' cannot be used while MessageNew/MessageExpunge is registered with NOTIFY for SELECTED.");

View on GitHub (pinned to 9d3859a785)