I am writing a inter-process comunication using WCF NetNamedPipeBinding.
My goal is to have service running at "net.pipe://localhost/service", so I running the simplest host:
host = new ServiceHost(contract, new Uri[] { "net.pipe://localhost" });
host.AddServiceEndpoint(typeof (IContract),
new NetNamedPipeBinding(), "service");
host.Open();
According to http://blogs.msdn.com/b/rodneyviana/archive/2011/03/22/named-pipes-in-wcf-are-named-but-not-by-you-and-how-to-find-the-actual-windows-object-name.aspx
the name is hidden behind system-generated guid.
And here comes the question.
Is there any possible way to get the name generated by system (guid) inside my program, so I could get path like "\Device\NamedPipe\GUID", like in the procexp, so it will be easier to sniff it?
(Except running sys internals executables in separate process and parsing its output?)
After a lot of fiddling around and breaking my head against the wall, I finally got this working:
Guid pipeGuid;
if (PipeName.Equals("*", StringComparison.InvariantCultureIgnoreCase) || PipeName.Equals("localhost", StringComparison.InvariantCultureIgnoreCase))
PipeName = "*";
string s = string.Format(#"net.pipe://{0}/", PipeName.ToUpper());
if(!string.IsNullOrWhiteSpace(ServiceName))
s = string.Format(#"net.pipe://*/{0}/", ServiceName.ToUpper());
var bytes = Encoding.UTF8.GetBytes(s);
var base64 = Convert.ToBase64String(bytes);
string namedPipeMMFName = string.Format(#"Global\net.pipe:E{0}", base64);
MemoryMappedFileSecurity mSec = new MemoryMappedFileSecurity();
mSec.AddAccessRule(new AccessRule<MemoryMappedFileRights>(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MemoryMappedFileRights.FullControl, AccessControlType.Allow));
using (var mmf = MemoryMappedFile.OpenExisting(namedPipeMMFName, MemoryMappedFileRights.Read))
{
using (var accessor = mmf.CreateViewAccessor(4, 45, MemoryMappedFileAccess.Read))
{
accessor.Read<Guid>(0, out pipeGuid);
}
}
using (NamedPipeClientStream client = new NamedPipeClientStream(GetResolvedText(ServerName), pipeGuid, PipeDirection.InOut,
PipeOptions.None, TokenImpersonationLevel.Impersonation))
{
client.Connect(10000);
}
I must thank Rodney Viana for his article and #Avner Shahar-Kashtan for his answer and numerous other articles I read. I hope that my answer can help someone in the future.
As the article you link to shows, WCF stores the named pipe name in a memory mapped file. To access it, you need to do the following:
Endpoint: net.pipe://localhost/TradeService/Service1
Normalized Endpoint: net.pipe://+/TRADESERVICE/SERVICE1/
Base 64 representation: bmV0LnBpcGU6Ly8rL1RSQURFU0VSVklDRS9TRVJWSUNFMS8=
Final memory mapped file: net.pipe:EbmV0LnBpcGU6Ly8rL1RSQURFU0VSVklDRS9TRVJWSUNFMS8=
Now you take the final MMF name and open it. Here's an article on using MMFs on MSDN: https://msdn.microsoft.com/en-us/library/dd267590(v=vs.110).aspx
// Open the MMF.
using (var mmf = MemoryMappedFile.OpenExisting(namedPipeMMFName))
{
// Create an accessor for 16 bytes (Size of GUID) starting at
// offset 5 (as the article states)
using (var accessor = mmf.CreateViewAccessor(5, 16))
{
Guid pipeGuid;
accessor.Read<Guid>(0, out pipeGuid);
Console.WriteLine("This should be the pipe name: " + pipeGuid);
}
}
Related
I'm using a WCF service with NetNamedPipeBinding for IPC. This prevents the code to be updated to .Net 7 so I want to replace the WCF server with a client compatible solution. I can't afford breaking changes, so replacing server and client with sth else is no option.
Getting the windows name of the named pipe works
//localhost replaced by + or *, capitals, trailing slash
string normalizedName = "net.pipe://+/SOME/PATH/";
var base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(normalizedName));
string namedPipeMMFName = string.Format(#"Global\net.pipe:E{0}", base64);
For the server
mmf = MemoryMappedFile.CreateOrOpen(namedPipeMMFName, 20, MemoryMappedFileAccess.ReadWrite);
{
using (var accessor = mmf.CreateViewAccessor(0, 20, MemoryMappedFileAccess.Write))
{
//Reverse engineered. Meaning unclear
accessor.Write(0, 1);
accessor.Write(1, 0);
accessor.Write(2, 0);
accessor.Write(3, 0);
Guid pipeGuid = Guid.NewGuid();
accessor.Write<Guid>(4, ref pipeGuid);
retVal = pipeGuid.ToString();
}
}
For the client
using (var mmf = MemoryMappedFile.OpenExisting(namedPipeMMFName, MemoryMappedFileRights.Read))
{
using (var accessor = mmf.CreateViewAccessor(4, 16, MemoryMappedFileAccess.Read))
{
accessor.Read(0, out Guid pipeGuid);
retVal = pipeGuid.ToString();
}
}
The server now looks like that
var pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.InOut, maxNumberOfServerInstances, PipeTransmissionMode.Message, PipeOptions.Asynchronous);
pipeServer.BeginWaitForConnection(WaitForConnectionCallBack, null);
When the client (WCF!) opens the connection the new server recognizes it and begins to read.
After calling EndRead() I get the first result
"\0\u0001\0\u0001\u0002\u0002\u0019net.pipe://localhost/IF13\u0003\b\f"
which looks like sth from the client. Further read calls result in no data as if the pipe was closed by the client
I expect that WCF client requires some kind of hand shake.
What do I have to answer after the first successful read?
Thanks
Tom
I know this question can be interpreted as a duplicate, but I can simply not get the blop service working. I have followed the standard example on msdn. I have implemented in my code but followed the example. I can get my MobileService, with the supplied script in the example, to insert a blob with open properties. I then use this code to upload an image to the blob storage:
BitmapImage bi = new BitmapImage();
MemoryStream stream = new MemoryStream();
if (bi != null)
{
WriteableBitmap bmp = new WriteableBitmap((BitmapSource)bi);
bmp.SaveJpeg(stream, bmp.PixelWidth, bmp.PixelHeight, 0, 100);
}
if (!string.IsNullOrEmpty(uploadImage.SasQueryString))
{
// Get the URI generated that contains the SAS
// and extract the storage credentials.
StorageCredentials cred = new StorageCredentials(uploadImage.SasQueryString);
var imageUri = new Uri(uploadImage.ImageUri);
// Instantiate a Blob store container based on the info in the returned item.
CloudBlobContainer container = new CloudBlobContainer(
new Uri(string.Format("https://{0}/{1}",
imageUri.Host, uploadImage.ContainerName)), cred);
// Upload the new image as a BLOB from the stream.
CloudBlockBlob blobFromSASCredential = container.GetBlockBlobReference(uploadImage.ResourceName);
await blobFromSASCredential.UploadFromStreamAsync(stream);//error!
// When you request an SAS at the container-level instead of the blob-level,
// you are able to upload multiple streams using the same container credentials.
stream = null;
}
I am getting an error in this code at the point marked error, with the following error:
+ ex {Microsoft.WindowsAzure.Storage.StorageException: The remote server returned an error: NotFound. ---> System.Net.WebException: The remote server returned an error: NotFound. ---> System.Net.WebException: The remote server returned an error: NotFound.
Which I do not understand since the code that returns the string from the script is:
// Generate the upload URL with SAS for the new image.
var sasQueryUrl = blobService.generateSharedAccessSignature(item.containerName,
item.resourceName, sharedAccessPolicy);
// Set the query string.
item.sasQueryString = qs.stringify(sasQueryUrl.queryString);
// Set the full path on the new new item,
// which is used for data binding on the client.
item.imageUri = sasQueryUrl.baseUrl + sasQueryUrl.path;
Of course this also depicts that I do not completely grasp the construction of the blob storage. And therefore any help would be appreciated.
Comment elaborations
From the server code it should create a public note for at least 5 minutes. And therefore not be an issue. My server script is the same as the link. But replicated here:
var azure = require('azure');
var qs = require('querystring');
var appSettings = require('mobileservice-config').appSettings;
function insert(item, user, request) {
// Get storage account settings from app settings.
var accountName = appSettings.STORAGE_ACCOUNT_NAME;
var accountKey = appSettings.STORAGE_ACCOUNT_ACCESS_KEY;
var host = accountName + '.blob.core.windows.net';
if ((typeof item.containerName !== "undefined") && (
item.containerName !== null)) {
// Set the BLOB store container name on the item, which must be lowercase.
item.containerName = item.containerName.toLowerCase();
// If it does not already exist, create the container
// with public read access for blobs.
var blobService = azure.createBlobService(accountName, accountKey, host);
blobService.createContainerIfNotExists(item.containerName, {
publicAccessLevel: 'blob'
}, function(error) {
if (!error) {
// Provide write access to the container for the next 5 mins.
var sharedAccessPolicy = {
AccessPolicy: {
Permissions: azure.Constants.BlobConstants.SharedAccessPermissions.WRITE,
Expiry: new Date(new Date().getTime() + 5 * 60 * 1000)
}
};
// Generate the upload URL with SAS for the new image.
var sasQueryUrl =
blobService.generateSharedAccessSignature(item.containerName,
item.resourceName, sharedAccessPolicy);
// Set the query string.
item.sasQueryString = qs.stringify(sasQueryUrl.queryString);
// Set the full path on the new new item,
// which is used for data binding on the client.
item.imageUri = sasQueryUrl.baseUrl + sasQueryUrl.path;
} else {
console.error(error);
}
request.execute();
});
} else {
request.execute();
}
}
The idea with the pictures is that other users of the app should be able to access them. As far as I understand I have made it public, but only write public for 5 minutes. The url for the blob I save in a mobileservice table, where the user needs to be authenticated, I would like the same safety on the storage. But do not know if this is accomplished? I am sorry for all the stupid questions, but I have not been able to solve it on my own so I have to "seem" stupid :)
If someone ends up in here needing help. The problem for me was the uri. It should have been http and not https. Then there were no error uploading.
But displaying the image even on a test image control from the toolbox, did not succeed. The problem was I had to set the stream to the begining:
stream.Seek(0, SeekOrigin.Begin);
Then the upload worked and was able to retrieve the data.
Hey guys I'm trying to write an AXL-client (SOAP) for the Cisco Unified Communications Manager. For that purpose I need to establish an ssl-connection to the AXL-service. Unfortunatly I dont know much about all that ssl-stuff.
However I was able to find a working Java-example, that does, what I want. The problem is, i need that in C#.NET. So I'm hoping, that someone could "translate" the following Java-code in a C#-version. But it has to do exactly the same, espacially the authentication and certificate-stuff.
Here is the code:
String sAXLSOAPRequest = "...";
byte[] bArray = null; // buffer for reading response from
Socket socket = null; // socket to AXL server
OutputStream out = null; // output stream to server
InputStream in = null; // input stream from server
X509TrustManager xtm = new MyTrustManager();
TrustManager[] mytm = { xtm };
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(null, mytm, null);
SSLSocketFactory sslFact = (SSLSocketFactory) ctx.getSocketFactory();
socket = (SSLSocket) sslFact.createSocket("192.168.1.100", Integer.parseInt("8443"));
in = socket.getInputStream();
// send the request to the server
// read the response from the server
StringBuffer sb = new StringBuffer(2048);
bArray = new byte[2048];
int ch = 0;
int sum = 0;
out = socket.getOutputStream();
out.write(sAXLSOAPRequest.getBytes());
while ((ch = in.read(bArray)) != -1) {
sum += ch;
sb.append(new String(bArray, 0, ch));
}
socket.close();
// output the response to the standard output
System.out.println(sb.toString());
and this is the MyTrustManager-Class:
public class MyTrustManager implements X509TrustManager {
MyTrustManager() {
// create/load keystore
}
public void checkClientTrusted(X509Certificate chain[], String authType)
throws CertificateException {
}
public void checkServerTrusted(X509Certificate chain[], String authType)
throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
Any help would be appreciated.
Thanks
edit: sorry i should have mentioned: youre right i can generate a proxy-class, but sadly its not working properly. cisco did a really bad job with that (not to mention the really bad documentation). the proxy class throws some xml-errors when parsing some responses. so i have to do it manually for that cases...
i'll worry about the certificate security later
Have you tried consuming the web service the "proper" way? Add a SOAP web service reference to your C# project in Visual Studio, gets the stubs etc? That's the easiest way of doing it from C#. You can just specify a https protocol in the URL when you add the reference.
I'd like to create a small application that can collect system information (Win32_blablabla) using WinRM as opposed to WMI. How can i do that from C#?
The main goal is to use WS-Man (WinRm) as opposed to DCOM (WMI).
I guess the easiest way would be to use WSMAN automation. Reference wsmauto.dll from windwos\system32 in your project:
then, code below should work for you. API description is here: msdn: WinRM C++ API
IWSMan wsman = new WSManClass();
IWSManConnectionOptions options = (IWSManConnectionOptions)wsman.CreateConnectionOptions();
if (options != null)
{
try
{
// options.UserName = ???;
// options.Password = ???;
IWSManSession session = (IWSManSession)wsman.CreateSession("http://<your_server_name>/wsman", 0, options);
if (session != null)
{
try
{
// retrieve the Win32_Service xml representation
var reply = session.Get("http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Service?Name=winmgmt", 0);
// parse xml and dump service name and description
var doc = new XmlDocument();
doc.LoadXml(reply);
foreach (var elementName in new string[] { "p:Caption", "p:Description" })
{
var node = doc.GetElementsByTagName(elementName)[0];
if (node != null) Console.WriteLine(node.InnerText);
}
}
finally
{
Marshal.ReleaseComObject(session);
}
}
}
finally
{
Marshal.ReleaseComObject(options);
}
}
hope this helps, regards
I've got an article that describes an easy way to run Powershell through WinRM from .NET at http://getthinktank.com/2015/06/22/naos-winrm-windows-remote-management-through-net/.
The code is in a single file if you want to just copy it and it's also a NuGet package that includes the reference to System.Management.Automation.
It auto manages trusted hosts, can run script blocks, and also send files (which isn't really supported but I created a work around). The returns are always the raw objects from Powershell.
// this is the entrypoint to interact with the system (interfaced for testing).
var machineManager = new MachineManager(
"10.0.0.1",
"Administrator",
MachineManager.ConvertStringToSecureString("xxx"),
true);
// will perform a user initiated reboot.
machineManager.Reboot();
// can run random script blocks WITH parameters.
var fileObjects = machineManager.RunScript(
"{ param($path) ls $path }",
new[] { #"C:\PathToList" });
// can transfer files to the remote server (over WinRM's protocol!).
var localFilePath = #"D:\Temp\BigFileLocal.nupkg";
var fileBytes = File.ReadAllBytes(localFilePath);
var remoteFilePath = #"D:\Temp\BigFileRemote.nupkg";
machineManager.SendFile(remoteFilePath, fileBytes);
Hope this helps, I've been using this for a while with my automated deployments. Please leave comments if you find issues.
I would like to note that this shows an interop error by default in Visual Studio 2010.
c.f. http://blogs.msdn.com/b/mshneer/archive/2009/12/07/interop-type-xxx-cannot-be-embedded-use-the-applicable-interface-instead.aspx
There appear to be two ways to solve this. This first is documented in the article listed above and appears to be the correct way to handle the problem. The pertinent changes for this example is:
WSMan wsManObject = new WSMan();
This is in lieu of IWSMan wsman = new WSManClass(); which will throw the error.
The second resolution is to go to the VS2010—>Solution Explorer—>Solution—>Project—>References and select WSManAutomation. Right click or hit Alt-Enter to access the properties. Change the value of the "Embed Interop Types" property of the wsmauto reference.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Does anyone have any sample code in that makes use of the .Net framework that connects to googlemail servers via IMAP SSL to check for new emails?
I'd recommend looking at MailKit as it is probably the most robust mail library out there and it's Open Source (MIT).
One of the awesome things about MailKit is that all network APIs are cancelable (something I haven't seen available in any other IMAP library).
It's also the only library that I know of that supports threading of messages.
using System;
using System.Net;
using System.Threading;
using MailKit.Net.Imap;
using MailKit.Search;
using MailKit;
using MimeKit;
namespace TestClient {
class Program
{
public static void Main (string[] args)
{
using (var client = new ImapClient ()) {
using (var cancel = new CancellationTokenSource ()) {
client.Connect ("imap.gmail.com", 993, true, cancel.Token);
// If you want to disable an authentication mechanism,
// you can do so by removing the mechanism like this:
client.AuthenticationMechanisms.Remove ("XOAUTH");
client.Authenticate ("joey", "password", cancel.Token);
// The Inbox folder is always available...
var inbox = client.Inbox;
inbox.Open (FolderAccess.ReadOnly, cancel.Token);
Console.WriteLine ("Total messages: {0}", inbox.Count);
Console.WriteLine ("Recent messages: {0}", inbox.Recent);
// download each message based on the message index
for (int i = 0; i < inbox.Count; i++) {
var message = inbox.GetMessage (i, cancel.Token);
Console.WriteLine ("Subject: {0}", message.Subject);
}
// let's try searching for some messages...
var query = SearchQuery.DeliveredAfter (DateTime.Parse ("2013-01-12"))
.And (SearchQuery.SubjectContains ("MailKit"))
.And (SearchQuery.Seen);
foreach (var uid in inbox.Search (query, cancel.Token)) {
var message = inbox.GetMessage (uid, cancel.Token);
Console.WriteLine ("[match] {0}: {1}", uid, message.Subject);
}
client.Disconnect (true, cancel.Token);
}
}
}
}
}
The URL listed here might be of interest to you
http://www.codeplex.com/InterIMAP
which was extension to
http://www.codeproject.com/KB/IP/imaplibrary.aspx?fid=91819&df=90&mpp=25&noise=5&sort=Position&view=Quick&fr=26&select=2562067#xx2562067xx
As the author of the above project i can say that yes it does support SSL.
I am currently working on a new version of the library that will be completely asynchronous to increase the speed with which it can interact with IMAP servers.
That code, while not complete, can be downloaded, along with the original synchronous library (which also supports SSL), from the code plex site linked to above.
Cross posted from the other similar question. See what happens when they get so similar?
I've been searching for an IMAP solution for a while now, and after trying quite a few, I'm going with AE.Net.Mail.
There is no documentation, which I consider a downside, but I was able to whip this up by looking at the source code (yay for open source!) and using Intellisense. The below code connects specifically to Gmail's IMAP server:
// Connect to the IMAP server. The 'true' parameter specifies to use SSL
// which is important (for Gmail at least)
ImapClient ic = new ImapClient("imap.gmail.com", "name#gmail.com", "pass",
ImapClient.AuthMethods.Login, 993, true);
// Select a mailbox. Case-insensitive
ic.SelectMailbox("INBOX");
Console.WriteLine(ic.GetMessageCount());
// Get the first *11* messages. 0 is the first message;
// and it also includes the 10th message, which is really the eleventh ;)
// MailMessage represents, well, a message in your mailbox
MailMessage[] mm = ic.GetMessages(0, 10);
foreach (MailMessage m in mm)
{
Console.WriteLine(m.Subject);
}
// Probably wiser to use a using statement
ic.Dispose();
I'm not affiliated with this library or anything, but I've found it very fast and stable.
Lumisoft.net has both IMAP client and server code that you can use.
I've used it to download email from Gmail. The object model isn't the best, but it is workable, and seems to be rather flexible and stable.
Here is the partial result of my spike to use it. It fetches the first 10 headers with envelopes, and then fetches the full message:
using (var client = new IMAP_Client())
{
client.Connect(_hostname, _port, _useSsl);
client.Authenticate(_username, _password);
client.SelectFolder("INBOX");
var sequence = new IMAP_SequenceSet();
sequence.Parse("0:10");
var fetchItems = client.FetchMessages(sequence, IMAP_FetchItem_Flags.Envelope | IMAP_FetchItlags.UID,
false, true);
foreach (var fetchItem in fetchItems)
{
Console.Out.WriteLine("message.UID = {0}", fetchItem.UID);
Console.Out.WriteLine("message.Envelope.From = {0}", fetchItem.Envelope.From);
Console.Out.WriteLine("message.Envelope.To = {0}", fetchItem.Envelope.To);
Console.Out.WriteLine("message.Envelope.Subject = {0}", fetchItem.Envelope.Subject);
Console.Out.WriteLine("message.Envelope.MessageID = {0}", fetchItem.Envelope.MessageID);
}
Console.Out.WriteLine("Fetching bodies");
foreach (var fetchItem in client.FetchMessages(sequence, IMAP_FetchItem_Flags.All, false, true)
{
var email = LumiSoft.Net.Mail.Mail_Message.ParseFromByte(fetchItem.MessageData);
Console.Out.WriteLine("email.BodyText = {0}", email.BodyText);
}
}
There is no .NET framework support for IMAP. You'll need to use some 3rd party component.
Try Mail.dll email component, it's very affordable and easy to use, it also supports SSL:
using(Imap imap = new Imap())
{
imap.ConnectSSL("imap.company.com");
imap.Login("user", "password");
imap.SelectInbox();
List<long> uids = imap.Search(Flag.Unseen);
foreach (long uid in uids)
{
string eml = imap.GetMessageByUID(uid);
IMail message = new MailBuilder()
.CreateFromEml(eml);
Console.WriteLine(message.Subject);
Console.WriteLine(message.Text);
}
imap.Close(true);
}
Please note that this is a commercial product I've created.
You can download it here: https://www.limilabs.com/mail.
MailSystem.NET contains all your need for IMAP4. It's free & open source.
(I'm involved in the project)
the source to the ssl version of this is here: http://atmospherian.wordpress.com/downloads/
Another alternative: HigLabo
https://higlabo.codeplex.com/documentation
Good discussion: https://higlabo.codeplex.com/discussions/479250
//====Imap sample================================//
//You can set default value by Default property
ImapClient.Default.UserName = "your server name";
ImapClient cl = new ImapClient("your server name");
cl.UserName = "your name";
cl.Password = "pass";
cl.Ssl = false;
if (cl.Authenticate() == true)
{
Int32 MailIndex = 1;
//Get all folder
List<ImapFolder> l = cl.GetAllFolders();
ImapFolder rFolder = cl.SelectFolder("INBOX");
MailMessage mg = cl.GetMessage(MailIndex);
}
//Delete selected mail from mailbox
ImapClient pop = new ImapClient("server name", 110, "user name", "pass");
pop.AuthenticateMode = Pop3AuthenticateMode.Pop;
Int64[] DeleteIndexList = new.....//It depend on your needs
cl.DeleteEMail(DeleteIndexList);
//Get unread message list from GMail
using (ImapClient cl = new ImapClient("imap.gmail.com"))
{
cl.Port = 993;
cl.Ssl = true;
cl.UserName = "xxxxx";
cl.Password = "yyyyy";
var bl = cl.Authenticate();
if (bl == true)
{
//Select folder
ImapFolder folder = cl.SelectFolder("[Gmail]/All Mail");
//Search Unread
SearchResult list = cl.ExecuteSearch("UNSEEN UNDELETED");
//Get all unread mail
for (int i = 0; i < list.MailIndexList.Count; i++)
{
mg = cl.GetMessage(list.MailIndexList[i]);
}
}
//Change mail read state as read
cl.ExecuteStore(1, StoreItem.FlagsReplace, "UNSEEN")
}
//Create draft mail to mailbox
using (ImapClient cl = new ImapClient("imap.gmail.com"))
{
cl.Port = 993;
cl.Ssl = true;
cl.UserName = "xxxxx";
cl.Password = "yyyyy";
var bl = cl.Authenticate();
if (bl == true)
{
var smg = new SmtpMessage("from mail address", "to mail addres list"
, "cc mail address list", "This is a test mail.", "Hi.It is my draft mail");
cl.ExecuteAppend("GMail/Drafts", smg.GetDataText(), "\\Draft", DateTimeOffset.Now);
}
}
//Idle
using (var cl = new ImapClient("imap.gmail.com", 993, "user name", "pass"))
{
cl.Ssl = true;
cl.ReceiveTimeout = 10 * 60 * 1000;//10 minute
if (cl.Authenticate() == true)
{
var l = cl.GetAllFolders();
ImapFolder r = cl.SelectFolder("INBOX");
//You must dispose ImapIdleCommand object
using (var cm = cl.CreateImapIdleCommand()) Caution! Ensure dispose command object
{
//This handler is invoked when you receive a mesage from server
cm.MessageReceived += (Object o, ImapIdleCommandMessageReceivedEventArgs e) =>
{
foreach (var mg in e.MessageList)
{
String text = String.Format("Type is {0} Number is {1}", mg.MessageType, mg.Number);
Console.WriteLine(text);
}
};
cl.ExecuteIdle(cm);
while (true)
{
var line = Console.ReadLine();
if (line == "done")
{
cl.ExecuteDone(cm);
break;
}
}
}
}
}
LumiSoft.ee - works great, fairly easy. Compiles with .NET 4.0.
Here are the required links to their lib and examples.
Downloads Main:
http://www.lumisoft.ee/lsWWW/Download/Downloads/
Code Examples:
are located here: ...lsWWW/Download/Downloads/Examples/
.NET:
are located here: ...lsWWW/Download/Downloads/Net/
I am putting a SIMPLE sample up using their lib on codeplex (IMAPClientLumiSoft.codeplex.com). You must get their libraries directly from their site. I am not including them because I don't maintain their code nor do I have any rights to the code. Go to the links above and download it directly. I set LumiSoft project properties in my VS2010 to build all of it in .NET 4.0 which it did with no errors.
Their samples are fairly complex and maybe even overly tight coding when just an example. Although I expect that these are aimed at advanced level developers in general.
Their project worked with minor tweaks. The tweaks: Their IMAP Client Winform example is set in the project properties as "Release" which prevents VS from breaking on debug points. You must use the solution "Configuration Manager" to set the project to "Active(Debug)" for breakpoints to work. Their examples use anonymous methods for event handlers which is great tight coding... not real good as a teaching tool. My project uses "named" event method handlers so you can set breakpoints inside the handlers. However theirs is an excellent way to handle inline code. They might have used the newer Lambda methods available since .NET 3.0 but did not and I didn't try to convert them.
From their samples I simplified the IMAP client to bare minimum.