Форум » GUI » получение почты из Harbour-программы » Ответить

получение почты из Harbour-программы

gustow: Нет ли у кого опыта получения почты с аттачами из Harbour-программы? DeleteEmail и CheckMailBox в SAMPLES смотрел, на старте помогло, но... в там используемом классе "Socket" (как понял, во всяком случае) плохо с работой с аттачами... а мне-то как раз с ними работать и надо. Решил пользовать классы из библиотеки TIP.LIB (ранее HBTIP вроде бы она была), т.е. tURL, TIpClientPop... но с документацией по ним беда (т.е. фактически нету). Вот и разбираюсь постепенно (а поразобравшись - опубликую "накопленный опыт" или как наглядный пример, или как нормальное описание, или как то и другое)... Стоит такая задача автоматизации (как раз в разрезе "свиняче-гриппозной" эпидемии) (и слепить надо довольно срочно, аж к понедельнику-вторнику, т.е. к 16-17.11.09 - собственно, все остальное ясно как делать, кроме "грамотной" работы с почтовым сервером): 1) наши больницы (Свердловская область 300-400 шт.) будут слать нам (на определенный и им известный адрес) КАЖДЫЙ день по письму, к которому приаттачено 4 XLS-ки (к примеру, для больницы с кодом "015" это будут "a015.xls", "b015.xls", "c015.xls", "d015.xls") с данными, сколько и какого народу заболело-лечится-померло и пр. 2) отчетный период - с 11:00 до 11:00 (т.е. после 11:00 забираем все, что накопилось в ящике "Входящие" на мэйл-сервере - и пусть кидают снова; а мы тем временем - уже другой прогой, это не моя забота - суммируем все по области и высылаем сводку в Минздрав). 3) моей проге надо: а) законнектиться (умею); б) залогиниться (умею); в) получить кол-во писем в ящике (умею); ... вот дальше пока не получается ... г) прочитать первое из новых писем (кстати, как определить "новизну" письма?); д) если есть аттачи - и именно четыре нужных экселки - сохранить их в определенную папку; е) если есть еще новые письма - перейти к следующему письму; ж) если нет - отлогиниться, закрыть сессию и выйти (умею). Небольшой пример, что уже получается: [more] [pre2]компилируется как: call c:\MiniGUI\Batch\Compile.bat GrippMail /l tip --------- дальше собственно код -------- local oMail, cUrl, oUrl, oClient, txt cUrl := "pop://gripptest:gripptest@26.188.255.166" if empty( alltrim( cUrl ) ) MsgInfo( "Invalid (empty) URL: " + cUrl ) Return Nil endif oUrl := tURL():New( cUrl ) if empty( oUrl ) MsgInfo("oUrl -- Invalid URL : [ " + cUrl + " ]") Return Nil else MsgInfo("oUrl created!") endif oClient := TIpClientPop():new( oUrl ) if empty( oClient ) MsgInfo("oClient -- Invalid URL : [ " + cUrl + " ]") Return Nil else MsgInfo("oClient created!") endif oClient:nConnTimeout := 2000 //:= 20000 oUrl:cUserid := strtran( oUrl:cUserid, "&at;", "@" ) if oClient:Open() if empty( oClient:cReply ) MsgInfo( "Connecting to " + oUrl:cProto + "://" + oUrl:cServer + CRLF + ; "Connection status: <connected>" ) else MsgInfo( "Connecting to " + oUrl:cProto + "://" + oUrl:cServer + CRLF + ; "Connection status: " + oClient:cReply ) endif txt := "oClient:isOpen = " + iif( oClient:isOpen, ".T.", ".F." ) MsgInfo( txt ) // в моем случае (пока) дает "-1" и "0" txt := "oClient:nLength = " + ltrim(str( oClient:nLength )) + CRLF + ; "oClient:nRead = " + ltrim(str( oClient:nRead )) MsgInfo( txt ) // в моем случае дает "+ОК " + (кол-во писем) + (кол-во октетов)(длина) txt := "oClient:Stat() = " + oClient:Stat() MsgInfo( txt ) // дает как строку (для всех писем через CRLF): // ("номер письма" "длина") (типа "1 32452" + CRLF ) txt := "oClient:List() = " + CRLF + oClient:List() MsgInfo( txt ) txt := "Количество писем в ящике ( oClient:countMail ): " + ; ltrim(str( oClient:countMail )) // почему-то дает на 1 больше MsgInfo( txt ) // запрашивает "unique ID" (без параметра - _всех_ писем) // возвращает строку (разделенную CRLF - если _всех_ писем) // (внутри подстроки - в виде // "1 MD50000000001:MSG:18386:30041174:1176554496" ) txt := "oClient:UIDL( ) = " + CRLF + oClient:UIDL( ) MsgInfo( txt ) // для одного письма возвращает только UIDL ( "MD5..." ) txt := "oClient:UIDL( 1 ) = " + CRLF + oClient:UIDL( 1 ) MsgInfo( txt ) // METHOD Read( nLen ) CLASS tIPClientPOP // ... // RETURN ::Retrieve( Val( ::oUrl:cFile ), nLen ) txt := 'valtype( oClient:Read( 1 ) ) = "' + valtype( oClient:Read( 1 ) ) + '"' MsgInfo( txt ) // пытаемся получить текст определенного письма (1-го) txt := "oClient:Read( oClient:UIDL( 1 ) ) = " + CRLF + ; "--- start --" + CRLF + ; oClient:Read( oClient:UIDL( 1 ) ) + CRLF + ; "--- finish ---" MsgInfo( txt ) // ? выдает то же, что и по List() // ? как прочитать конкретное письмо, имея его UIDL ?? /* // через Retrieve (2-е письмо, первые 100 байт) txt := "oClient:Retrieve( 2, 100 ) = " + CRLF + ; "--- start --" + CRLF + ; oClient:Retrieve( 2, 100 ) + CRLF + ; "--- finish ---" MsgInfo( txt ) // "Касперский Мэйл-Диспетчер" возбудился - // т.е. письмо действительно получили // но... полученное через Retrieve - пустая строка (??) видать, это объект */ /* // через Retrieve (2-е письмо, все целиком сколько ни есть) txt := "oClient:Retrieve( 2 ) = " + CRLF + ; "--- start --" + CRLF + ; oClient:Retrieve( 2 ) + CRLF + ; "--- finish ---" MsgInfo( txt ) // "Касперский Мэйл-Диспетчер" возбудился - // т.е. письмо действительно получили // но... полученное через Retrieve - пустая строка (??) видать, это объект */ // через Retrieve (2-е письмо, все целиком сколько ни есть) - смотрим тип txt := 'valtype( oClient:Retrieve( 2 ) ) = "' + ; valtype( oClient:Retrieve( 2 ) ) + '"' MsgInfo( txt ) // тип - "С" // ... тут эксперимент прервал, ибо жрать охота и домой пора // закрываем сессию (обязательно!) oClient:Quit() // см. HBTIP\POPCLI.PRG // а так - не вылетает! (все завершается чисто... вроде бы...) oClient:Close() MsgInfo( "Session closed." + CRLF + "Done: " + ; iif( empty( oClient:cReply ), ; "(no goodbye message)", ; 'goodbye message "' + oClient:cReply + '"' ) ) else if empty( oClient:cReply ) MsgInfo( "Can't open URI " + cUrl ) else MsgInfo( "Can't open URI " + cUrl + CRLF + ; 'oClient:Reply = "' + oClient:cReply + '"') endif endif MsgInfo( "That's all folks!" ) oMail := .F. cUrl := .F. oUrl := .F. oClient := .F. ---------- конец собственно кода -------------[/pre2][/more] Кто в данной тематике продвинут - подскажите, пожалуйста. И срочно! Пользую HMG Ext 1.7.75-76 Harbour 2.0.0beta3 (Rev.12849) Помогшему (помогшим) - антигриппозную маску в подарок! :)

Ответов - 70, стр: 1 2 3 4 All

Петр: gustow пишет: oClient:Read( oClient:UIDL( 1 ) ) Тут у вас что-то не то написано д) если есть аттачи - и именно четыре нужных экселки - сохранить их в определенную папку; Для работы с письмами предназначен класс TipMail - у него есть соответствующие методы

