Send IMAP commands to GMail using C# - c#

I've been trying to access my GMail account to retrieve the unread emails from my email account. However, I only con perform login... Anything after that doesn't work.
First of all I connect to the server, then send the login command and finally the examine command. The thing is that the responses that are receive refers only to the connection and to the login. After that, it just stops waiting for someting to read from the StreamReader.
try
{
// create an instance of TcpClient
TcpClient tcpclient = new TcpClient();
// HOST NAME POP SERVER and gmail uses port number 995 for POP
//tcpclient.Connect("pop.gmail.com", 995);
tcpclient.Connect("imap.gmail.com", 993);
// This is Secure Stream // opened the connection between client and POP Server
SslStream sslstream = new SslStream(tcpclient.GetStream());
// authenticate as client
sslstream.AuthenticateAsClient("imap.gmail.com");
bool flag = sslstream.IsAuthenticated; // check flag
// Asssigned the writer to stream
System.IO.StreamWriter sw = new StreamWriter(sslstream);
// Assigned reader to stream
System.IO.StreamReader reader = new StreamReader(sslstream);
sw.WriteLine("tag LOGIN user#gmail.com pass");
sw.Flush();
sw.WriteLine("tag2 EXAMINE inbox");
sw.Flush();
sw.WriteLine("tag3 LOGOUT ");
sw.Flush();
string str = string.Empty;
string strTemp = string.Empty;
try
{
while ((strTemp = reader.ReadLine()) != null)
{
Console.WriteLine(strTemp);
// find the . character in line
if (strTemp == ".")
{
//reader.Close();
break;
}
if (strTemp.IndexOf("-ERR") != -1)
{
//reader.Close();
break;
}
str += strTemp;
}
}
catch (Exception ex)
{
string s = ex.Message;
}
//reader.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}

I was looking for just this sort of "Hello World" example to get me started. With the help of dkarp's answers, here's my take on Miguel's example:
static void Main( string[] args ) {
try {
TcpClient tcpclient = new TcpClient();
tcpclient.Connect( "imap.gmail.com", 993 );
SslStream sslstream = new SslStream( tcpclient.GetStream() );
sslstream.AuthenticateAsClient( "imap.gmail.com" );
if ( sslstream.IsAuthenticated ) {
StreamWriter sw = new StreamWriter( sslstream );
StreamReader sr = new StreamReader( sslstream );
sw.WriteLine( "tag LOGIN user#gmail.com pass" );
sw.Flush();
ReadResponse( "tag", sr );
sw.WriteLine( "tag2 EXAMINE inbox" );
sw.Flush();
ReadResponse( "tag2", sr );
sw.WriteLine( "tag3 LOGOUT" );
sw.Flush();
ReadResponse( "tag3", sr );
}
}
catch ( Exception ex ) {
Console.WriteLine( ex.Message );
}
}
private static void ReadResponse( string tag, StreamReader sr ) {
string response;
while ( ( response = sr.ReadLine() ) != null ) {
Console.WriteLine( response );
if ( response.StartsWith( tag, StringComparison.Ordinal ) ) {
break;
}
}
}

You might look at using a canned IMAP/SSL library instead - there is one that is still active here.
This alternative is not free.
The basis for one of these has source code that might be helpful since you want to roll your own protocol handler.

Your problem is that you're expecting POP responses from an IMAP server. POP terminates fetched messages with . and responds to other commands with a line beginning with either +OK or -ERR. IMAP doesn't. You're consuming all the server responses and then hanging, waiting for something to match your POP-like response parser. If you examine the returned data, you should see the remainder of the server's responses to your (properly-formatted) requests.
There is a possibility that the server isn't sending back responses to your second and third commands. This could be because you're trying to pipeline three requests; that is, you're sending the requests without waiting for the responses. The server is obliged to allow pipelining while in the SELECTED state, but the protocol doesn't guarantee that you can pipeline commands from the NOT AUTHENTICATED state.

Related

POP3 protocol. Operations STAT and LIST

I try to realize simple mail client. Now I can retriev messages:
// create an instance of TcpClient
TcpClient tcpclient = new TcpClient();
// HOST NAME POP SERVER and gmail uses port number 995 for POP
tcpclient.Connect("pop.gmail.com", 995);
// This is Secure Stream // opened the connection between client and POP Server
System.Net.Security.SslStream sslstream = new SslStream(tcpclient.GetStream());
// authenticate as client
sslstream.AuthenticateAsClient("pop.gmail.com");
//bool flag = sslstream.IsAuthenticated; // check flag
// Asssigned the writer to stream
StreamWriter sw = new StreamWriter(sslstream);
// Assigned reader to stream
StreamReader reader = new StreamReader(sslstream);
// refer POP rfc command, there very few around 6-9 command
sw.WriteLine("USER my_mail#gmail.com");
// sent to server
sw.Flush();
sw.WriteLine("PASS my_pass");
sw.Flush();
// this will retrive your first email
sw.WriteLine("RETR 1");
sw.Flush();
string str = string.Empty;
string strTemp = string.Empty;
while ((strTemp = reader.ReadLine()) != null)
{
// find the . character in line
if (strTemp == ".")
{
break;
}
if (strTemp.IndexOf("-ERR") != -1)
{
break;
}
str += strTemp;
}
//str = reader.ReadToEnd();
// close the connection
sw.WriteLine("QUIT");
sw.Flush();
richTextBox2.Text = str;
But when I try to realize operations STAT and LIST my programm crashes. I think there is a problem in cycle of reading streams. For operation STAT I try to read until "\r\n" (strTemp = "\r\n") and for operation LIST - ".\r\n" respectively.
This is my code for STAT:
// create an instance of TcpClient
TcpClient tcpclient = new TcpClient();
// HOST NAME POP SERVER and gmail uses port number 995 for POP
tcpclient.Connect("pop.gmail.com", 995);
// This is Secure Stream // opened the connection between client and POP Server
System.Net.Security.SslStream sslstream = new SslStream(tcpclient.GetStream());
// authenticate as client
sslstream.AuthenticateAsClient("pop.gmail.com");
//bool flag = sslstream.IsAuthenticated; // check flag
// Asssigned the writer to stream
StreamWriter sw = new StreamWriter(sslstream);
// Assigned reader to stream
StreamReader reader = new StreamReader(sslstream);
// refer POP rfc command, there very few around 6-9 command
sw.WriteLine("USER my_mail#gmail.com");
// sent to server
sw.Flush();
sw.WriteLine("PASS my_pass");
sw.Flush();
// this will retrive your first email
sw.WriteLine("STAT");
sw.Flush();
string str = string.Empty;
string strTemp = string.Empty;
while ((strTemp = reader.ReadLine()) != null)
{
// find the . character in line
if (strTemp == "\r\n")
{
break;
}
if (strTemp.IndexOf("-ERR") != -1)
{
break;
}
str += strTemp;
}
//str = reader.ReadToEnd();
// close the connection
sw.WriteLine("QUIT");
sw.Flush();
richTextBox2.Text = str;
After I press the button my main window is not responding. Where is my mistake?
Thank you!
Your app is most likely hung on ReadLine(). Note that StreamReader.ReadLine() does not include the \r\n. So your check for \r\n will never hit, hence that break statement will never hit.
You may simply need to change it to if (strTemp == ""). If that doesn't do the trick, you'll have to step through in the debugger.
Also note that blocking calls like this are not a good idea in the UI thread. You really should offload this to a background worker.

Host a text file on WindowsCE using a web server

Im trying to host a text file which can be viewed via a browser. This server will be running on a WindowsCE machine.
Currently when i try and view the file on my windows 7 machine using internet explorer 9 it works fine.
Once i host it on WindowsCE internet explorer just sits there waiting with the working circle rotating.
If i run a telnet on port 80 to the webserver i can see my text file is returned:
HTTP/1.1 200 OK
Content-Type: text/plain
MyTextFileContents
Below is the complete method. No exceptions are logged and it logs "Finished serving log".
static void launchLogWebServer()
{
new Thread(delegate()
{
LogIt(0, "Starting Log Server");
TcpListener server = new TcpListener(IPAddress.Any, 80);
server.Start();
TcpClient newConn;
while (true)
{
try
{
newConn = server.AcceptTcpClient();
LogIt(0, "Connection Made to Log Server");
NetworkStream stream = newConn.GetStream();
StreamReader sr = new StreamReader(stream);
StreamWriter sw = new StreamWriter(stream);
sw.WriteLine("HTTP/1.1 200 OK");
sw.WriteLine("Content-Type: text/plain");
sw.WriteLine();
String line = null;
while ((line = sr.ReadLine()).Length != 0)
{
}
string text = string.Empty;
LogIt(0, "Reading Log File");
try
{
using (StreamReader logReader = new StreamReader("mylog.log"))
{
text = logReader.ReadToEnd();
logReader.Close();
}
}
catch (Exception ex)
{
LogIt(0, ex.ToString());
text = ex.ToString();
}
LogIt(0, "Completed Reading Log File");
sw.WriteLine(text);
sw.Flush();
newConn.Close();
LogIt(0, "Finished serving log");
}
catch(Exception ex)
{
LogIt(0, ex.ToString());
}
}
}).Start();
}
EDIT: I should also note my WindowsCE is running .NET Compact Framework 2.0
You need to add 'Content-Length' parameter in HTTP header.

How to read the body of the message in the mail retrieve from gmail by using pop3 in c #?

This is code:
protected void Button9_Click(object sender, EventArgs e)
{
try
{
// create an instance of TcpClient
TcpClient tcpclient = new TcpClient();
// HOST NAME POP SERVER and gmail uses port number 995 for POP
tcpclient.Connect("pop.gmail.com", 995);
// This is Secure Stream // opened the connection between client and POP Server
System.Net.Security.SslStream sslstream = new SslStream(tcpclient.GetStream());
// authenticate as client
sslstream.AuthenticateAsClient("pop.gmail.com");
//bool flag = sslstream.IsAuthenticated; // check flag
// Asssigned the writer to stream
System.IO.StreamWriter sw = new StreamWriter(sslstream);
// Assigned reader to stream
System.IO.StreamReader reader = new StreamReader(sslstream);
// refer POP rfc command, there very few around 6-9 command
sw.WriteLine("USER your_gmail_user_name#gmail.com");
// sent to server
sw.Flush(); sw.WriteLine("PASS your_gmail_password");
sw.Flush();
// RETR 1 will retrive your first email. it will read content of your first email
sw.WriteLine("RETR 1");
sw.Flush();
// close the connection
sw.WriteLine("Quit ");
sw.Flush(); string str = string.Empty;
string strTemp = string.Empty;
while ((strTemp = reader.ReadLine()) != null)
{
// find the . character in line
if (strTemp == ".")
{
break;
}
if (strTemp.IndexOf("-ERR") != -1)
{
break;
}
str += strTemp;
}
textbox1.text = str;
textbox1.text += "<BR>" + "Congratulation.. ....!!! You read your first gmail email ";
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
The message body is a bunch of what appears to be random characters. I know it's not just a bunch of random characters but some code that needs to be parsed and converted. How can I read content in "message body"?
I know i'm not directly replying to your answer but reading email is a really complex task and I think you can achieve this better and faster with an external library instead of implementing it by yourself.
There are many good implementation, i usually use OpenPop.NET which works fine and is opensource.
https://sourceforge.net/projects/hpop/
You can find many example on internet because it is really popular.
http://hpop.sourceforge.net/examples.php
you can get all mail easly:
using(Pop3Client client = new Pop3Client())
{
// Connect to the server
client.Connect("pop.gmail.com", 995, true);
// Authenticate ourselves towards the server
client.Authenticate("username#gmail.com", "password", AuthenticationMethod.UsernameAndPassword);
// Get the number of messages in the inbox
int messageCount = client.GetMessageCount();
// We want to download all messages
List<Message> allMessages = new List<Message>(messageCount);
// Messages are numbered in the interval: [1, messageCount]
// Ergo: message numbers are 1-based.
// Most servers give the latest message the highest number
for (int i = messageCount; i > 0; i--)
{
allMessages.Add(client.GetMessage(i));
}
}
you can get the full raw message
var mailbody = ASCIIEncoding.ASCII.GetString(message.RawMessage);
or if it is an utf8 encoded email:
var encodedStringAsBytes = System.Convert.FromBase64String(message.RawMessage);
var rawMessage =System.Text.Encoding.UTF8.GetString(encodedStringAsBytes);
Instead if you want only the mail body you have to dig into the mail structure:
http://hpop.sourceforge.net/documentation/OpenPop~OpenPop.Mime.MessagePart.html
I know it is not an easy task but as I stated above emails are complex objects.

Pipe is being closed Exception

Sometimes, on some machines often and on some seldom, the clients which are using my program are getting a "pipe is being closed" exception. This happens on the NamedPipeServerStream that is on .WaitForConnection(). After that, the Application totally crashes and releases a windows exception. This happens when a NamedPipeClientStream transfers information to the standalone application.
main Funktionality:
I wrote several Tools (Office Toolbars, a Service, a standalone .net Application, and a litle starter exe) that communicate together with NamedPipes.
The Service runs a NamedPipeServerStream that is always open (in state .WaitForConnection();) and the Standalone Application has a NamedPipeServerStream too.
The Toolbars and starter .exe communicate with the service. The Service then with the Standalone Application.
what kind of problems can release the pipe is being closed Exception?
Is it possible that the server sends information to the Standalone Application but closes the stream to early because the Standalone Application is not ready or something? on each NamedPipeClientStream i do a waitforpipedrain if pipeClient.IsConnected befor i close the pipeclient..
thanks for help
edit: Here an Example of a clientstream
using (NamedPipeClientStream pipeClient =
new NamedPipeClientStream(".", pipename, PipeDirection.Out))
{
// Wait for a client to connect
try
{
pipeClient.Connect(3000);
// send params to the form
using (StreamWriter sw = new StreamWriter(pipeClient))
{
sw.AutoFlush = true;
sw.WriteLine(sendtext);
}
}
// Catch the IOException that is raised if the pipe is
// broken or disconnected.
catch (Exception e)
{
if (sid != "")
{
connections.Remove(conName);
}
eventLog1.WriteEntry("SendText Fehler 1 " + e.Message);
}
finally
{
if (pipeClient.IsConnected)
{
pipeClient.WaitForPipeDrain();
}
pipeClient.Close();
pipeClient.Dispose();
}
Example of an pipeserver (that runs in a seperad thread)
NamedPipeServerStream pipeServer;
PipeSecurity pipe_security = CreateSystemIoPipeSecurity();
do
string pipename = global::TOfficeCenter.Properties.Settings.Default.pipename;
string aText = "";
pipeServer = new NamedPipeServerStream(pipename, PipeDirection.In, ONE_INSTANCE, PipeTransmissionMode.Byte,
PipeOptions.None, IN_BUF_SIZE, OUT_BUF_SIZE, pipe_security);
try
{
// Verbindung zu TOfficeCenter.exe aufbauen
try
{
IsWaiting = true;
pipeServer.WaitForConnection();
IsWaiting = false;
using (StreamReader sr = new StreamReader(pipeServer))
{
string temp;
while ((temp = sr.ReadLine()) != null)
{
aText = aText + temp;
}
}
try
{
if (aText == "")
{
empfang(null);
}
else
{
if (aText != "KillPipe")
{ // XML empfangen
XmlDocumentTC xml = new XmlDocumentTC();
xml.LoadXml(aText);
empfang(xml);
}
}
}
catch (Exception)
{
empfang(null);
}
}
catch
{...........
}
}
catch (Exception e)
{...........
}
} while (running);
pipeServer.Close();
It's possible that i finally found the problem..
I found out that after this code:
using (StreamWriter sw = new StreamWriter(pipeClient))
{
sw.AutoFlush = true;
sw.WriteLine(sendtext);
}
the pipeClient.IsConnected(); returns directly false, so that it never comes to the WaitForPipeDrain. I Now did it like that and hope that the client does not close the connection before the server is finished with reading..
using (StreamWriter sw = new StreamWriter(pipeClient))
{
sw.AutoFlush = true;
sw.WriteLine(sendtext);
pipeClient.WaitForPipeDrain();
}
Do You Think that could have solved the problem? Since i did it, i never got the error on two test-machines. But the Errors anyway happened seldom..
My use is a bit different, but I'll include the server thread in sum as it's mostly being hacked from the MSDN page at present:
MSDN: How to Use Named Pipes
Not sure if the "WaitForPipeToDrain()" is needed for me, but I took it from your code :)
I think the reset of the pipeServer each time is what cleaned up my IOException.
int threadId = Thread.CurrentThread.ManagedThreadId;
bool sentinel = true;
while (sentinel)
{
NamedPipeServerStream pipeServer =
new NamedPipeServerStream("shapspipe", PipeDirection.InOut, 1);
// Wait for a client to connect
pipeServer.WaitForConnection();
Console.WriteLine("Client connected on thread[{0}].", threadId);
try
{
// Read the request from the client. Once the client has
// written to the pipe its security token will be available.
StreamString ss = new StreamString(pipeServer);
// Verify our identity to the connected client using a
// string that the client anticipates.
ss.WriteString("I am the one true server!");
string message = ss.ReadString();
Console.WriteLine("received from client: " + message);
ss.WriteString("echo from server: " + message);
Console.WriteLine("Received from client: {0} on thread[{1}] as user: {2}.",
message, threadId, pipeServer.GetImpersonationUserName());
}
// Catch the IOException that is raised if the pipe is broken
// or disconnected.
catch (IOException e)
{
Console.WriteLine("ERROR: {0}", e.Message);
}
pipeServer.WaitForPipeDrain();
pipeServer.Close();
}

Reading a POP3 server with only TcpClient and StreamWriter/StreamReader

I'm trying to read mails from my live.com account, via the POP3 protocol.
I've found the the server is pop3.live.com and the port if 995.
I'm not planning on using a pre-made library, I'm using NetworkStream and StreamReader/StreamWriter for the job. I need to figure this out. So, any of the answers given here: Reading Email using Pop3 in C# are not usefull.
It's part of a larger program, but I made a small test to see if it works. Eitherway, i'm not getting anything. Here's the code I'm using, which I think should be correct.
EDIT: this code is old, please refer to the second block problem solved.
public Program() {
string temp = "";
using(TcpClient tc = new TcpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"),8000))) {
tc.Connect("pop3.live.com",995);
using(NetworkStream nws = tc.GetStream()) {
using(StreamReader sr = new StreamReader(nws)) {
using(StreamWriter sw = new StreamWriter(nws)) {
sw.WriteLine("USER " + user);
sw.Flush();
sw.WriteLine("PASS " + pass);
sw.Flush();
sw.WriteLine("LIST");
sw.Flush();
while(temp != ".") {
temp += sr.ReadLine();
}
}
}
}
}
Console.WriteLine(temp);
}
Visual Studio debugger constantly falls over tc.Connect("pop3.live.com",995); Which throws an "A socket operation was attempted to an unreachable network 65.55.172.253:995" error.
So, I'm sending from port 8000 on my machine to port 995, the hotmail pop3 port.
And I'm getting nothing, and I'm out of ideas.
Second block: Problem was apparently that I didn't write the quit command.
The Code:
public Program() {
string str = string.Empty;
string strTemp = string.Empty;
using(TcpClient tc = new TcpClient()) {
tc.Connect("pop3.live.com",995);
using(SslStream sl = new SslStream(tc.GetStream())) {
sl.AuthenticateAsClient("pop3.live.com");
using(StreamReader sr = new StreamReader(sl)) {
using(StreamWriter sw = new StreamWriter(sl)) {
sw.WriteLine("USER " + user);
sw.Flush();
sw.WriteLine("PASS " + pass);
sw.Flush();
sw.WriteLine("LIST");
sw.Flush();
sw.WriteLine("QUIT ");
sw.Flush();
while((strTemp = sr.ReadLine()) != null) {
if(strTemp == "." || strTemp.IndexOf("-ERR") != -1) {
break;
}
str += strTemp;
}
}
}
}
}
Console.WriteLine(str);
}
What happens if you view the Network Traffic using Wireshark? Is it sending anything at all?
Edit: I can't connect via telnet to pop3.live.com at that port either. Have you managed to successfully connect via a pop3 email client ever?

Categories

Resources