Buscar

viernes, 22 de mayo de 2009

Recibir o leer correos por c# .net mediante pop3

Esta es una clase para leer correos desde c#, mediante pop3, básicamente es una conexión al servidor de correo y le mandamos parámetros, como si lo estuviéramos haciéndolo por telnet o consola. Lo ensaye con un servidor de correo Linux, pero no he tenido la oportunidad de ensayarlo ni con gmail ni con Hotmail. Si alguien tiene la oportunidad de ensayarlos espero que dejen sus comentarios.
Este código fue sacado de este enlace, donde hay una muy buena explicación de cómo funciona (Esta en ingles), cuando tenga tiempo de ensayarlo y analizarlo pondré los comentarios de su funcionamiento:

http://www.csharphelp.com/archives2/archive450.html
Nota: Los correos se visualizan en texto plano, con todas las cabeceras

espacio de nombres

using System;
using System.Collections.Generic;
using System.Text;
using a=System.Net ;
using System.Net.Mail;
using System.Net.Mime;
using System.Collections;
using System.Net.Sockets;
using System.Diagnostics;



//http://www.csharphelp.com/archives2/archive450.html
public class Pop3Exception : System.ApplicationException
{
public Pop3Exception(string str) : base(str)
{

}

}


public class Pop3Message
{
public long number;
public long bytes;
public bool retrieved;
public string message;
}





public class Pop3 : System.Net.Sockets.TcpClient
{
public void Connect(string server, string username, string password)
{
string message;
string response;
Connect(server, 110);
response = Response();
if (response.Substring(0, 3) != "+OK")
{
throw new Pop3Exception(response);
}
message = "USER " + username + "\r\n";
Write(message);
response = Response();
if (response.Substring(0, 3) != "+OK")
{
throw new Pop3Exception(response);
}
message = "PASS " + password + "\r\n";
Write(message);
response = Response();
if (response.Substring(0, 3) != "+OK")
{
throw new Pop3Exception(response);
}
}
public void Disconnect()
{
string message;
string response;
message = "QUIT\r\n";
Write(message);
response = Response();
if (response.Substring(0, 3) != "+OK")
{
throw new Pop3Exception(response);
}
}

public ArrayList List()
{
string message;
string response;

ArrayList retval = new ArrayList();

message = "LIST\r\n";
Write(message);
response = Response();
if (response.Substring(0, 3) != "+OK")
{
throw new Pop3Exception(response);
}

while (true)
{
response = Response();
if (response == ".\r\n")
{
return retval;
}
else
{
Pop3Message msg = new Pop3Message();
char[] seps = { ' ' };
string[] values = response.Split(seps);
msg.number = Int32.Parse(values[0]);
msg.bytes = Int32.Parse(values[1]);
msg.retrieved = false;
retval.Add(msg);
continue;
}
}
}

public Pop3Message Retrieve(Pop3Message rhs)
{
string message;
string response;
Pop3Message msg = new Pop3Message();
msg.bytes = rhs.bytes;
msg.number = rhs.number;
message = "RETR " + rhs.number + "\r\n";
Write(message);
response = Response();
if (response.Substring(0, 3) != "+OK")
{
throw new Pop3Exception(response);
}
msg.retrieved = true;
while (true)
{
response = Response();
if (response == ".\r\n")
{
break;
}
else
{
msg.message += response;
}
}
return msg;
}

public void Delete(Pop3Message rhs)
{
string message;
string response;
message = "DELE " + rhs.number + "\r\n";
Write(message);
response = Response();
if (response.Substring(0, 3) != "+OK")
{
throw new Pop3Exception(response);
}
}


private void Write(string message)
{

System.Text.ASCIIEncoding en = new System.Text.ASCIIEncoding();

byte[] WriteBuffer = new byte[1024];
WriteBuffer = en.GetBytes(message);
NetworkStream stream = GetStream();
stream.Write(WriteBuffer, 0, WriteBuffer.Length);
Debug.WriteLine("WRITE:" + message);
}



private string Response()
{

System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();

byte[] serverbuff = new Byte[1024];
NetworkStream stream = GetStream();
int count = 0;
while (true)
{

byte[] buff = new Byte[2];
int bytes = stream.Read(buff, 0, 1);
if (bytes == 1)
{
serverbuff[count] = buff[0];
count++;
if (buff[0] == '\n')
{
break;
}
}
else
{
break;
};
};

string retval = enc.GetString(serverbuff, 0, count);
Debug.WriteLine("READ:" + retval);
return retval;
}

}






Utilización:



private void button1_Click(object sender, EventArgs e)
{
try
{
Pop3 obj = new Pop3();
obj.Connect("correo.xxxxxxx.com","usuario(sin @)","Pass");
ArrayList list = obj.List();
foreach (Pop3Message msg in list)
{
Pop3Message msg2 = obj.Retrieve(msg);
textBox1.Text += "N." +msg2.number + "Mensaje" + msg2.message;
}
obj.Disconnect();
}
catch (Pop3Exception E)
{
textBox1.Text= E.ToString();
}
}

