This project is read-only.

ImapX 2.0.0.13 Release

Topics: Releases
Oct 23, 2013 at 12:21 AM
Edited Oct 24, 2013 at 11:34 PM
Good morning everyone!

I'm really happy to announce that ImapX 2.0.0.13 (10) is now available for download! It's been a long way to this release, and within six months, I have completely rewritten the library, considering all the bugs that been reported and features you've been asking for. Here is a brief list of changes made:
  • Added support for Mono.
  • Added support for Windows Phone 7.1 and 8.0
  • Added support for .Net 2.0, 3.0
  • Simplified connecting to server by reducing the number of parameters and adding automatic port selection.
  • Changed authentication handling to be universal and allowing to build custom providers.
  • Added advanced server feature detection.
  • Added direct access to common folders like Inbox, drafts, sent etc.
  • Partial message requests (decide yourself what parts you need and when).
  • Added support for GMail message ids, labels and threads.
  • Automated body decoding. No need to call the GetDecodedBody method.
  • Massive refactoring, many classes removed, methods marked as obsolete.
  • New sample application demonstrating all major features.
In the next days I will finish the missing parts of documenation and provide you with a list of methods that were marked as obsolete and explain how to use the new APIs instead.

I welcome everyone to test the new release. Your feedback is what makes it better.

I'd also like to say thanks to all the people who helped me developing and testing this release!

You can download the library through the downloads section or using Nuget.

Best regards,

Pavel Azanov
Oct 23, 2013 at 1:09 AM
Thank you, Pavel! I'm looking forward to testing 2.0.0.10!

--Ravi
Oct 23, 2013 at 5:21 AM
Good job Pavel! great thanks, we start to test it, is there any way to get login error like username or password is wrong or imap disabled error in new version?
Oct 23, 2013 at 8:18 AM
Edited Oct 23, 2013 at 8:20 AM
Hi ehsan63,

take a look at this small piece of code, it contains more details about the exceptions and server responses which you can handle:
var client = new ImapClient("imap.gmail.com", true);

try
{
    if (client.Connect())
    {
        if (client.Login("login", "pass"))
        {
            // Login successful
        }
        else
        {
            // User or password invalid
        }
    }
    else
    {
        // Connection could not be established
    }
}
catch (InvalidStateException)
{
    // Action can't be performed in current state
                
    // Occurs when you try changing host/port
    // or other connection relevant data when connected

    // Occurs if client is already connected and you call Connect

}
catch (NotSupportedException)
{
    // Authentication mechanism not supported 
    // (e.g LOGIN disabled, oAuth2 not supported)
}
catch (SocketException)
{
    // Connection lost, server unavailable
}
catch (Exception)
{
    // Everything else that could go wrong
}
When IMAP is disabled on server, you won't be able to create a connection or a SocketException will be thrown. In certain cases there might be some server response, but I couldn't simulate this situation. If you can provide me with some test server, I will check it and update the library if needed.
Oct 23, 2013 at 2:10 PM
Hi Pavel,
Thanks for this great new version!

I am having trouble getting to gmail's threadID / messageID in a way that will allow me to directly access a specific message/thread in a browser (i.e. X-GM-MSGID and X-GM-THRID headers).
I am connecting to gmail successfully, getting a collection of messages with
ImapX.Message[] messages = client.Folders.Inbox.Search("UNSEEN");   
foreach (ImapX.Message msg in messages)
{
       // Trying to get to msg.GmailThread or msg.GMailMessageId here but it's all null
}
Is this supposed to be implemented already? Am I missing some method I need to call first to "fetch" those headers from the gmail server?

Thanks!
--Muly
Oct 23, 2013 at 3:22 PM
Edited Oct 23, 2013 at 4:18 PM
Hi,

i have used your test code on Windows Phone and simply client.Connect() return false but without error.

where is the problem?

Tnx
Oct 23, 2013 at 3:53 PM
Edited Oct 23, 2013 at 3:57 PM
Hi Muly,

