C# : POP3 renvoie des réponses incorrectes

Bonjours à tous et à toutes

Je m’essaye aujourd’hui à la lecture des messages en POP3 et j’ai un problème: lorsque j’envoie certaines requetes, la réponse du serveur est incorrecte, ou peut-etre je tente de lire la mauvaise réponse: exemple:
j’envoire RETR 1,et la réponse est la liste des messages, soit LIST, commande que j’ai envoyé juste avant. Faut-il que je laisse un peu de temps au serveur pour “souffler”?

Le bug apparait sur différents serveurs POP3, comme laposte.net ou ifrance.com
 Voila le code

public class Session  { public string Host; public string UserName; public string Password; public int Port; public ArrayList Messages=new ArrayList(); byte[] Buffer;   private NetworkStream stream; private TcpClient client=new TcpClient();

public string LastMessage;
public Session(string host,int port,string username,string password)
{
 Host=host;
 Port=port;
 UserName=username;
 Password=password;
}

private bool dataReady=false;
private string CurrentData;

public string ExecuteCommand(string command)
{
 dataReady=false;
 CurrentData="";
 
 command+=System.Environment.NewLine;
 byte[] data=System.Text.Encoding.ASCII.GetBytes(command.ToCharArray());
 Buffer=new byte[client.ReceiveBufferSize];

 stream.Write(data,0,data.Length);
 stream.BeginRead(Buffer,0,client.ReceiveBufferSize,new AsyncCallback(ReceiveData),null);

 while(dataReady==false)
 {
Thread.Sleep(100);
 }
 return CurrentData;
}
 
private void ReceiveData( IAsyncResult ar )
{
 CurrentData+=System.Text.Encoding.ASCII.GetString(Buffer);
 dataReady=true;  
}

private bool DoLogin()
{
 try
 {
client.Connect(Host,Port);
 }
 catch
 {
LastMessage=“Erreur de connection avec le serveur”;
return false;
 }
 stream=client.GetStream();
 
 if(TryCommand("user "+UserName)==false)
 {
LastMessage=“Identifiant incorrect”;
return false;
 }
 if(TryCommand("pass "+Password)==false)
 {
LastMessage=“Mot de passe incorrect”;
return false;
 }
 return true;
}

public bool Connect()
{
 return DoLogin();
}

public bool Disconnect()
{
 bool z=TryCommand(“QUIT”);
 client.Close();
 if(z==false)
LastMessage=“Erreur lors de la fermeture de la connection”;
 return z;
}

public bool GetMessages()
{
 if(Connect())
 {
bool z=PrepareMessages();
if(z)
{
 foreach(Message m in Messages)
 {
m.Retrieve();
 }
}
else
 LastMessage=“Erreur lors de la vérification des messages”;

Disconnect();
return z;

 }
 else
 {

return false;

 }
}

private bool PrepareMessages()
{
 string r;
 r=ExecuteCommand(“LIST”);

 if(CheckResponse®==true)
 {
ArrayList list=ParseResponse®;
string[] minf;
int idx=0;
foreach(string s in list)
{
 if(idx>0 & idx<list.Count-1)
 {
minf=s.Split(’ ');

  Messages.Add(new Message(this,minf[0],int.Parse(minf[1])));
&nbsp;}
&nbsp;idx++;
}
return true;

 }
 else
 {
LastMessage=“Erreur lors de la requete de la liste de messages”;
return false;
 }
}

public bool TryCommand(string command)
{
 string s=ExecuteCommand(command);
 return CheckResponse(s);
}
 

private string GetResponse() 
{
 byte[] bytes=new byte[client.ReceiveBufferSize];
 int ret=stream.Read(bytes,0,bytes.Length);
 string returndata=System.Text.Encoding.ASCII.GetString(bytes)  ;
 stream.Flush();
 return returndata;
}

public bool CheckResponse(string response)
{
 if(response.StartsWith("+OK"))
return true;
 else
return false;
}

public static ArrayList ParseResponse(string response)
{
 int idx=0;
 int pos=-1;
 int next=0;
 ArrayList ret=new ArrayList();

 while(next>(-1))
 {
next=response.IndexOf(System.Environment.NewLine,pos+1);
if(next>-1)
 ret.Add(response.Substring(pos+1,next-pos-1));
pos=next+1;
 }
 return ret;

}

 }

