Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.15.229.113] |
|
Сообщ.
#1
,
|
|
|
POP3 (Post Office Protocol version 3 - протокол приёма почты) нужен для приёма почты с почтового сервера. Использует 110
порт, по которому посылаются команды и текст письма. На написание этой статьи меня сподвигло то что после долгих поисков в сети примера, показывающего как работать с POP3 протоколом с помощью VB.NET так и не привело к успеху, но благодаря FlyDead'у, который поделился примером на С# (с хорошими коментариями) мне всетаки удалость приконектиться к 110 порту своего почтового сервера и забрать оттудого свою почту. Далее я приведу код любезно предоставленный FlyDead'ом и подробно опишу код на VB.NET Public void CheckMail() { NetworkStream ns; StreamReader sr; //два потока для чтения из потока StreamWriter sw; //и для записи в поток String response; //для хранения результата запроса TcpClient tcpClient = new TcpClient(); //создаем клиент try { tcpClient.Connect(cConfig.ServerPop,Convert.ToInt32(cConfig.PortPop)); } catch(SocketException sExc) { MessageBox.Show("Соединение неустановлено \n"+"Проверьте настройки POP3 сервера и номер порта \n"+sExc.Message); Return; } catch(Exception eX) { MessageBox.Show("Соединение неустановлено \n"+eX.Message); Return; } ns = tcpClient.GetStream(); //запускаем потоки sr = new StreamReader(ns); sw = new StreamWriter(ns); response = sr.ReadLine(); sw.WriteLine("User " + cConfig.UserPop); //посылаем юзера sw.Flush(); response = sr.ReadLine(); //опять читаем что вернул сервер If (response.Substring(0,3) == "-ER") //если вернул сообщение об ошибке { MessageBox.Show("Неверный логин","Ошибка аутентификации",MessageBoxButtons.OK,MessageBoxIcon.Error); Return; } sw.WriteLine("Pass " + cConfig.PasswordPop); //Послылаем пароль sw.Flush(); //очистка response = sr.ReadLine(); //опять читаем If (response.Substring(0,4) == "-ERR") //если не ошибка то идем дальше { MessageBox.Show("Неверный пароль","Ошибка аутентификации",MessageBoxButtons.OK,MessageBoxIcon.Error); Return; } sw.WriteLine("stat"); sw.Flush(); response = sr.ReadLine(); String[] nummess = response.Split(' '); Int totmessages; totmessages = Convert.ToInt16(nummess[1]); If (totmessages > 0) { notifyIcon1.Icon = (System.Drawing.Icon)resources.GetObject("2.ico"); MessageBox.Show(Convert.ToString(totmessages)+" новых сообщений"); } Else { notifyIcon1.Icon = (System.Drawing.Icon)resources.GetObject("1.ico"); } tcpClient.Close(); } А теперь все то же самое на VB.NET 1. Шаг первый, надо соединиться с сервером, вот код который это делает: Dim client As Net.Sockets.TcpClient Dim sr As IO.StreamReader Dim sw As IO.StreamWriter Dim ns As Net.Sockets.NetworkStream Dim otvet As String 'соединяемся с сервером client = New Net.Sockets.TcpClient Try client.Connect(server, 110) Catch e As Exception MessageBox.Show("Соединение не установленно" + e.ToString, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly, False) Return End Try ns = client.GetStream sr = New IO.StreamReader(ns, Encoding.ASCII, True) 'это то что отправляет наши команды на сервер sw = New IO.StreamWriter(ns) 'а это то что читает ответы сервера otvet = sr.ReadLine() 'это наш ответ от сервера На это нам сервер должен ответить +ОК [какойто текст]. В конце каждой отправленной сервером строки обязательно символы перехода на новую строку(chr(13) & chr(10)) 2.Второй шаг, после утвердительного ответа сервера отправляем имя пользователя user [имя] & chr(13) & chr(10) На что сервер нам может ответить следующее: +OK [какойто текст] - такой пользователь существует, продолжайте -ERR [какойто текст] - ошибка, либо такого пользователя нет Вот код который это делает: sw.WriteLine("User " & user & Chr(13) & Chr(10)) sw.Flush() otvet = sr.ReadLine() If otvet.Substring(0, 3) = "-ER" Then _ MessageBox.Show("Неверный логин", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error,_ MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly, False) 3.Далее посылаем серверу пароль pass [****] & chr(13) & chr(10) Вместо **** указывается пароль. На что сервер нам опять ответит следующим: +OK [какойто текст] - пароль верный, продолжайте -ERR [какойто текст] - ошибка, либо неверный пароль Вот код который это делает: 'отправляем пароль sw.WriteLine("Pass " & pass & Chr(13) & Chr(10)) sw.Flush() otvet = sr.ReadLine If otvet.Substring(0, 4) = "-ER" Then _ MessageBox.Show("Неверный пароль", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error,_ MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly, False) 4.Теперь можно определить количество новых писем на сервере, и их общий объём, для этого отправим stat Ответом будет +OK [кол-во] [объем] Dim nummess As Array Dim totmessages As Integer sw.WriteLine("stat") sw.Flush() otvet = sr.ReadLine() nummess = otvet.Split(" ") totmessages = CInt(nummess(1)) 5.Для того чтобы определить индексы писем и объем каждого по отдельности, отправляем list Сервер ответит списком с номером и объемом письма +OK 2 messages 320 1 120 2 200 . Список оканчивается переходом на новую строку и знаком "." Dim i As Integer Dim MessageArr() As String 'получаем идеинтификаторы писем sw.WriteLine("list") sw.Flush() otvet = sr.ReadLine() Debug.Print(otvet) myArr = otvet.Split(" ") ReDim MessageArr(totmessages - 1) For i = 0 To CInt(myArr(1)) - 1 MessageArr(i) = (sr.ReadLine()) Next 6.Теперь мы можем производить разные операции с письмами dele [x] Удаление сообщения номер x. Изменения вступают в силу только после корректного закрытия соединения. sw.WriteLine("dele x") 'х это идеинтификатор письма sw.Flush() otvet = sr.ReadLine() Возможные ответы: +OK [какойто текст] - письмо удалено -ERR [какойто текст] - нет письма с таким идеинтификатором retr [x] Приём сообщения номер x. Оно оканчивается переходом на новую строку и знаком "." 'получаем письма Dim x As Integer = 0 sr = New IO.StreamReader(ns, Encoding.Default, True) 'Encoding.Default вот чего не хватало для чтения руских букв For i = 0 To (totmessages - 1) sw.WriteLine("retr " & (i + 1)) sw.Flush() FileOpen(1, Application.StartupPath & "\mails\Mail" & MessageArr(i) & ".txt", OpenMode.Append, OpenAccess.Write) Do While otvet <> "." otvet = sr.ReadLine Debug.Print(otvet) Print(1, otvet & vbNewLine) Loop FileClose(1) Next i Возможные ответы: +OK [какойто текст] - вот ваше письмо -ERR [какойто текст] - нет такого письма Примеры: +OK 120 octets [заголовок письма] [текст письма] . Дополнительные POP3 команды Следующие дополнительные команды дают вам большую свободу при работе с сообщениями: Команда: TOP [сообщение] [n] Аргументы: [сообщение] - номер сообщения [n] - положительное число (обязательный аргумент) Описание: Если ответ сервера положительный, то после него он передаёт заголовки сообщения и указанное кол - во строк из тела сообщения. Возможные ответы: +OK top of message follows -ERR no such message Примеры: C: TOP 1 10 S: +OK S: <здесь POP3 сервер передаёт заголовки первого сообщения и первые 10-ть строк из тела сообщения.> S: . ... C: TOP 100 3 S: -ERR no such message Команда: UIDL [сообщение] Аргументы: [сообщение] - номер сообщения (необязательный аргумент). Описание: Если был указан номер сообщения, то сервер выдаёт уникальный идентификатор для этого сообщения. Если аргумент не был передан, то идентификаторы перечисляются для всех сообщений, кроме помеченных для удаления. Возможные ответы: +OK unique-id listing follows -ERR no such message Примеры: C: UIDL S: +OK S: 1 whqtswO00WBw418f9t5JxYwZ S: 2 QhdPYR:00WBw1Ph7x7 S: . ... C: UIDL 2 S: +OK 2 QhdPYR:00WBw1Ph7x7 ... C: UIDL 3 S: -ERR no such message, only 2 messages in maildrop Команда:loop Эта команда просто говорит серверу, что мы ещё висим на порту, чтобы он не закрывал соединение после длительной паузы. Команда:quit Закрытие соединения. Эта тема была разделена из темы "Наполнение и развитие FAQ" Прикреплённый файлbasPOP3.rar (1.15 Кбайт, скачиваний: 656) |
Сообщ.
#2
,
|
|
|
Цитата Pit-Bul @ 3.Далее посылаем серверу пароль pass [****] & chr(13) & chr(10) Вместо **** указывается пароль. На что сервер нам опять ответит следующим: +OK [какойто текст] - пароль верный, продолжайте -ERR [какойто текст] - ошибка, либо неверный пароль Вот код который это делает: 'отправляем пароль sw.WriteLine("Pass " & pass & Chr(13) & Chr(10)) sw.Flush() otvet = sr.ReadLine If otvet.Substring(0, 4) = "-ER" Then _ MessageBox.Show("Неверный пароль", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error,_ MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly, False) Сегодьня такой способ проверки пароля на сервере pop.mail.ru не работает. Выдаёт ошибку, что пароль неверный, а в переменной "otvet" текст такой: -ERR Unknown command:"". Жаль. |
Сообщ.
#3
,
|
|
|
zipa455, возможно сервер использует какой либо шифрованный метод аутеинтификации
|
Сообщ.
#4
,
|
|
|
If otvet.Substring(0, 4) = "-ER" В любом случае вернёт false. Независимо от того что будет в переменной otvet. Правильно будет либо так: If otvet.Substring(0, 3) = "-ER" либо так: If otvet.Substring(0, 4) = "-ERR" Кстати такой код отлично работает. Проверяно только что. private void button2_Click(object sender, EventArgs e) { NetworkStream ns; StreamReader rs; StreamWriter ws; String response; String userName = "user@mail.ru"; String pass = "password"; TcpClient client = new TcpClient(); try { client.Connect("pop.mail.ru", (Int32)110); } catch (Exception ex) { MessageBox.Show("Соединение не установлено! \n" + ex.Message, "Ошибка соединения!", MessageBoxButtons.OK, MessageBoxIcon.Error); } ns = client.GetStream(); rs = new StreamReader(ns); ws = new StreamWriter(ns); response = rs.ReadLine(); ws.WriteLine("User " + userName); ws.Flush(); response = rs.ReadLine(); if (response.Substring(0, 3) == "-ER") { MessageBox.Show("Неверный логин", "Ошибка аутентификации", MessageBoxButtons.OK, MessageBoxIcon.Error); client.Close(); return; } ws.WriteLine("Pass " + pass); ws.Flush(); response = rs.ReadLine(); if (response.Substring(0, 3) == "-ER") { MessageBox.Show("Неверный пароль", "Ошибка аутентификации", MessageBoxButtons.OK, MessageBoxIcon.Error); client.Close(); return; } MessageBox.Show("Соединение установлено!"); client.Close(); } |
Сообщ.
#5
,
|
|
|
Ребята, вот такой вопрос: Как автоматически определить настройки почтового сервера?
Пример: в Outlook вводим только логин, пароль, почтовый адрес и все. А Outlook сам автоматом определяет pop3.domain и порт. Определяет даже не стандартные порты и необходимость использования SSL. |
Сообщ.
#6
,
|
|
|
коллеги с pop.gmail.com и порт=995 не работает, никто с gmail не сделал?
|