i'm sorry, hanging a bit behind in updating the documenation. By default, the message fetch mode is set to Basic, which means flags, headers, body structure, size, internal date and the message body (excluding embedded images and attachments) will be downloaded. The data associated with GMail extensions will not be fetched. To request it, simply change the client behavior:
// Request basic information and GMail mesage id, labels and thread id
client.Behavior.MessageFetchMode = MessageFetchMode.Basic |  MessageFetchMode.GMailExtendedData;
A part of the documentation for working with messages is available already, more is coming tonight.
Oct 23, 2013 at 3:56 PM
Hi acquariusoft,

i will test the library with Windows Phone tonight, and let you know if find any issue. Another user also reported problems downloading the nuget package for a Windows Phone project, so will take a closer look at it too.

Greets,

Pavel

PS: Please do not quote long code parts, this makes the thread unreadable.
Oct 23, 2013 at 4:17 PM
pavel_azanov wrote:
Hi acquariusoft,

i will test the library with Windows Phone tonight, and let you know if find any issue. Another user also reported problems downloading the nuget package for a Windows Phone project, so will take a closer look at it too.

Greets,

Pavel

PS: Please do not quote long code parts, this makes the thread unreadable.
Tnx for your quick response, i have the same problem of other user so i have downloaded the binary and install from download section.
I wait your test.

Tnx!!!
Oct 23, 2013 at 7:11 PM
Thanks Pavel!
This worked like a charm, just what I needed.

Keep up the great work!
--Muly
Oct 23, 2013 at 7:49 PM
Edited Oct 23, 2013 at 8:16 PM
Good evening everyone,

due to a significant bug in the library for Windows Phone and some limitations of Nuget (every package update requires changing version), I'm releasing ImapX 2.0.0.13, which is actually same as 2.0.0.10, only the bug on Windows Phone is fixed now.

Kind regards,

Pavel Azanov
Oct 23, 2013 at 9:09 PM
tnx, now all works well!!!

