Форум » 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

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 ) и т.д. никаких изменений не происходило. Прочитал кучу советов, но у "всех" этот нулевой этап доступа к почтовому ящику видимо спокойно проходил... Что делаю неправильно или где копать? Подскажите пожалуйста!



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