gustow: Петр, спасибо за отклик - а то что-то тишина была (видать, никто с этим не работал). Насчет oClient:Read( oClient:UIDL( 1 ) ) - хотел выяснить, что делает функция READ() (почему-то сперва посчитал, что так могу выяснить, читано ли уже письмо прежде... мне же надо определять, какие письма новые... только погодя понял, что не так это надо делать - на сервере ж не хранится какая-либо пометка, что письмо уже кем-то скачивалось с POP-сервера... или я неправ?). Про класс TipMail тоже уже знаю (теперь) - сейчас постепенно документирую библиотеку TIP (по исходникам с CVS) (для себя и кто заинтересуется из харбористов). А то про почту народ в основном интересуется "как отослать письмо из Харбор-программы?"... Это-то как раз в один плевок :) - Hb_SendMail () из этой же библиотеки... А вот с получением почты (да еще с "разгребанием" аттачей) - видать, мало кому интересно.

Петр: gustow пишет: на сервере ж не хранится какая-либо пометка, что письмо уже кем-то скачивалось с POP-сервера... или я неправ? Для POP/POP3 - это работа для почтового клиента, которую он может делать в разные способы, вплоть до удаления прочитанного сообщения с сервера. Наиболее распространенный способ - использование UIDL, клиент сохраняет UIDL в собственной базе и перед чтением письма смотрит, не читалось ли письмо с указанным идентификатором ранее. UIDL - в теории является уникальным идентификатором, но в целях упрощения алгоритма его часто получают посредством применения алгоритма хеширования (например MD5) к заголовку сообщения. Применение такой технологии может привести к тому, что два одинаковых сообщения могут получить одинаковый UIDL. Почтовый клиент должен уметь распознавать и устранять такие ситуации.


gustow: Понял - спасибо за разъяснения (не знал). Т.ч. как раз и буду делать то, что и собирался, для запоминания "есть ли что непрочитанное?": буду хранить для последнего обработанного письма UIDL, а также (для предотвращения "дубликатов" по MD5) дату и время, когда отправитель его послал, - т.е. "Date:" из RFC-822. И буду либо читать начиная со следующего после последнего обработанного (если буду сохранять письма на сервере - что вряд ли), либо (если такого в списке UIDL'ов для "всех писем" нет) все письма с сервера. Такой способ годится? (просто никогда еще с почтовыми серверами не работал программно) Поскольку уж начал разбираться с этой библиотекой, то решил хоть какой-то Help сделать (хотя бы то, что уже знаю) - авось и кому другому, кому надо будет такой функционал иметь, пригодится... Если интересно - положил пока одну страничку (но с достаточно полноценным примером: "как достучаться до ящика, получить кол-во писем, получить RFC-822 от конкретного письма, выудить из него содержимое от "Subject:" - т.е. "Тема:" - и показать") на HMGforum. http://hmgforum.com/viewtopic.php?f=5&t=977

gfilatov: gustow пишет: как достучаться до ящика, получить кол-во писем, получить RFC-822 от конкретного письма Попробовал добавить в Ваш пример использование класса TipMail, как предлагал Петр. Но при обработке письма получаю ошибку в функции HB_RegEx, которая вызывается из библиотеки tip. #include "minigui.ch" #define APP_TITLE "Hello World!" /* */ Function Main DEFINE WINDOW Win_1 ; AT 0,0 ; WIDTH 400 ; HEIGHT 400 ; TITLE APP_TITLE ; MAIN @ 10,10 BUTTONEX BTNOK ; CAPTION "Get Mails" ; ACTION Fun_1() ; WIDTH 100 HEIGHT 30 @ 45,10 BUTTONEX BTNCANCEL ; CAPTION "Cancel" ; ACTION ThisWindow.Release ; WIDTH 100 HEIGHT 30 END WINDOW CENTER WINDOW Win_1 ACTIVATE WINDOW Win_1 Return *------------- function Fun_1 () local cServer, cUser, cPass, cUrl, oUrl, oClient, nMsgs, ; cMail, oMail, cData, txt, i cServer := "pop.myhome.com" // your POP3-server (DNS-name or IP address) cUser := "testuser" // if your Email-adress is "testuser@myhome.com" cPass := "12345678" // password for your account on POP-server cUrl := "pop://" + cUser + ":" + cPass + "@" + cServer // or simple // cUrl := "pop://testuser:testpass@myhome.com" // ( look at \hbtip\tests\tiptest.prg ) if empty( alltrim( cUrl ) ) // error: empty URL Return Nil endif oUrl := tURL():New( cUrl ) if empty( oUrl ) // error: invalid URL Return Nil endif oClient := TIpClientPop():new( oUrl ) if empty( oClient ) // error: invalid URL Return Nil endif oClient:nConnTimeout := 10000 // connection timeout oUrl:cUserid := strtran( oUrl:cUserid, "&at;", "@" ) // user ID if oClient:Open() txt := "Connecting to " + oUrl:cProto + "://" + oUrl:cServer + CRLF + ; "Connection status: " if empty( oClient:cReply ) MsgInfo( txt + "<connected>" ) // MsgInfo() - function from MiniGUI else MsgInfo( txt + oClient:cReply ) endif nMsgs := oClient:countMail // oops!.. It returns greater on 1 value (for example: not 3 but 4) nMsgs -- // :) let's correct this mistake txt := iif( nMsgs > 0, ; "You have (total) " + ltrim(str(nMsgs)) + ; " message(s) into your mailbox.", ; "Sorry, no mail into your mailbox..." ) MsgInfo( txt ) if nMsgs > 0 /* getting Header (RFC-822) from 1st mail into mailbox cHeader := alltrim( oClient:Top( 1 ) ) // getting substring ( after "Subject:" to CHR(13)+CHR(10) ) i := at( "Subject:", cHeader ) cSubject := substr( cHeader, i+8 ) // len("Subject:") = 8 i := at( chr(13)+chr(10), cSubject ) cSubject := substr( cSubject, 1, i ) if len( cSubject ) > 1 cSubject := alltrim( substr( cSubject, 1, len(cSubject)-1 ) ) else cSubject := "" endif MsgInfo( '"Subject" of 1st mail: [ ' + cSubject + ' ]' ) */ // MsgInfo( oClient:UIDL( 1 ), "UIDL" ) oClient:reset() cMail := oClient:retrieve( 1 ) msginfo( cMail ) oMail := TipMail():New() IF oMail:FromString( cMail ) == 0 MsgInfo( "Malformed mail. Dumping up to where parsed" ) ENDIF //msginfo( oMail:isMultiPart() ) //msginfo( oMail:countAttachments(), "count" ) WITH OBJECT oMail // "-------------============== HEADERS =================--------------" FOR i := 1 TO Len( :hHeaders ) MsgInfo( str(hb_HKeyAt( :hHeaders, i ))+ ":"+ hb_HValueAt( :hHeaders, i ) ) NEXT // "-------------============== RECEIVED =================--------------" FOR EACH cData IN :aReceived MsgInfo( cData, "Received" ) NEXT // "-------------============== BODY =================--------------" IF !Empty( cMail ) MsgInfo( :GetBody(), "Body" ) ENDIF i := 1 DO WHILE :GetAttachment() != NIL // "-------------============== ATTACHMENT =================--------------" MsgInfo( :NextAttachment():GetBody(), "Attachment"+str(i) ) i++ ENDDO END endif oClient:Quit() // look at HBTIP\POPCLI.PRG // no run-time error! // but _without_ this ( with oClient:Close() only ) I had it... oClient:Close() MsgInfo( "Session closed." + CRLF + "Done: " + ; iif( empty( oClient:cReply ), ; "(no goodbye message)", ; 'goodbye message "' + oClient:cReply + '"' ) ) else if empty( oClient:cReply ) MsgInfo( "Can't open URI " + cUrl ) else MsgInfo( "Can't open URI " + cUrl + CRLF + ; 'oClient:Reply = "' + oClient:cReply + '"') endif endif MsgInfo( "That's all folks!" ) cUrl := Nil oUrl := Nil oClient := Nil Return Nil gustow, Может, Вам повезет больше...

gustow: Спасибо за тест, Григорий! Завтра покопаюсь (я до конкретной работы с письмом - т.е. уже загрузив его через Retrieve - пока не добирался: надо было сперва "гаммы разучить" :) ). А в остальном - все в примере достаточно грамотно? Или есть "ляпы"? И вообще - хэлп такой полезен будет на Ваш взгляд? (как писал тут не так давно кто-то - "всякая информация полезна" :) ) P.S. На comp.lang.xharbour отозвался Rafael Luiz - сказал, что может подмочь... но призвал перейти на xHarbour+hwgui. "sure i can help, but you need to use xharbour (where is the real tip library) and also use hwgui as gui library, which is much more stable and easy to use then hmg." Пока не знаю, поддаваться ли на "провокацию" :) - но, глядишь, чем-то и поможет (доками по библиотеке, примерами и пр.)