Great job!
Oct 23, 2013 at 9:22 PM
But now i can't download messages, if after the login i do
client.Folders.All.Messages.Download();
i obtain an exception
System.IO.IOException: Internal TLS error, this could be an attack
 at Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler.WriteData(Byte[] buf, Int32 offset, Int32 len)
   at Org.BouncyCastle.Crypto.Tls.TlsStream.Write(Byte[] buf, Int32 off, Int32 len)
   at ImapX.ImapBase.SendAndReceive(String command, IList`1& data, CommandProcessor processor, Encoding encoding)
   at ImapX.ImapClient.GetFolders(String path, CommonFolderCollection commonFolders, Folder parent, Boolean isFirstLevel)
   at ImapX.ImapClient.GetFolders()
What's wrong?
Oct 23, 2013 at 9:42 PM
Edited Oct 23, 2013 at 9:46 PM
Hi acquariusoft,

seems the BouncyCastle library has problems validating the server certificate. I will look into it, in worst case will have to provide a patched implementation of SocketEx/BouncyCastle.
Oct 23, 2013 at 9:47 PM
I connect to gmail, i use your example in the 3rd post
Oct 24, 2013 at 2:50 AM
Is there a method to retrieve message's uid only,not message's entity?
Oct 24, 2013 at 6:33 AM
Edited Oct 24, 2013 at 6:34 AM
I have find this
http://stackoverflow.com/questions/11154263/tls-connection-with-psk-using-bouncycastle

seems the same error but in java. Can help you?

Tnx in advance!!
Oct 24, 2013 at 8:05 AM
Edited Oct 24, 2013 at 8:05 AM
@lampo:

If you only need the UIds of the messages, simply set the message fetch mode to None:
// Request nothing except the UId
client.Behavior.MessageFetchMode = MessageFetchMode.None;
@acquariusoft

Thank you, I've seen this thread yesterday night, and also said in my post it might depend on the certificate validation. Nevertheless, the Connect method works, which makes me doubt that it is a problem of certificate.
Oct 24, 2013 at 8:56 AM
Tnx

you can reproduce the problem with Windows Phone?
I can help you in any way?
which library to use BouncyCastle?

pavel_azanov wrote:
@acquariusoft

Thank you, I've seen this thread yesterday night, and also said in my post it might depend on the certificate validation. Nevertheless, the Connect method works, which makes me doubt that it is a problem of certificate.
Oct 24, 2013 at 9:15 AM
BouncyCastle is used by SocketEx.SSL to provide support for SSL connections on Windows Phone. I will create a test application when back home in a few hours, and let you know the results of my research about this issue. Be patient.
Oct 24, 2013 at 9:20 AM
pavel_azanov wrote:
@lampo:

If you only need the UIds of the messages, simply set the message fetch mode to None:
// Request nothing except the UId
client.Behavior.MessageFetchMode = MessageFetchMode.None;
Thank you,I'll try it.
Oct 24, 2013 at 9:40 AM
pavel_azanov wrote:
BouncyCastle is used by SocketEx.SSL to provide support for SSL connections on Windows Phone. I will create a test application when back home in a few hours, and let you know the results of my research about this issue. Be patient.
Tnx, if i can help you tell me, i have see the SocketEx source and i see it use a modified BouncyCastle. if i remove bouncywp71.dll from the project it works, so i think is not used.

tnx again
Oct 24, 2013 at 1:07 PM
Hi again Pavel,

Any chance of showing a short code snippet for fetching only messages from a specific (custom) label in gmail?

Thanks,
--Muly
Oct 24, 2013 at 1:42 PM
Hi Muly,

sure, here you are:
// Using Folder.Search
folder.Search(string.Format("X-GM-LABELS \"{0}\"", "my label"));

//Using MessageCollection.Download
folder.Messages.Download(string.Format("X-GM-LABELS \"{0}\"", "my label"));
If you need to lookup Unicode labels, let me know, I will make another sample.
Oct 24, 2013 at 2:01 PM
Thanks Pavel.

I think that working with Unicode labels would be better, so a sample of that would be great.

Also, what is the syntax in folder.Search() to use multiple queries with AND/OR relationship (at least AND). e.g. if I want items from one label but only those who are unread - how do I combine your previous example with the "UNSEEN" search ?

Thanks for the great support!
--Muly
Oct 24, 2013 at 3:51 PM
Edited Oct 24, 2013 at 3:54 PM
@acquariusoft:

I have tested the library, but i'm not able to reproduce the issue you're talking about. Do you develop an application for the version 7.1 or 8.0?

@Muly:

To combine queries simply write them separated with a space:
var msgs = client.Folders.Inbox.Search(string.Format("UNSEEN X-GM-LABELS \"{0}\"", "test"));
You can also take a look at the specification of the SEARCH command, it contains all possible queries.

For the unicode labels, first of all you need to set the charset to utf8, and then, for each unicode string you need to pass the number of bytes, a \r\n and then the actual string. Currently i'm working on a search filter engine, so you won't need to write search queries by hand. A sample query could look this way:
var unicodeLabel = "личное";

var msgs = client.Folders.Inbox.Search("CHARSET UTF-8 UNSEEN X-GM-LABELS {" + Encoding.UTF8.GetByteCount(unicodeLabel) + "}\r\n" + unicodeLabel);
Oct 24, 2013 at 3:53 PM
Hi,

i develop a WIndows Phone 8 application.
Can you send the link to your test app so i can download and try?

Tnx in advance!!
Oct 24, 2013 at 5:58 PM
This is a test project i have created for windows phone 8 and don't work
https://skydrive.live.com/redir?resid=E8C623E54F96BDF1!5828&authkey=!AE4cxm5AghY3O_4

Tnx!!
Oct 24, 2013 at 6:28 PM
Edited Oct 24, 2013 at 6:44 PM
Hi acquariusoft,

Thank you,

You can check the latest source in the repository, I added a small Windows Phone 8 sample which requests the number of messages in the All Folder. It works fine on my phone.

I will take a look at your sample now.

UPDATE: Just looked into your code, if you set AutoPopulateFolderMessages = true, then there's no need to call folder.Messages.Download, it will be done automatically. After removing the call to Download, your sample works fine.
Oct 24, 2013 at 8:40 PM
Tnx,

i have tried also your code and found another problem, the code don't work if you set a breakpoint in the function :D

now your sample works, but if i change

client.Behavior.MessageFetchMode = MessageFetchMode.None;

because i need mail text,subject,ecc i obtain an error
System.FormatException: One of the identified items was in an invalid format.
at System.Net.Mime.ContentType.ParseValue()
   at System.Net.Mime.ContentType..ctor(String contentType)
   at ImapX.Message.BindHeadersToFields()
   at ImapX.Message.Download(MessageFetchMode mode, Boolean reloadHeaders)
   at ImapX.Folder.Fetch(IEnumerable`1 uIds, MessageFetchMode mode)
   at ImapX.Folder.Search(String query, MessageFetchMode mode, Int32 count)
   at ImapX.WindowsPhone.Sample.MainPage.Test()
   at ImapX.WindowsPhone.Sample.MainPage.btnSignIn_Click(Object sender, RoutedEventArgs e)
   at System.Windows.Controls.Primitives.ButtonBase.OnClick()
   at System.Windows.Controls.Button.OnClick()
   at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
   at System.Windows.Controls.Control.OnMouseLeftButtonUp(Control ctrl, EventArgs e)
   at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName)