31 comentarios:

  1. Hola, muy util lo que comentas, he probado a usarlo pero me surge el problema que las tildes y 'ñ' no me las recupera correctamente del cuerpo del mensaje. ¿sabrías como solucinar este problema?

    ResponderEliminar
  2. Bueno me contesto yo mismo jejeje, habría que modificar el encoding ASCII por Encoding iso = Encoding.GetEncoding("ISO-8859-1");

    Espero le sirva a alguien. Un saludo.

    ResponderEliminar
  3. Fernado, muchas gracias por tu aporte.

    ResponderEliminar
  4. hola! he probado el codigo y no me deja conectarme al servidor de gmail.. la verdad es q no se porque, en servidor le he pasado "pop.gamil.com" y tambien he probado con "mail.google.com". la verdad es que no entiendo mucho de sockets y protocolos, si me podeia ayudar solo quiero leer el inbox!!! en java habia una clase facilisma de usae.. javaMail.. crei q con c# seria parecido...
    muchas graciaass!!
    ADRIANA

    ResponderEliminar
  5. Intenta poniendo en el método Connect de la clase Pop3
    Connect(server, 995); // este es el puerto de gmail

    Y nos cuentas como te va.

    ResponderEliminar
  6. Estoy probándolo y aparentemente funciona bien. Muchas gracias.

    ResponderEliminar
  7. Saludos
    A mí no me funciona, yo quiero leer mis correos de gmail, entonces pongo como servidor pop.gmail.com, en user solo el nombre de mi usuario, sin el @gmail.com, y luego el password,, también cambie el puerto a 995. Pero la funcion Connect(), no logra conectarse, creo que ocurre un timeout. Que consejos me pueden dar? algo que no haya probado aún?

    ResponderEliminar
  8. Jaas.
    Tengo un par de preguntas:

    1. Lo has configurado con Exchange, estoy tratando de hacerlo sin éxito.
    2. Has probado ponerlo como servicio?

    ResponderEliminar
    Respuestas
    1. Hola Cesar, estuve leyendo el post y vi tu pregunta, has probado hacerlo como servicio el tema de los correos?..

      Saludos
      te dejo mi correo
      andre.haro.miranda@gmail.com

      Cudiate

      Eliminar
  9. ¡¡¡¡ Felicidades, gente !!!!
    Esto funciona de miedo.

    ResponderEliminar
    Respuestas
    1. Hola amigo no me corre el codigo
      hiciste algo especial ?
      por favor comentame

      Eliminar
  10. Este comentario ha sido eliminado por un administrador del blog.

    ResponderEliminar
  11. Les funcionó para leer correos de Gmail??? como lo hicieron?

    ResponderEliminar
  12. Buenas ,
    este código me produce un fallo de host , cuando pongo
    obj.Connect("pop.gemail.com", "usuario", "Pass");

    me da fallo aqui

    Connect("server", 995);

    dandome el fallo de "host no encontrado" , alguien sabe el porque???
    Gracias

    ResponderEliminar
  13. Te da error porque no es pop.gEmail.com, Sino pop.gmail.com, osea te sobra la "e"

    ResponderEliminar
  14. Muchas gracias jaas ,
    Si tienes razón ,eso estaba equivocado aunque despues de cambiarlo me da un error en el response
    ArgumentOutOfRangeException: El índice y la longitud deben hacer referencia a una ubicación en la cadena.

    Nombre del parámetro: length

    , es decir el primer response me da una cadena vacia ("") , y no se solucionarlo

    gracia spor vuestra atención , y si soy algo inutilo xD

    ResponderEliminar
    Respuestas
    1. conseguiste solucionarlo?
      Me pasa lo mismo

      Eliminar
  15. El codigo funciona esta muy bueno... solo le falta leer archivos adjuntos..... :( si tuviera eso seria excelente

    ResponderEliminar
    Respuestas
    1. como solucionaste el error que tenías de longitud?.
      Saludos

      Eliminar
  16. Un codigo genial ... pero ¿alquien sabe como leer archivos adjuntos?

    ResponderEliminar
  17. muy bueno, funciona, pero no puedo leer el cuerpo del correo, hay alguna forma de obtenerlo directamente y poder pasarlo a una variable??

    MUCHAS GRACIAS

    ResponderEliminar
    Respuestas
    1. hola me sale este error en la variable ArrayList :
      Error 1 No se puede encontrar el tipo o el nombre de espacio de nombres 'ArrayList' (¿falta una directiva using o una referencia de ensamblado?)
      C:\Users\MANUEL\AppData\Local\Temporary Projects\WindowsFormsApplication1\Form1.cs 25 17 WindowsFormsApplication1

      Eliminar
    2. bueno me respondo yo mismo
      faltaba este imports de la libreria
      coloquenla arriba de la clase

      using System.Collections; // falta esta libreria

      Eliminar
  18. Me sale el mismo error del response, la cadena llega vacia. Alguien logró solucionarlo??

    ResponderEliminar
  19. hola me sale este error en la variable ArrayList :
    me sale este unico error:
    Error 1 No se puede encontrar el tipo o el nombre de espacio de nombres 'ArrayList' (¿falta una directiva using o una referencia de ensamblado?)
    C:\Users\MANUEL\AppData\Local\Temporary Projects\WindowsFormsApplication1\Form1.cs 25 17 WindowsFormsApplication1

    ResponderEliminar
  20. Sale un error que no han comentado:
    An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll en la linea de : if (response.Substring(0, 3) != "+OK") que sera?

    ResponderEliminar
    Respuestas
    1. Este comentario ha sido eliminado por el autor.

      Eliminar
    2. Bueno averigüe que es por que el string response esta vacio, alguna idea del problema? y ya habilite la descarga de correo pop en mi configuracion de gmail

      Eliminar
    3. Han averiguado porque ocurre tal error? yo estoy con lo mismo, habiendo habilitado POP en gmail

      Eliminar