gfilatov: gustow пишет: А в остальном - все в примере достаточно грамотно? Да, иначе не достучался бы до pop-сервера gustow пишет: Rafael Luiz - сказал, что может подмочь... но призвал перейти на xHarbour+hwgui Ну, это - его стандартное предложение... Minigui ему абсолютно не нравится, поскольку не использует ООП gustow пишет: не знаю, поддаваться ли на "провокацию" Поддайтесь - хуже не будет

Andrey: gustow пишет: видать, мало кому интересно. Интересно в любом случае... Просто не всегда сразу начинаешь пробовать.... Спасибо за пример и хелп к нему ...

gustow: Andrey , дык завсегда пожалуйста (мои "два цента" в общий "лимон" :) ). Надеюсь, постепенно разберусь (сам - да и "с маленькой помощью друзей"), Help&Manual сляпается - и всем будет щазззтье! :) от расширения функционала. Григорий , понял, где и почему рушится (у меня тоже - на HMG Ext 1.7.75-76 Harbour 2.0.0beta3 (Rev.12849) ). У вас там небольшая ошибочка в коде: [pre2]WITH OBJECT oMail // "-------------============== HEADERS =================--------------" FOR i := 1 TO Len( :hHeaders ) MsgInfo( str(hb_HKeyAt( :hHeaders, i ))+ ":"+ hb_HValueAt( :hHeaders, i ) ) NEXT[/pre2] Не рушится, если писать hb_HKeyAt без str( ... ) (и вынеся его в заголовок MsgInfo-окна) - т.е. так: [pre2]WITH OBJECT oMail // "-------------============== HEADERS =================--------------" FOR i := 1 TO Len( :hHeaders ) MsgInfo( hb_HValueAt( :hHeaders, i ), hb_HKeyAt( :hHeaders, i ) + ":" ) NEXT[/pre2] И теперь еще "глупый" вопрос (что-то никак не пойму): ну хорошо, аттачи в письме есть (oMail:countAttachments() # 0), могу любой из них получить - как в Вашем добавлении: [pre2] DO WHILE :GetAttachment() != NIL MsgInfo( :NextAttachment():GetBody(), "Attachment"+str(i) ) ENDDO[/pre2] ...а как мне получить список имен файлов в аттачах? (или где посмотреть? в массиве oMail:aAttachments ?) - чтобы можно было анализировать "то пришло, что надо, или не то?", а затем к тому, что надо, применять метод Detach(), задавая путь для "сохранения файла в..."

gfilatov: gustow пишет: как мне получить список имен файлов в аттачах? Для этого есть METHOD getFileName(), который вызывается внутри detachFile( cPath )

gustow: Григорий, я вроде как нашел баг в TIP.LIB, в модуле MAIN.PRG Порождает runtime error вида [pre2] Error BASE/1108 Argument error: HB_AT</p><BR> Called from HB_AT(0) Called from TIPMAIL:FROMSTRING(391) [/pre2] при разборе писем (как я вроде бы понял - только когда письмо с аттачами). Чтобы не повторяться, гляньте мой пост на HMGforum http://hmgforum.com/viewtopic.php?f=20&t=979 Можете это поправить в своем варианте TIP.LIB (или Вы ее не пересобираете для HMG Ext.?) - или сообщать в Harbour Bugreport (т.е. Luiz'у)? Для примера (пример сегодня прислал Luiz): [pre2] oPop := TipClientPOP():New( oUrl1, lTrace ) ... // First lets read all messages from server ( i+m not deleting then //from the pop3 server as i got then) cTmp := oPop:List() oPop:Reset() MsgInfo( cTmp, "oPop:List()" ) if !empty( cTmp ) cTmp := strtran( cTmp, chr(13)+chr(10), "|") aTemp := Hb_atokens( cTmp, "|") for each cTemp in aTemp oPop:Reset() aItem := Hb_atokens( cTemp, ' ') cTmp := oPop:Retrieve( val( aItem[1] ), val( aItem[2] ) ) oMail := TipMail():New() oMail:FromString( cTmp ) aadd( aData, oMail ) next endif oPop:Close() [/pre2]вот в [pre2]oMail:FromString( cTmp )[/pre2] и вылетает.

gfilatov: gustow пишет: я вроде как нашел баг в TIP.LIB Текст в модуле MAIL.PRG Харбора повторяет тот же текст из этого модуля xHarbourа Могу сказать одно: в хХарборе прием почты с вложением(ями) работает корректно После небольших танцев с бубнами удалось корректно сохранить архив из письма, используя xHarbour Кстати, в xHarbour отсутствуют и две замеченные Вами проблемы: - nMsgs := oClient:countMail возвращает корректное число писем - oClient:Quit() абсолютно не требуется И, последнее, я выложил на английском форуме МиниГуи рабочую сборку библиотеки для xHarbour, которая включает xHarbour Compiler build 1.2.1 (SimpLex) (Rev. 6633)

gustow: Спасибо, Григорий, буду разбираться. О результатах (хотелось бы все же - по возможности - не слезать с иглы HMG Ext. :) а то уж втянулся :) ) сообщу.

Петр: gfilatov пишет: oClient:Quit() абсолютно не требуется Что вы имеете ввиду?

gfilatov: Петр пишет: gfilatov пишет: oClient:Quit() абсолютно не требуется Что вы имеете ввиду? В примере для Харбора Алексей написал ... oClient:Quit() // look at HBTIP\POPCLI.PRG // no run-time error! // but _without_ this ( with oClient:Close() only ) I had it... oClient:Close() ... Для хХарбора в аналогичном примере вызов oClient:Quit() не требуется

gustow: Извините, Григорий, но что-то я "устал мозгами"... :) Скачал xHarbour (последнюю инсталляшку с free.xharbour.com - от 5 ноября), установил (по умолчанию - в c:\xHarbour). А он, "зараза" (точнее, его xBuild и прочее), не работает под 98-й (под XP-то опробовал - все идет) - ругается на "Файл XBUILDW.EXE связан с отсутствующим компонентом KERNEL32.DLL:GetUserDefaultUILanguage..." и т.п. Попробовать-то можно - а работать и отлаживать программку (в конторе) надо под 98-й (из неких "политических" соображений). Но библиотеки-то xHarbour'овские и все его остальное - на месте... Как мне его подвязать (миниГУИвские компоненты не нужны - делаю просто консоль), чтобы скомпилировать .PRG-шку в EXE? (т.е. нечто вроде COMPILE.BAT в MINIGUI-вских примерах) Извините, если путано... видать, погода плохая :) Надеюсь, поняли, что хочу.

Петр: Вот этим COMPILE.BAT и пользуйтесь, просто укажите в строке 129 if "%MG_XHRB%"=="" set MG_XHRB=c:\xharbour правильный путь к xHb и компилируйте программу compile /X /C Вы что реально решились менять компилятор и из-за чего? P.S. строка 129 находится в \MiniGUI\BATCH\Compile.Bat