what is wrong?

Tnx for your help!! you are BIG!!!
Oct 24, 2013 at 11:15 PM
Ok, i have solved, with hotmail other MessageFetchMode works, but not with gmail.
I have solved with this code
client.Behavior.MessageFetchMode = MessageFetchMode.None;
                        List<Message> messages=client.Folders.Inbox.Search().OrderByDescending(x=>x.UId).ToList();
                        
                        foreach (Message m in messages)
                        {
                           
                                m.Download(mode: MessageFetchMode.Basic);
                                MessageBox.Show(m.Subject);
                           
                        }
another little question, this is the right mode to return the last mail?
How i can query the search to have the last x mail?

Tnx for your hard work!!
Oct 25, 2013 at 10:27 AM
Hi acquariusoft,

Thank you,

by defaut the download mode is set to Basic, and for me it works no matter if i change it or not.
Your approach to get the last mail is right!

Greets,

Pavel
Oct 25, 2013 at 10:39 PM
Good night everyone,

I updated the binaries in download section and the source code in repository (not the Nuget package). The update fixes an issue with the method Folder.EmptyFolder.

Best regards,

Pavel
Oct 26, 2013 at 3:59 PM
Hi Pavel
There is an issue with Linq Methods after installing ImapX 2.0.0.13 and LinqBridge,
.Net gives this error when you build project: the call is ambiguous between method x and x.
It sounds LinqBridge conflicts with System.Linq

Thanks

Ehsan
Oct 26, 2013 at 4:05 PM
Hi ehsan63,

that's a little strange, if you have a project which uses .Net 3.5+ then use the ImapX binaries built for the version you have. You don't need LinqBridge unless you use .Net 2.0/3.0.

Best regards,

Pavel
Oct 27, 2013 at 7:55 AM
Edited Oct 27, 2013 at 9:43 AM
Thanks Pavel for your help,
one more thing I tested client.Folders[folder.Name].Search("ALL"); for yahoo, gmail and hotmail,
It works with gmail and hotmail but for yahoo it gives error: Input string was not in a correct format.
Other thing is the code for checking is IMAP is disabled or username or password is wrong is not working:
var client = new ImapClient("imap.gmail.com", true);