 public class Message
 {
private Session session;
private string ID;
public int Length;

internal Message(Session s,string id,int lenght)
{
 session=s;
 ID=id;
 Length=lenght;
}

public void Retrieve()
{
 string m;
 m=session.ExecuteCommand("retr " + ID);
 ArrayList l=Session.ParseResponse(m);

}

 }
[/quote]Une idée peut-etre?

ok, merci à tous pour vos commentaires nombreux et instructifs, si,si, chaudement merci!

bon, vu que je ne suis pas un sale egoiste et qu’en plus j’ai trouvé la solution tout seul, je vous le dis: il faut attacher un StreamReader au stream renvoyé par le TcpClient. Voila, pour ceux qui veulent le code, je peut toujours donner ca, hein, je suis pas cool moi?

PS: si vous avez une idée a propos de mon theard précédent, “Word.net”, je suis toujours preneur…
Ce message a été édité par bwets le 11/01/2004

Bon, y’a un problème dans ta facon de recevoir les données.
D’une part, pourquoi utiliser une lecture du stream en asynchrone, si tu attends la réponse avant de sortir de la fonction. D’autre part, ta foncition receive lit tout le buffer, bien qu’il ne soit pas forcément plain.

Sinon, tu n’as aucun moyen de savoir que le serveur a fini de répondre, vu qu’un appel a Read (ou a BeginRead) ne renvoie que ce qu’il y a dans le buffer d’entrée. Il faut donc attendre la fin du message, signalée par . dans le protocole POP3

[quote]Bon, y’a un problème dans ta facon de recevoir les données.
D’une part, pourquoi utiliser une lecture du stream en asynchrone, si tu attends la réponse avant de sortir de la fonction. D’autre part, ta foncition receive lit tout le buffer, bien qu’il ne soit pas forcément plain.

Sinon, tu n’as aucun moyen de savoir que le serveur a fini de répondre, vu qu’un appel a Read (ou a BeginRead) ne renvoie que ce qu’il y a dans le buffer d’entrée. Il faut donc attendre la fin du message, signalée par . dans le protocole POP3[/quote]merci bcp, mais ca n’etait pas le pb, je pense que je piquait les données au mauvais endroit. En fait j’avais essayé le monde synchrone et asynchrone, et les deux donnaient le meme résultat, meme en attendant la fin du transfert. Mais vu que c’est reglé… merci quand meme

Effectivement, le streamreader permet de transformer le flux binaire en texte clair.
Tu peux alors utiliser ReadLine (vu que le pop3 fonctionne avec les saut de ligne), t’es donc sur que les lignes recues sont complètes. Par contre, il faut bien lire jusqu’a recevoir une ligne composée d’un point ‘.’ seul.

oui, oui, ca je le savais, le probleme etait:
je fais un STAT, il me revoie +OK 2 464654 puis un RETR 1 et il me renvoyait encore +OK 2 464654.

Bon ca c’est un exemple, ca pouvait aussi etre:
RETR 1 et il me renvoie le résultat de LIST… comme je disais, le pb etais le streamreader qui lit lui meme au bon endroit dans le stream. Je pense que j’oubliais simplement d’incrémenter l’index de lecture dans le stream.

Perso, je crois plutôt que tu relisait le buffer pas encore écris, mais ca reviens au même .

c aussi ce que je me disait, mais ca donnait le meme resultat en faisant un Thread.Sleep(1000) entre la requette et la lecture de la réponse… m’enfin bon…