gustow: Спасибо, Петр, за подсказку! Просто действительно "тупой" какой-то сегодня :) Петр пишет: Вы что реально решились менять компилятор и из-за чего? Задачу описывал в начале ветки. Получается такая ерунда (к примеру): Компилирую так: [pre2]call c:\MiniGUI\batch\compile.bat test2 /c /l tip /l xhb[/pre2] [pre2]/* from xHarbour Language Reference Guide (bundled with xHarbour) Class Reference -> TIpClientPop GAL - only reformatting and commenting */ // The example outlines the steps required for retrieving all // eMails from a POP mail server and how to decompose // incoming mail messages. ////#include "minigui.ch" // GAL /// GAL (from "\MiniGUI\Harbour\doc\xhb-diff.txt") #ifndef __XHARBOUR__ #include "xhb.ch" // add xHarbour emulation to Harbour #endif PROCEDURE Main LOCAL oPop, oPart, aParts, oTIpMail, aEmails, i // GAL Local cTmp, aTemp, nMsgs, aItem cSaveFolder := CurDrive() + ":\" + CurDir() + "\tmp\" // куда сохранять set color to "w/b, n/w" cls //oPop := TIpClientPop():new( "pop://mailaccount:password@pop.server.com" ) oPop := TIpClientPop():new( "pop://gtest:gtest@26.188.212.164" ) IF .NOT. oPop:open() ? "Connection error:", oPop:lastErrorMessage() clear type inkey(0) QUIT ELSE //// GAL ? "Connection OK" cTmp := oPop:List() if ! empty( cTmp ) cTmp := strtran( cTmp, chr(13)+chr(10), "|") aTemp := Hb_atokens( cTmp, "|") if empty( atail( aTemp ) ) // List() returns value greater on 1 aTemp := asize( aTemp, len( aTemp ) - 1 ) endif nMsgs := len( aTemp ) ? "nMsgs = " + str( nMsgs ) else ? "No mails" endif ? "oPop:countMail() = " + str( oPop:countMail() ) // return as "List()" // (greater on 1) //// //aEMails := oPop:retrieveAll() GAL commented //// GAL aEmails := array( nMsgs ) for i:=1 to nMsgs aItem := Hb_atokens( aTemp[ i ], ' ') oPop:Reset() //cTmp := oPop:Retrieve( val( aItem[1] ), val( aItem[2] ) ) cTmp := oPop:Retrieve( val( aItem[1] ) ) // as in POPCLN.PRG - "RetrieveAll()" (without 2nd) aEmails[ i ] := TIpMail():new() aEmails[ i ]:FromString( cTmp ) /* тут вылетает Called from HB_REGEX(0) Called from TIPMAIL:GETFIELDOPTION(195) in .\mail.prg Called from TIPMAIL:FROMSTRING(432) in .\mail.prg Called from MAIN(70) in test2.prg --- см. в Roberto'вской (! там правильно по NN строк) HBTIP TIPMAIL:GETFIELDOPTION(195) aMatch := HB_Regex( ";\s*" + cOption +"\s*=\s*([^;]*)", cEnc, .F. ) TIPMAIL:FROMSTRING(432) // se if we have subparts: 431 IF At( "multipart/", Lower( ::GetFieldPart( "Content-Type" ) ) ) > 0 432 cSubBoundary := ::GetFieldOption( "Content-Type", "Boundary" ) */ next i //// oPop:close() clear type inkey(0) //QUIT // GAL досюда доходит нормально // (если не "разбирать" письма через :FromString(), а просто надо список) ENDIF [/pre2] И, к примеру, когда компилирую под Харбором (HMG Ext 1.7.76), :countMail() возвращает кол-во писем, большее "истинного" на 1 (т.е. в ящике 3 письма, а возвращает 4)... Ну это-то ладно - поправлю легко (хотя результат от :List() совместно с :countMail() используются в :RetrieveAll() - "получить ВСЕ письма", и тогда при получении якобы "последнего" письма вылетит по ошибке). Хуже-то, что когда начинаю "разбирать письмо" (создавать TipMail-объект и заполнять его из строки через :FromString() ) - в Harbour'е вылетает... У Григория получался тот же вылет ( http://clipper.borda.ru/?1-1-0-00000205-000-0-0#003.001 ). Чуть позже Григорий посоветовал: "в xHarbour'e эти классы и их методы отрабатывают корректно"... вот и хочу попробовать (мне, в общем-то и надо "просто консоль", без минигуивских наворотов).

gfilatov: gustow пишет: У Григория получался тот же вылет Да, подтверждаю gustow пишет: в xHarbour'e эти классы и их методы отрабатывают корректно Да, подтверждаю gustow пишет: вот и хочу попробовать Ждем отчета о результатах...

gustow: Как писано в "Евгении Онегине": "Еще страшней! Еще чуднее!..." :) скомпилировал как [pre2]call c:\MiniGUI\batch\compile.bat test2 /x /c /l tip[/pre2] Экран (фон DOS-окна) черный (должен быть "белое на синем"), "? ..." не отображаются, на INKEY(0) не реагирует, почта не забирается ("Касперский Почтовый Антивирус" не вылезает - а при Harbour'е "вылезал" на :Retrieve() ). Реагирует только на Ctrl/C (закрывая окно) - и то хотя бы... :) Что делаю не так? (или не доделываю) P.S. Никаких добавок, SETов в AUTOEXEC'ах и др. подобного против установок, что были при "нормальной" работе с Harbour+MiniGUI, не вписывал - "просто добавил воды" :) (т.е. поставил xHarbour в c:\xHarbour).

gfilatov: gustow пишет: Что делаю не так? Алексей! Создайте все же графическое окошко, и уже из него вызывайте доставку/проверку почты. У меня такое впечатление, что с помощью compile.bat Вы не получите консольное приложение под xHarbour Что-нибудь типа... #include "minigui.ch" #define APP_TITLE "Hello World!" /* */ Function Main DEFINE WINDOW Win_1 ; AT 0,0 ; WIDTH 400 ; HEIGHT 400 ; TITLE APP_TITLE ; MAIN @ 10,10 BUTTONEX BTNOK ; CAPTION "Get Mails" ; ACTION Fun_1() ; WIDTH 100 HEIGHT 30 @ 45,10 BUTTONEX BTNCANCEL ; CAPTION "Cancel" ; ACTION ThisWindow.Release ; WIDTH 100 HEIGHT 30 END WINDOW CENTER WINDOW Win_1 ACTIVATE WINDOW Win_1 Return

Pasha: Наверное, не подключается консольный терминал В начале программы надо указать: REQUEST HB_GT_WIN REQUEST HB_GT_WIN_DEFAULT и проследить, чтобы прилинковывалась gtwin.lib И еще, если не устраивает библиотека hbtip из Harbour, необязательно переходить на xHarbour Можно создать гибрид, скрестив ужа с ежом, т.е. попробовать собрать tip из xharbour компилятором harbour. Может и получится

gfilatov: Pasha пишет: В начале программы надо указать: REQUEST HB_GT_WIN REQUEST HB_GT_WIN_DEFAULT Спасибо! Да, это решает проблему компиляции консольного приложения под xHarbour с помощью compile.bat

gustow: Отвечаю не по очереди, извините (по мере "тырканья и пробования" :) ). Pasha, прилинковал ( в компилирующую строку добавил "/l gtwin") и вписал REQUEST'ы. Помогло! Экран синенький, "? ..." отображаются, на INKEY(0) реагирует. И - самое главное - ВСЁ ОТРАБОТАЛО КАК НАДО ! Разгребло мэйлы, оставило в стороне те, которые без аттачей, а аттачи скинуло в указанную папочку (в CurDrive() + ":\" + CurDir() + "\tmp\" ). А дальше уж "бизнес-логику" (куда перекидывать из "времянки", да надо ли [то ли, что надо, прислали?], да если дубли по именами [такой файл в "целевой" папке уже есть]...) - это уж, можно сказать, легко "как два пальца" распишу!.. Это уж ерунда! Главное как раз в этом-то и было. (Кстати, тут :countMail() действительно правильно отрабатывает - возвращает "единственно верное" значение 3.) Т.ч., Григорий, возьмите на заметку (авось, и другим пригодится) - вполне нормально получается консольное приложение и под xHarbour'ом! Причем с помощью вполне обычного, "родного минигуёвского" Compile.bat. СПАСИБО, РЕБЯТА! P.S. Примерчик оформлю завтра - запостю сюда, не возражаете? (да и в качестве сэмпла в "пакет" HMG Ext., думаю, пригодится - но этот вариант сделаю чуть попозже, чтоб красиво, "по правилам" всё оформить). P.P.S. Куда антигриппозные маски высылать? :) :) :)