try
{
if (client.Connect())
{
    if (client.Login("login", "pass"))
    {
        // Login successful
    }
    else
    {
        // User or password invalid
    }
}
else
{
    // Connection could not be established
}
}
catch (InvalidStateException)
{
// Action can't be performed in current state

// Occurs when you try changing host/port
// or other connection relevant data when connected

// Occurs if client is already connected and you call Connect
}
catch (NotSupportedException)
{
// Authentication mechanism not supported 
// (e.g LOGIN disabled, oAuth2 not supported)
}
catch (SocketException)
{
// Connection lost, server unavailable
}
catch (Exception)
{
// Everything else that could go wrong
}

When IMAP is disable code goes to:
else
    {
        // User or password invalid
    }
Thanks

Ehsan
Oct 27, 2013 at 10:23 AM
Hi Ehsan,

thank you for your reports, I will check the library with Yahoo Mail today. Also will try to get the IMAP disabled recognition working. Which server did you use to test?

Greets,

Pavel
Oct 27, 2013 at 6:34 PM
I test IMAP Disabled with gmail, 2 other things:
  1. in message object there was messageid(string) which was a unique id for each message but in new version it returns null.
  2. on old version we have Boolean parameter in search method: client.Folders[folder.Name].Search("ALL", false); to not process messages and then we could process it with message.Process(); but on new version it takes longer time to do client.Folders[folder.Name].Search("ALL"); how we can solve that?
Oct 27, 2013 at 7:45 PM
Edited Oct 27, 2013 at 8:23 PM
The library became more flexible when it comes to downloading messages. Now you can define a message fetch mode and also which message headers should be requested.

The default message fetch settings are the following:
// Folders are being examined when loaded first
client.Behavior.ExamineFolders = true;

// Do not automatically download all messages to folder.Messages, a manual call to Folder.Messages.Download or Folder.Search is needed
client.Behavior.AutoPopulateFolderMessages = false;

// Download Message.Body when the property is accessed if it not has been done before
client.Behavior.AutoDownloadBodyOnAccess = true;

// Basic mode, request flags, headers, body structure and body, size and internal date
client.Behavior.MessageFetchMode = MessageFetchMode.Basic; 

// Request following headers only:
// MessageHeader.From
// MessageHeader.To
// MessageHeader.Date
// MessageHeader.Subject
// MessageHeader.Cc
// MessageHeader.ContentType
client.Behavior.RequestedHeaders = MessageHeaderSets.Minimal;
Simply change it according to your needs, like adding a new header (MessageHeader.MessageId) to the requested headers or change the download mode to download less data.

When you define the headers to be requested, you can set client.Behavior.RequestedHeaders to null, to request all message headers. I also recommend you to always add the MessageHeader.ContentType to the requested headers if you provide a custom header list.

If you give me a more detailed description of your scenario, I can show you which configuration is best.

There's also a part of the documentation available by now:
UPDATE: Coming back to your question about IMAP disabled: It is not possible to say for sure when IMAP is disabled, as the server will respond with a NO, and include an ALERT message, which might be in any language. I added a new kind of exception which will be thrown on such alerts:
var client = new ImapClient("imap.gmail.com", true);

try {  }
catch (ServerAlertException) { 
    // Server alert, IMAP may be disabled, see exception message for detailed server alert.
}
catch (InvalidStateException) { }
catch (NotSupportedException) { }
catch (SocketException) {  }
catch (Exception) {  }
UPDATE 2: The issue with Yahoo Mail is fixed.

The code in the repository contains the updates already, the binaries will be updated tomorrow.
Oct 28, 2013 at 9:13 PM
Edited Oct 28, 2013 at 10:00 PM
Binaries in download section have been updated and include the latest updates. This thread gets pretty unreadable through many posts, if you experience any issues or have questions, please create a new thread or open a ticket in the issue tracker.

Best regards,

Pavel