{"id":831,"date":"2010-04-15T07:22:42","date_gmt":"2010-04-15T05:22:42","guid":{"rendered":"http:\/\/www.limilabs.com\/blog\/?p=831"},"modified":"2014-02-28T11:28:30","modified_gmt":"2014-02-28T09:28:30","slug":"imap-idle","status":"publish","type":"post","link":"https:\/\/www.limilabs.com\/blog\/imap-idle","title":{"rendered":"IMAP IDLE: instant push email notifications"},"content":{"rendered":"<p><strong>IDLE <\/strong> is an IMAP protocol extension described in <a href=\"\/mail\/rfc\/2177\">RFC 2177<\/a>. It allows an IMAP client to indicate to the server that it is ready to accept <strong>real-time notifications<\/strong> about the changes (e.g. new message) in the currently selected folder.<\/p>\n<p>This feature is not available for every IMAP server. You need to check if your <a href=\"\/blog\/get-supported-server-extensions-imap-pop3-smtp\">IMAP server supports <em>ImapExtension.Idle<\/em> extension<\/a>.<\/p>\n<p>Mail.dll <a href=\"\/mail\">.NET IMAP library<\/a> supports IDLE command.<\/p>\n<p>There are two <em>Imap <\/em>class methods, that allow client to receive notifications:<\/p>\n<ul>\n<li><em>Idle()<\/em> &#8211; starts accepting real-time notifications. The method hangs until the new notification is received.<\/li>\n<li><em>StopIdle()<\/em> &#8211; stops accepting real-time notifications. This method is thread-safe.<\/li>\n<\/ul>\n<p>The following sample connects to an IMAP server and starts to receive notifications. When new message arrives (or an old message is deleted) it displays new message count, then searches IMAP server for unseen messages, downloads them, and displays subjects of all new messages.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nusing (Imap client = new Imap())\r\n{\r\n    client.ConnectSSL(&quot;imap.server.com&quot;);\r\n    client.Login(&quot;user@server.com&quot;, &quot;password&quot;);\r\n\r\n    FolderStatus folderStatus = client.SelectInbox();\r\n    Console.WriteLine(&quot;Total message count: {0}&quot;,\r\n        folderStatus.MessageCount);\r\n\r\n    while(true)\r\n    {\r\n        FolderStatus currentStatus = client.Idle();\r\n        Console.WriteLine(&quot;Total message count: {0}&quot;,\r\n                currentStatus.MessageCount);\r\n        foreach(long uid in client.Search(Flag.Unseen))\r\n        {\r\n            IMail email = new MailBuilder().CreateFromEml(\r\n                client.GetHeadersByUID(uid));\r\n            Console.WriteLine(email.Subject);\r\n        }\r\n    }\r\n    client.Close();\r\n}\r\n<\/pre>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n' VB.NET code\r\n\r\nUsing client As New Imap()\r\n\tclient.ConnectSSL(&quot;imap.server.com&quot;)\r\n\tclient.Login(&quot;user@server.com&quot;, &quot;password&quot;)\r\n\r\n\tDim folderStatus As FolderStatus = client.SelectInbox()\r\n\tConsole.WriteLine(&quot;Total message count: {0}&quot;,_\r\n\t\tfolderStatus.MessageCount)\r\n\r\n\tWhile True\r\n\t\tDim currentStatus As FolderStatus = client.Idle()\r\n\t\tConsole.WriteLine(&quot;Total message count: {0}&quot;,_\r\n\t\t\tcurrentStatus.MessageCount)\r\n\t\tFor Each uid As Long In client.Search(Flag.Unseen)\r\n\t\t\tDim email As IMail = New MailBuilder()_\r\n \t\t\t\t.CreateFromEml(client.GetHeadersByUID(uid))\r\n\t\t\tConsole.WriteLine(email.Subject)\r\n\t\tNext\r\n\tEnd While\r\n\tclient.Close()\r\nEnd Using\r\n<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"\/blog\/wp-content\/uploads\/2010\/04\/idle.png\" alt=\"\" title=\"idle\" width=\"300\" height=\"143\" class=\"aligncenter size-full wp-image-842\" \/><\/p>\n<h2>Stop IDLE gracefully<\/h2>\n<p>In this next sample we&#8217;ll handle stop gracefully. As you can see <em>StopIdle<\/em> method is thread safe. This means that it can be used from any other thread (for example UI thread).<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n\/\/ C# code\r\n\r\nusing (Imap client = new Imap())\r\n{\r\n    client.ConnectSSL(&quot;imap.server.com&quot;);\r\n    client.Login(&quot;user@server.com&quot;, &quot;password&quot;);\r\n\r\n    FolderStatus folderStatus = client.SelectInbox();\r\n    Console.WriteLine(&quot;Total message count: {0}&quot;,\r\n        currentStatus.MessageCount);\r\n\r\n    bool stop = false;\r\n    \/\/ We start a new thread to handle user input, enter = stop idle\r\n    new Thread(() =&gt;\r\n\t{\r\n\t\tConsole.ReadLine();\r\n\t\tclient.StopIdle();\r\n\t\tstop = true;\r\n\t}).Start();\r\n\r\n    while(stop == false)\r\n    {\r\n        FolderStatus currentStatus = client.Idle();\r\n        if (stop == true)\r\n            break;\r\n\r\n        Console.WriteLine(&quot;Total message count: {0}&quot;,\r\n            currentStatus.MessageCount);\r\n\r\n        foreach(long uid in client.Search(Flag.Unseen))\r\n        {\r\n            IMail email = new MailBuilder().CreateFromEml(\r\n                client.GetHeadersByUID(uid));\r\n            Console.WriteLine(email.Subject);\r\n        }\r\n    }\r\n    client.Close();\r\n}\r\n<\/pre>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n' VB.NET code\r\n\r\nUsing client As New Imap()\r\n\tclient.ConnectSSL(&quot;imap.server.com&quot;)\r\n\tclient.Login(&quot;user@server.com&quot;, &quot;password&quot;)\r\n\r\n\tDim folderStatus As FolderStatus = client.SelectInbox()\r\n\tConsole.WriteLine(&quot;Total message count: {0}&quot;,_\r\n\t\tcurrentStatus.MessageCount)\r\n\r\n\tDim &#x5B;stop] As Boolean = False\r\n\t' We start a new thread to handle user input, enter = stop idle\r\n\tNew Thread(Function() Do\r\n\t\tConsole.ReadLine()\r\n\t\tclient.StopIdle()\r\n\t\t&#x5B;stop] = True\r\n\tEnd Function).Start()\r\n\r\n\tWhile &#x5B;stop] = False\r\n\t\tDim currentStatus As FolderStatus = client.Idle()\r\n\t\tIf &#x5B;stop] = True Then\r\n\t\t\tExit While\r\n\t\tEnd If\r\n\r\n\t\tConsole.WriteLine(&quot;Total message count: {0}&quot;,_\r\n\t\t\tcurrentStatus.MessageCount)\r\n\r\n\t\tFor Each uid As Long In client.Search(Flag.Unseen)\r\n\t\t\tDim email As IMail = New MailBuilder()_\r\n\t\t\t\t.CreateFromEml(client.GetHeadersByUID(uid))\r\n\t\t\tConsole.WriteLine(email.Subject)\r\n\t\tNext\r\n\tEnd While\r\n\tclient.Close()\r\nEnd Using\r\n<\/pre>\n<h2>Drawbacks<\/h2>\n<p>IDLE has some drawbacks:<\/p>\n<ul>\n<li>It requires constant server connection.<\/li>\n<li>\nIDLE command leaves TCP\/IP connection unused for a long time, and although IDLE is reissued\/refreshed every 10 minutes (RFC requirement is 29 minutes, but this is much to long), some routers may assume the connection is dead, because of too long period of inactivity.<\/p>\n<p>Shortening the timeout using <em>Imap.Idle(TimeSpan)<\/em> overload usually solves this issue. Don&#8217;t be afraid of shortening the timeout value as reissuing IDLE command takes less that a hundred bytes of data.\n<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>IDLE is an IMAP protocol extension described in RFC 2177. It allows an IMAP client to indicate to the server that it is ready to accept real-time notifications about the changes (e.g. new message) in the currently selected folder. This feature is not available for every IMAP server. You need to check if your IMAP [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[15,27,28,77,57],"class_list":["post-831","post","type-post","status-publish","format-standard","hentry","category-mail-dll","tag-c","tag-idle","tag-imap","tag-imap-component","tag-vb-net"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/831"}],"collection":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/comments?post=831"}],"version-history":[{"count":9,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/831\/revisions"}],"predecessor-version":[{"id":2782,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/831\/revisions\/2782"}],"wp:attachment":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/media?parent=831"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/categories?post=831"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/tags?post=831"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}