Петр: Все же вернемся к TIPClientPOP К сожалению, он плохо спроектирован (в обеих своих вариантах) и его просто надо довести до ума. Вот к примеру метод quit , Григорий - это не деструктор, а обычный метод который отправляет команду QUIT POP3 серверу со всеми вытекающими из этого последствиями. Его использование в Harbour совсем не обязательно, этот пример будет работать корректно oPopCli := IPClientPOP():New( "pop://user:pass@pop3.mail.ru") IF !oPopCli:Open(); RETURN; ENDIF ? Left( oPopCli:List(), 10 ) //oPopCli:Stat() //oPopCli:Quit() oPopCli:Close() если добавите перед :Close() вызов :Quit() - тоже будет все работать нормально. Но! Если посмотреть реализацию метода Close, то увидим, что внутри этого метода ::Quit тоже вызывается ;( А это уже вяжет программисту руки - команда QUIT переводит POP сервер из состояния TRANSACTION в состояние UPDATE. А значит все ошибочные изменения, допустим при использовании метода Delete, вступят в силу. Значит нужно изворачиваться и вместо :Close() использовать напрямую hb_inetClose( oPopCli:SocketCon ) или переопределять свой метод. Далее - обратите внимание, что возвращает ? Left( oPopCli:List(), 10 ) и вы поймете почему counMail() не может не возвращать то, что возвращает. Сама реализация counMail() через команду LIST, а не STAT тоже вызывает, по меньшей мере, недоумение.

gustow: Спасибо, Петр, что обратили внимание на "кривизны" (или мне спасибо, что "поднял шум" вокруг этого функционала? :) ). Ну уж в "доводке" я (пока, надеюсь) спецам не помощник - надеюсь, кто-нибудь из более грамотных "довылижет"... И всем будет еще лучше! :) (часа 3 спустя) И уж заодно - очередной "тупой" вопрос (просто не надо было такое раньше знать): 1) получаю список имеющихся писем; 2) выделяю из него "новые" (если есть); 3) иду по циклу "новых" (сперва беру от письма только :Top() - не все письмо); 4) если нет вложений - отвечаю посылателю (адрес знаю из :Top() ): мол, "ай-яй-яй" - и на п.3; 5) если есть вложения - иду в функцию (параметром передаю № письма из списка - nMail ); 6) там гружу уже письмо целиком - через :Retrieve( nMail ) и :FromString( cTmp ) ( cTmp - Local в функции ); 7) разбирая его ( oMail - тоже Local ), смотрю кол-во вложений; 8) если меньше пяти (надо иметь теперь 5 .XLS'ок) - соотв. "ай-яй-яй" и на п.3; 9) если есть среди вложений то, что надо - сохраняю вложения, посылаю "отлично!" и на п.3; Так вот вопрос: коли и письмо, полученное в строку, и сформированный из строки oMail, и пр. будут в функции локальными - не будет ли накапливаться "мусор" в памяти (при большом кол-ве писем, обрабатываемых "за сеанс")? Надо ли принудительно "чистить" локальные перед выходом из функции (присваивая Nil), или память, отведенная под них, будет освобождаться "автоматом" при RETURN ? А то приложение должно крутиться в автоматическом режиме на сервере - и, естественно, желательно обойти подобные "подводные камни". Просто как-то не просвещался ранее в подобном...

Петр: Я так понял вы будете использовать xHb - значит смотрите описание функций hb_gc*() (у вас к xBuild еще reference guide в придачу). В принципе GC (сборщик мусора) в xHb и Harbour отличаются и в последнее время очень. Я, чтобы потом не заморачиваться, при компиляции Harbour использую макро HB_GC_AUTO (читайте в Harbour ChangeLog, что это за зверь и зачем он нужен). regustow пишет: Надо ли принудительно "чистить" локальные перед выходом из функции (присваивая Nil), или память, отведенная под них, будет освобождаться "автоматом" при RETURN Не надо или не обязательно, в общем как вам нравится. Сокеты не забывайте закрывать, файлы. В общем все как всегда, только аккуратненько так.. Да, TRY/CATCH, BEGIN SEQUENCE/END SEQUENCE - ваши надежные друзья-товарищи; переработанный errorsys в случае краха всегда должен быть готов отправить вам мыло или SMS; при возможности приставьте к вашей программе программу-сторожа, которая проверяла бы - жив ли процесс и в случае необходимости запускала бы его автоматически; помните, что ваша программа может управляться при помощи получаемых сообщений и т.д.

gustow: Петр, советы понял и принял :) Приложение будет запускаться на сервере (там же - на сервере - будет лежать и сама EXEшка, и "выгребенные" ею вложения из писем) Шедулером каждый час (или 2 - в общем, как у нас решат), "разгребать" и завершаться. Главное - чтобы если подвалит (вдруг) достаточно большое количество писем (в очередной "сеанс"), то чтобы в процессе "разгребания" не случилось ситуации "а у меня памяти больше нету :) ..." (надеюсь, что такого не случится - постараюсь "тщательнЕе" расписать).

Петр: Сбросил на SVN изменения в класс TIPClientPOP Основные изменения: - полностью переписанный метод countMail() возвращает правильный результат, использует меньше памяти, создает меньше сетевого трафика, работает быстрее; - добавлен метод Rset(). Если какие-то сообщения были помечены для удаления с помощью метода Delete(), то с них снимается метка удаления. Всегда нужно помнить, что метод countMail() не учитывает сообщения, отмеченные для удаления (как и List()) - добавлен метод OpenDigest() - данный метод для авторизации на сервере использует команду APOP. В отличии от Open() (команды USER/PASS) где и имя и пароль пользователя отсылаются "как есть" в виде строки, OpenDigest() передает на pop3 сервер пароль пользователя зашифрованным в виде MD5 хеш-строки, что само по себе несколько увеличивает безопасность Пример здесь [pre2]PROCEDURE main() LOCAL oPop, nCount, lAutoQuit := .t. LOCAL cLogin := "Using APOP" oPopCli := TipClientPOP():New( "pop://user:pass@127.0.0.1", .f. ) oPopCli:nConnTimeout := 12500 IF ! oPopCli:OpenDigest() oPopCli:Quit() cLogin := "Using USER/PASS" IF ! oPopCli:Open() RETURN ENDIF ENDIF QOut( cLogin ) nCount := oPopCli:countMail() IF nCount > 1 QOut( "Before DELE ", nCount ) oPopCli:Delete( 1 ) QOut( "After DELE ", oPopCli:countMail() ) oPopCli:Rset() QOut( "After RSET ", oPopCli:countMail() ) ENDIF oPopCli:Close( lAutoQuit )[/pre2] Тестировал на локальном почтовом сервере и с помощью сервиса mail.ru

gustow: Спасибо, Петр! Сам я пересобирать библиотеку для Harbour (текущего, что идет с HMG Ext.) не буду (пока) - пусть уж появится в "нормальном" виде (в очередной сборке Григория), тогда уж и перестану "изменять с xHarbour'ом" :) . А как насчет "вылетов" по FromString() (в Harbour - есть, в xHarbour - нет)? Удалось (удастся) побороть? Не понукаю - просто вспомнил, что еще и это... А, наверное, есть и еще не обнаруженные (мною или кем-то) "глюки" в реализации для Harbour. За метод шифрованной авторизации - отдельное спасибо! (думаю, многим понравится не "светиться" с паролями в открытом виде в трафике) Да и остальные добавления и изменения весьма полезны. По моей работе - практически всё (под xHarbour в консоли) работает уже как надо (допричесываю "бизнес-логику": разбор самих вложений, что делать с "повторными" письмами и пр. - но это уже "фантики" :) ).

Петр: gustow пишет: А, наверное, есть и еще не обнаруженные (мною или кем-то) "глюки" в реализации для Harbour. Есть, конечно. По крайней мере я еще 2 нашел, но относятся они в равной мере к обеим реализациям. А как насчет "вылетов" по FromString() (в Harbour - есть, в xHarbour - нет)? Просто многие забывают, а некоторые, думаю, и не знают различий в реализации hb_aTokens в Harbour и xHb Для начала попробуйте угадать, что выведет на консоль эта программа в Harbour/xHb [pre2]PROCEDURE main LOCAL aTokens := hb_aTokens( "1|2|3|", "|") QOut( Len( aTokens ) ) RETURN [/pre2] Я думаю дальше все становится очевидным..

