我必须通过C#和.NET Standard 2.0在我自己的电子邮件客户端中实现IMAP。在任务期间,我可以使用TcpClient和SslStream类。问题在于从服务器获得响应。我找不到如何识别消息结束的通用解决方案。比如SMTP有" \ r \ n。\ r \ n"在每条消息的最后,IMAP没有相同的模式(根据我的研究)。大多数IMAP邮件以[TAG] [RESPONSE]
结尾,例如A1 OK success
,但有些邮件以* OK Gimap...
或* BAD Invalid...
结尾。我刚写了几行代码:
class Program
{
static TcpClient tcp;
static SslStream ssl;
static void Main(string[] args)
{
tcp = new TcpClient("imap.gmail.com", 993);
ssl = new SslStream(tcp.GetStream());
ssl.AuthenticateAsClient("imap.gmail.com");
ReceiveResponse("");
while (true)
{
try
{
string query = Console.ReadLine();
if (query == "exit") break;
ReceiveResponse(query + "\r\n");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
Console.WriteLine(ReceiveResponse("$ LOGOUT\r\n"));
Console.ReadKey();
}
static string ReceiveResponse(string query)
{
StringBuilder sb = new StringBuilder();
try
{
if (query != "")
{
if (tcp.Connected)
{
byte[] dummy = Encoding.ASCII.GetBytes(query);
ssl.Write(dummy, 0, dummy.Length);
}
else
{
throw new ApplicationException("TCP CONNECTION DISCONNECTED!!");
}
}
ssl.Flush();
byte[] buffer = new byte[1024];
List<byte> response = new List<byte>();
while (true) // ваш метод, который определит полный ответ
{
int bytesRead = ssl.Read(buffer, 0, 1024);
if (bytesRead == 0)
throw new EndOfStreamException("err");
string str = Encoding.UTF8.GetString(buffer).Replace("\0", "");
sb.Append(str);
if (/* PATTERN I NEED*/) break;
}
Console.WriteLine(sb.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return sb.ToString();
}
}
如您所知,我需要使用该模式来识别消息的单义结尾,或者至少解决如何从IMAP服务器获取完整消息的方法。
P.S。我不是英语母语人士,如果你能用简单的语言表达你的思想,那就太好了。提前谢谢。
答案 0 :(得分:2)
IMAP响应是一行,或n部分加一行。四种反应只有一行:OK,BYE,NO和BAD。其他部分是n个部分,其中每个部分是以{number}结尾的行,后跟该字节数,以及一个不以{number}结尾的最后一行。
page 80 of RFC 3501上的示例清楚地显示了这两种情况。请注意,即使单行也可能很长,实际上比1024字节长得多。 formal syntax starting on page 81描述了细节;我故意遗漏了一些细节。