Петр: ну и еще один пример для закрепления материала [pre2]PROCEDURE main LOCAL aTokens := hb_aTokens( "1|2|3|", "|2") QOut( Len( aTokens ) ) RETURN[/pre2]

gustow: На 1-й пример гордо :) и сходу отвечаю: в Harbour = 4, в xHb = 3 ( тот же countMail() - где поначалу сходу и "обмишурился"). Во 2-м: у xHb = 2, у Hb = тоже 2. Мдааа... Не думал, что так все "запущено" :) :( В общем, понятно, что для Harbour, скорее всего, изрядно "перелопачивать" реализацию придется...

Петр: gustow пишет: Во 2-м: у xHb = 2, у Hb = тоже 2. в xHb - 3 поскольку hb_aTokens в качестве 2-го параметра принимает только строку состоящую из одного символа или правильнее сказать использует в качестве разделителя первый символ передаваемой строки. Для того чтобы получить результаты как в Harbour, нужно использовать функцию hb_aTokens2 (упоминания о ней не найдете ни changelog, ни в xHarbour Guide Reference ). В общем, понятно, что для Harbour, скорее всего, изрядно "перелопачивать" реализацию придется... Не думаю, всего лишь нужно учитывать особенность реализации одной функции и не более. К слову сказать, я считаю результат возвращаемый Harbour более корректным и не я один, наверное, раз в xHb появилась hb_aTokens2

gustow: Петр пишет: в xHb - 3 А, да, конечно - просто автоматом шлепнул 2. Чем дальше в лес... :)

gustow: Еще "помощь зала" понадобилась :) В полях заголовка письма и в именах файлов аттачей встречаются строки в KOI8-R (бог с ней, с UTF8 - хоть бы с этим разобраться!)... Что-то не соображу, как перекодировать, например, такую строку из поля заголовка письма "From" (адрес отправителя - "От") [pre2]=?koi8-r?Q?=E1=CC=C5=CB=D3=C5=CA_=E7=D5=D3=D4=CF=D7?= <gustow336@pochtamt.ru>[/pre2], чтобы в результате (в RU1251) иметь [pre2]Алексей Густов <gustow336@pochtamt.ru>[/pre2] Аналогично и для аттачей: например, при разборе очередного аттача к письму, считанному в oMail, при GetFileName() получаю, например, [pre2]=?koi8-r?Q?Press=5Freliz=5F9=5F10=5F09g.doc?=[/pre2], а в результате надо иметь строку в RU1251: [pre2]Press_reliz_9_10_09g.doc[/pre2] Извиняюсь, если раньше обсуждалось - что-то не нашел. "oMail" создаю и заполняю как (к примеру) [pre2] cTmp := oPop:Retrieve( 1 ) // читаем с POP-сервера письмо №1 oMail := TIpMail():new() oMail:FromString( cTmp ) cFrom := oTIpMail:getFieldPart( "From" ) // получаем строку с именем (необязательно) и адресом отправителя[/pre2]

Петр: Как то раньше на глаза не попалось.. Наверное уже решили, но может кому то пригодится Значит на входе у вас =?koi8-r?Q?Press=5Freliz=5F9=5F10=5F09g.doc?= Отбрасываете слева =?koi8-r? Потом еще Q? Отрезаете справа ?= Далее в результате oEncoder := TIPEncoderQP():New() ? oEncoder:Decode( "Press=5Freliz=5F9=5F10=5F09g.doc" ) получаете искомое Press_reliz_9_10_09g.doc Теперь =?koi8-r?Q?=E1=CC=C5=CB=D3=C5=CA_=E7=D5=D3=D4=CF=D7?= <gustow336@pochtamt.ru> Для начала вам необходимо выделить адрес [pre2] nPos := At( "<", cFrom ) IF nPos > 0 nPos2 := hb_At( ">", cFrom, nPos + 1 ) IF nPos2 > nPos cMailAdr := SubStr( cFrom, nPos, ( nPos2 - nPos ) + 1 ) ENDIF cFrom := substr( cFrom, 1, nPos ) ENDIF [/pre2] А потом уже декодирование строки с именем, т.е. отбрасываем слева =?koi8-r?, потом еще Q?, отрезаем справа ?= и т.д. Обратите внимание, что при использовании метода FromString объекта oMail объект oEncoder может создаваться автоматически - это упрощает вашу задачу oMail := TIpMail():new() oMail:FromString( cTmp ) cFrom := oTIpMail:getFieldPart( "From" ) потом манипулируем с cFrom как было указано выше и в конце концов ? oMail:oEncoder:Decode( cFrom ) + cMailAdr выведет вам Алексей Густов <gustow336@pochtamt.ru> gustow пишет: как перекодировать, например, hb_translate еще не отменяли REQUEST HB_CODEPAGE_RU866 REQUEST HB_CODEPAGE_RUKOI8 hb_translate( "с╠┼╦╙┼╩ ч╒╙╘╧╫ <gustow336@pochtamt.ru>", "RUKOI8", "RU866" )

gustow: Петр пишет: Наверное уже решили, Да, в принципе (и почти что уже "в кожухе" :) - ["Прибор должен быть не в принципе, а в кожухе." (с) С.П. Королев]) решил. Чуть "поплутал" с Hb_Translate() - но все же выплыл. :) Кстати, вместо "простого" пути ("отбрасываете..." и т.д. по вышеуказанному) пришлось чуть усложнить процедуру раскодирования. При крэш-тестах на реальном массиве писем наткнулся на ситуации, когда строка (например, значение из "From") содержит не одну, а 2 или более подстрок, каждая из которых ограничена, к примеру, "=?koi8-r" и "?="... Ничего страшного - написал процедурку для разбора и с учетом таких ситуаций... Причем встречаются - и довольно часто - ситуации, когда oEncoder не создается автоматически (ну нет в RFC-822 у этого письма строки "Content-Transfer-Encoding" !..) - и тогда берем CharSet и Encoding непосредственно из закодированной строки (там же нам есть - как в разбираемой моей строке в вашем посте - и "koi8-r" [cChar = "RUKOI8"], и "q" [Encoding = ""quoted-printable"]... сооружаем соответствующий энкодер [oEncoder := TIPEncoderBase64():New( ) или oEncoder := TIPEncoderQP():New( )], раскодируем [cData := oEncoder:Decode( cData )], потом транслэйтим [cData := Hb_Translate( cData, cChar, "RUWIN" ) или cData := Hb_Utf8ToStr( cData )]... и все нормально! (в cData - выделенная из ограничителей раскодируемая подстрока) Т.ч. это сборол... почти... Иногда (корреляцию еще не выявил) в декодируемых строках вместо пробелов появляются "_" (точнее, "_" есть и в закодированной строке в явном виде - а при раскодировании они сохраняются, хотя тут должен быть пробел... а иногда это действительно должен быть "_")... или "?" вместо "№"... или еще что-то "непланировавшееся"... Но это уже не "жизненно важно" - да и в конце концов обойдусь пока. Главное - что сам процесс заработал вполне четко и контролируемо!.. P.S. Да!.. Еще выявился недостаток (недостаток ли?) метода oMail:DetachFile()... Если имя файла содержит не только латиницу, цифры или "-", "_" (и, соответственно, в результате :GetFileName() тоже предстает подобной кодированной строкой - см. начало DetachFile() в MAIL.PRG), то без дополнительного декодирования DetachFile() не срабатывает (возвращает .F. и FError() = 2; "File not found"), и, соответственно, вложение не сохраняется... Пока что решил это просто: скопировал DetachFile() как функцию к себе, добавил в ее вызов параметр cFileName (соответственно, "заглушив" внутренний ее LOCAL), и вызываю, указывая не только cPath, но и (уже раскодированный) cFileName... И все отлично срабатывает! М.б. как-то учесть такое в "родном" харборовском MAIL.PRG? На днях (сейчас чуть запарка) выложу все же пример на основе кода для этой задачки. Надеюсь, кому поможет в подобной "автоматизации". P.P.S. По "скоростным" характеристикам "крэш-теста": из 90 писем с вложениями (а это около 25% дневной нормы) "раскидывает" вложения по папочкам секунд за 40... По-моему, вполне прилично (человек - минимум минут за 30 "тупой" работы). P.P.S. А как начнутся "кириллические" домены (надеюсь, не слишком скоро) - ооооопяяятттььь в куче мест (в т.ч. и для этих "почтовых" вещей) придется "учитывать специфику" :) всем нам...

Петр: gustow пишет: Кстати, вместо "простого" пути Это не "простой" путь - это такой упрощенный типа алгоритм. Нормально-правильно использовать регулярные выражения для разбора строки - но извините, не хотелось много писать когда oEncoder не создается автоматически Имейте ввиду, что указать на нужный oEncoder мы можем создавая объект oMail с помощью метода New или с помощью метода setEncoder в декодируемых строках вместо пробелов появляются "_" Я заметил. Может быть это связано с несоответствием таблиц перекодировок в разных реализациях. М.б. как-то учесть такое в "родном" харборовском MAIL.PRG? М.б. К примеру метод GetBody это учитывает [pre2]METHOD GetBody() CLASS TipMail .. ELSEIF ::oEncoder != NIL RETURN ::oEncoder:Decode( ::cBody ) .. [/pre2]

AndreyZh: Добрый вечер! Подскажите пожалуйста? Встала аналогичная задача... разобрав пример из инструкции и полазив по исходникам - она показалась несложной, но возник затык в самом начале: В примере: Задан адрес "почты" oPop := TIpClientPop():new( "pop://mailaccount:password@pop.server.com" ) IF .NOT. oPop:open() ? "Connection error:", oPop:lastErrorMessage() QUIT ELSE aEMails := oPop:retrieveAll() oPop:close() ENDIF У меня настройки почты: Логин: Andrey@pricup.com Пароль: **** IMAP-сервер: imap.pricup.com POP3-сервер: pop.pricup.com SMTP-сервер: smtp.pricup.com Пишу соответственно: oPop := TIpClientPop():new( "pop://Andrey@pricup.com:****@pop.pricup.com" ) - программа в ? "Connection error:", oPop:lastErrorMessage() диагностирует превышение timeout Пытаюсь изменить время "допроса" сервера oPop := TIpClientPop():new( "pop://Andrey@pricup.com:****@pop.pricup.com" ) oPop:nConnTimeout := 20000 - впрочем ставил разные значения - всё без разницы Игрался с адресами, другими почтовыми ящиками, вызовами через класс: cUrl := "pop://gripptest:gripptest@26.188.255.166" oUrl := tURL():New( cUrl ) oClient := TIpClientPop():new( oUrl ) и т.д. никаких изменений не происходило. Прочитал кучу советов, но у "всех" этот нулевой этап доступа к почтовому ящику видимо спокойно проходил... Что делаю неправильно или где копать? Подскажите пожалуйста!

Dima: AndreyZh Сделай лог приема/отправки (есть опция) и разбери его , возможно нужно включить SSL

AndreyZh: Dima пишет: Сделай лог приема/отправки (есть опция) и разбери его , возможно нужно включить SSL Дима спасибо! Но ничего не понял? 1.Сделай лог приема/отправки (есть опция) Как и где? 2. и разбери его Какой формат и как его увидеть? 3. возможно нужно включить SSL Как? Хотя смотрел настройки "учетной записи" в Thunbird - там не включено 4. Как можно увеличить таймаут? Может просто не успеваю "достучаться"?

Dima: AndreyZh пишет: 1.Сделай лог приема/отправки (есть опция) Как и где? AndreyZh пишет: oPop := TIpClientPop():new( "pop://Andrey@pricup.com:****@pop.pricup.com" ) TIpClientPop():new( "pop://Andrey@pricup.com:****@pop.pricup.com", .T.) // видимо так , смотри сырец по умолчанию на POP , порт 110

petr707: Не уверен, что выбранный метод..TIpClientPop - лучшее решение можно попробовать hb_sendmail или TIpClientSmtp Что такое лог ? Во всех методах есть параметр - включить создание лог файла при ltrace=.t. создается лог - файл с именем SMTP-nnn.log где nnn - порядковый номер сеанса // preparing SMTP object oSmtp := TIpClientSmtp():new( cSmtpUrl, ltrace ) ... так выглядит лог-файл 20150801-19:53:55 :INETCONNECT( me.myserver.ru.com, 25 ) >> <pointer> << 20150801-19:53:55 :INETERRORCODE( <pointer> ) >> 0 << 20150801-19:53:55 :INETRECVLINE( <pointer>, , 512 ) >> 220 post.myserver.ru.com Microsoft ESMTP MAIL Service ready at Sat, 1 Aug 2015 19:53:52 +0300 << 20150801-19:53:55 :INETERRORCODE( <pointer> ) >> 0 << 20150801-19:53:55 :INETSENDALL( <pointer>, 9, HELO ОТПРАВИТЕЛЬ<cr><lf> ) >> 9 << 20150801-19:53:55 :INETRECVLINE( <pointer>, , 512 ) >> 250 post.myserver.ru.com Hello [83.167.104.184] << 20150801-19:53:55 :INETERRORCODE( <pointer> ) >> 0 << 20150801-19:53:55 :INETSENDALL( <pointer>, 28, MAIL FROM: <me@myserver.com><cr><lf> ) >> 28 << 20150801-19:53:55 :INETRECVLINE( <pointer>, , 512 ) >> 250 2.1.0 Sender OK << 20150801-19:53:55 :INETERRORCODE( <pointer> ) >> 0 << 20150801-19:53:55 :INETSENDALL( <pointer>, 25, RCPT TO: <who@me.myserver.com><cr><lf> ) >> 25 << 20150801-19:53:55 :INETRECVLINE( <pointer>, , 512 ) >> 250 2.1.5 Recipient OK << 20150801-19:53:55 :INETERRORCODE( <pointer> ) >> 0 << 20150801-19:53:55 :INETSENDALL( <pointer>, 6, DATA<cr><lf> ) >> 6 << 20150801-19:53:55 :INETRECVLINE( <pointer>, , 512 ) >> 354 Start mail input; end with <CRLF>.<CRLF> << 20150801-19:53:55 :INETERRORCODE( <pointer> ) >> 0 << .... 2) Нужно понять или настроить - какого типа авторизацию просит почтовый сервер, через который Вы пробуете работать. Отправлять письма можно: 1) через свой собственный сервер - все настройки полностью Ваши 2) публичный или корпоративный - надо соблюдать правила чужого сервера. Это номера портов, SSL или нет , и т.д. .. В примерах достаточно инфы, чтобы сделать свою почтовую службу

Dima: petr707 пишет: Отправлять письма можно: Андрей хочет принимать мыло.

AndreyZh: Dima пишет: Андрей хочет принимать мыло. Абсолютно верно... и как ТС для сохранения и обработки вложений Сейчас продолжу эксперименты

AndreyZh: Так и ничего не добился! Код: cUrl := pop://Andrey@pricup.com:****@pop.pricup.com oUrl := tURL():New( cUrl ) oPop := TIpClientPop():new( oUrl, .F. ) // .T. Трассировка соединения oPop:nDefaultPort := 110 oPop:nConnTimeout := 500000 IF !oPop:open() Возвращает .F. и по факту таймаут не меняется... Файлы трассировки при включении пустые... Непонятно!!! Во всех интернетовских примерах и обсуждениях это беспроблемно работающий код? Ping по адресу: pop.pricup.com проходят, пытался заменять на прямой адрес 89.111.176.249 - абсолютно аналогично

Dima: файер не блочит ?

AndreyZh: Dima пишет: файер не блочит ? Нет всё что можно отключил - те же история... Не понятно и до меня тяжело доходит, когда нет ни сообщений, ни диагностик, а лишь "срединение не доступно"... ещё конечно полазию по интернету, м.б. какие ещё нюансы нарою?

Dima: AndreyZh пишет: oPop := TIpClientPop():new( "pop://Andrey@pricup.com:****@pop.pricup.com" ) oPop:nConnTimeout := 20000 - впрочем ставил разные значения - всё без разницы Пробнул у себя с mail.ru , лог ведется , но он меня тормознул месагой "-ERR POP3 is available only with SSL or TLS connection enabled" в логе oPop:nConnTimeout ставил 2000 AndreyZh пишет: cUrl := pop://Andrey@pricup.com:****@pop.pricup.com вот так надо в кавычках "pop://Andrey@pricup.com:****@pop.pricup.com"

AndreyZh: Dima пишет: вот так надо в кавычках "pop://Andrey@pricup.com:****@pop.pricup.com" Извините за молчание - работа в "поле"... Конечно ставил в кавычках, просто при копировании не отразил... Вариантов решения общей "задачи" - сохранение вложение довольно много, например настройка почтового клиента на сохранение вложений... просто интересно было решить задачку в рамках средств xHarbour, тем более, что имеются такие "красивые" согласно документации средства. Ещё поизучаю опыт из интернета, но если не получится - не судьба

Dima: AndreyZh пишет: просто интересно было решить задачку в рамках средств xHarbour Так у тебя xHarbour все таки. А я тестил на Harbour

PSP: AndreyZh, а доступ к логам почтового сервера pop.picup.com есть? Может там что-то интересное найдётся?

AndreyZh: Dima пишет: Так у тебя xHarbour все таки. А я тестил на Harbour Извини, что не указал... просто стартовая тема была тоже под xHarbour и кажется тоже эксперименты безрезультатны. Для данной задачи мне по барабану - может быть и Harbour, т.к. это небольшая изолированная от других моих проектов задача, а по структуре баз всё идентично

AndreyZh: PSP пишет: AndreyZh, а доступ к логам почтового сервера pop.picup.com есть? Может там что-то интересное найдётся? Думаю, что доступа нет, но мне главное решение "в принципе", а почтовый ящик можно сделать на любом сервере - лишь бы работало!

petr707: Удается ли прочитать письма этого почтового ящика стандартным почтовым клиентом , Outlook' ом , например ? В этом клиенте - есть же настройки портов и прочее..

Dima: Был похожий глюк на Harbour 1.x http://clipper.borda.ru/?1-4-0-00000508-000-10001-0-1337333829 Не берусь судить о Xharbour так как не использую более. Пробни все таки свой примерчик собрать на последнем более менее свежем Harbour. Пробовал твой же пример из 7 строчек , все путем.

AndreyZh: petr707 пишет: Удается ли прочитать письма этого почтового ящика стандартным почтовым клиентом , Outlook' ом , например ? В этом клиенте - есть же настройки портов и прочее.. Всё настраивал и работаю с Thunderbird и понятно, что спокойно вхожу через броузер Dima пишет: Был похожий глюк на Harbour 1.x http://clipper.borda.ru/?1-4-0-00000508-000-10001-0-1337333829 Не берусь судить о Xharbour так как не использую более. Пробни все таки свой примерчик собрать на последнем более менее свежем Harbour. Пробовал твой же пример из 7 строчек , все путем Есть такой глюк с mail.ru, но через другие почтовые сервера отправка писем из прог на xHarbour при помощи Hb_sendmail не вызывает проблем Сейчас, в перерывах "между" попробую поставить Harbour и посмотреть на нём

AndreyZh: Разрешите для начала анекдот? Еврей приходит к Раввину, и говорит: - Ребе, помогите, куры дохнут! Раввин подумал, порылся в Талмуде, и говорит: - Попробуй их в морской воде искупать. Еврей возвращается через неделю, и говорит: - Ребе, всё равно куры дохнут! Раввин подумал, порылся в Талмуде, и говорит: - Попробуй их кормить свежей редькой. Еврей возвращается через неделю, унылый, и говорит: - Ребе, куры все сдохли! Раввин почесал в затылке, и говорит: - Жаль, а у меня ещё столько хороших идей было... Установил сначала Harbour на другом ПК, где когда-то трахался с ним сейчас в работе... и конечно кучка проблем со сборками программ - одна из причин почему использую xHarbour: меньше плясок с бубнами... конечно с ходу не получилось, тем более, что дергают. Тогда просто скопировал MiniGui, где так же есть свежий Harbour - более простое решение ради двух строк кода... Затем по "советам" начал перебирать свои почтовые ящики и пробовать передачу параметра в TIpClientPop по символьной переменной или объекту, например: oUrl := tURL():New( "pop://poseydon2000solprod@yandex.ru:****@pop.yandex.ru" ) oPop := TIpClientPop():new( oUrl, .T. ) ..... Короче, как не меняй эффект один, только Harbour хотя бы идентичные логи лепит, хотя и таймаут реально не изменяет, например: 20160302-12:18:49 :INETCONNECT( pricup.com, 110 ) >> <pointer> << 20160302-12:18:49 :INETERRORCODE( <pointer> ) >> 17 << 20160302-12:25:58 :INETCONNECT( mail.ru, 110 ) >> <pointer> << 20160302-12:25:58 :INETERRORCODE( <pointer> ) >> 17 << 20160302-12:43:59 :INETCONNECT( yandex.ru, 110 ) >> <pointer> << 20160302-12:43:59 :INETERRORCODE( <pointer> ) >> 17 << ... В общем понял, что нужно искать более проработанный инструмент или терять время, когда его будет больше

Dima: AndreyZh пишет: 20160302-12:25:58 :INETCONNECT( mail.ru, 110 ) До лампочки AndreyZh пишет: 20160302-12:43:59 :INETCONNECT( yandex.ru, 110 ) И это тоже , так как на них обоих включена обязательная SSL , поэтому без HBSSL тут не обойтись. Порт 110 так же не катит.

AndreyZh: Извините за тон уважаемые господа... и спасибо за посильную помощь! Задача по примеру инструкции казалась легкой, о оказалось "как обычно". Видимо нет сейчас времени глубоко изучать и вникать - отложу задачу до "лучших" времен

Dima: AndreyZh пишет: oUrl := tURL():New( "pop://poseydon2000solprod@yandex.ru:****@pop.yandex.ru" ) тут нужен pop3s Тоже стал разбираться со чтением почты , чекал на mail.ru Не знаю как на яше но на майл ру логин нужно передавать без @mail.ru

Dima: Непонятная порча с чтением темы письма , если оно отправлено с мобилы. В теме забивали *SOS# , читаю в Harbour и получаю =?UTF-8?B?KlNPUyM=?= Если отправлять с компа с такой же темой , то получаю в теме *SOS# Не пойму как такое может быть...

Dima: OnLine декодер распознал однако Как теперь в Harbour раскодировать ?

Dima: Вроде понял как Нужно проанализировать строку на предмет (по шаблону) =?UTF-8?B? Если такая строка есть , то вырезаем ее и после остатку строки делаем hb_base64Decode

Петр: Dima пишет: =?UTF-8?B? Если такая строка есть , то вырезаем ее и после остатку строки делаем hb_base64Decode Не совсем так. =?UTF-8?B?KlNPUyM=?= В этой теме был разбор похожей строки. Сначала отбрасываем то, что выделенно красным. Потом смотрим в какой кодировке указана тема (UTF-8) Потом упакована ли строка (B - base64, для utf8 упаковка производится всегда) Дальше вырезаем строку и декодируем/транслируем в соотв. кодировку.

Dima: Петр Сделал так [pre2] if hb_RegexHas('[=]\?[A-Z0-9\-]+\?[A-Z]{1}+\?' ,oPop:getSubject(i) ) kk:=hb_regexSplit( '[=]\?[A-Z0-9\-]+\?[A-Z]{1}+\?', oPop:getSubject(i) , , ,1) а далее разбираю массив + на нужном элементе result:=hb_base64Decode( kk[JJ] ) тема всегда на English endif [/pre2]

Петр: По моему это можно упростить Материал по теме Если English, то charset можно игнорировать; декодировать нужно, только если encoding == "B"; от регулярных выражений можно отказаться, а можно и не отказываться

Dima: Петр Благодарю за подсказку !

Dima: Петр пишет: от регулярных выражений можно отказаться Верно , так даже проще [pre2] if hb_LeftEq(tema,'=?UTF-8?B?') .and. right(tema,2)=='?=' tema:=hb_base64Decode(substr(tema,11,len(tema)-12)) endif [/pre2]



полная версия страницы