Форум: "Сети";
Текущий архив: 2011.08.07;
Скачать: [xml.tar.bz2];
ВнизTidPOP3 заголовки не всех писем получает. Как заставить? Найти похожие ветки
← →
sasha73 (2009-04-14 18:28) [0]Добрый день, Мастера.
Второй день бьюсь. Сначало код, потом объясню:
Var
POP3 : TIdPOP3;
MsgRecive : TIdMessage;
st : String;
Begin
POP3:=TIdPOP3.Create(nil);
MsgRecive:=TIdMessage.Create(nil);
POP3.Host:="aa.bb.cc.dd";
POP3.Username:="user1";
POP3.Password:="passwd1";
POP3.Connect(5000);
POP3.RetrieveHeader(3,MsgRecive);
St:=MsgRecive.Subject;
На некоторых сообщения не принимается заголовок. Не могу понять почему. Т.е. St в итоге пустая строка. Хотя на самом деле в письме тема заполнена.
Заголовок письма несколько нестандартен:
From user@domen.ru Mon Apr 13 17:45:41 2009
X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on domen.ru
X-Spam-Level: **
X-Spam-Status: No, score=2.9 required=5.0 tests=ALL_TRUSTED,DATE_IN_PAST_03_06,
TVD_SPACE_RATIO autolearn=no version=3.2.5
>From office Mon Apr 13 17:45:41 2009
Return-Path: <send@domen.ru>
X-Original-To: rcpt@domen.ru
Delivered-To: rcpt@domen.ru
Received: from domen.ru (localhost [127.0.0.1])
...
В Delphi 6 на POP3.RetrieveHeader(3,MsgRecive) вообще было исключение "Connection Closed Gracefully". После установки Delphi 7 исключения нет, но заголовок пустой.
Понятно, что это из-за нестандартности письма. Такие письма получаются в результате персылки. Но все же компонент TNMPOP3 обрабатывает его нормально. И все почтовые клиенты. На TNMPOP3 переходить не хочется, т.к. немало кода уже написано под TIdPOP3. :-(
Как думаете, есть возможность заставить TIdPOP3 воспринимать все заголовки отдельно?
← →
sasha73 (2009-04-14 18:30) [1]Не отдельно, а правильно, имелось ввиду. :-)
(Извините, голова уже болит и перепрыгиваю с одного задания на другое)
← →
Сергей М. © (2009-04-14 20:18) [2]
> это из-за нестандартности письма
Что же в нем нестандартного по-твоему ?
И где в процитированном тобой фрагменте заголовка оригинальное значение поля Subject, о проблеме с котором собссно и идет речь, судя по
> St в итоге пустая строка
?
← →
sasha73 (2009-04-15 10:13) [3]Спасибо за ответ.
> Что же в нем нестандартного по-твоему ?
Многие почтовые клиенты, особенно не самых последних версий "неадекватно" реагируют, на знаки типа ">" и т.п. в средине заголовка письма. Думал в нем причина, оказывается нет.
> И где в процитированном тобой фрагменте заголовка оригинальное
> значение поля Subject
Я внизу заголовка поставил троеточие, извините, не догадался, что слов "Хотя на самом деле в письме тема заполнена" и "Но все же компонент TNMPOP3 обрабатывает его нормально. И все почтовые клиенты" будет недостаточно. Привел, только по моему мнению "нестандартную часть".
Вот весь заголовок:
From send@domen.ru Mon Apr 13 17:45:41 2009
X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on domen.ru
X-Spam-Level: **
X-Spam-Status: No, score=2.9 required=5.0 tests=ALL_TRUSTED,DATE_IN_PAST_03_06,
TVD_SPACE_RATIO autolearn=no version=3.2.5
>From office Mon Apr 13 17:45:41 2009
Return-Path: <send@domen.ru>
X-Original-To: rcpt@domen.ru
Delivered-To: rcpt@domen.ru
Received: from domen.ru (localhost [aa.bb.cc.dd])
by domen.ru (Postfix) with ESMTP id E81A736A01E
for <rcpt@domen.ru>; Mon, 13 Apr 2009 17:45:40 +0000 (UTC)
Received: from [aa.bb.cc.dd] (aa.bb.cc.dd.ip.prov.net [aa.bb.cc.dd])
by domen.ru (Postfix) with ESMTPA id 26CDB36A01A
for <rcpt@domen.ru>; Mon, 13 Apr 2009 17:45:39 +0000 (UTC)
Message-ID: <49E34FD4.10701@domen.ru>
Date: Mon, 13 Apr 2009 17:44:36 +0300
From: =?UTF-8?B?0JDQu9C10LrRgdCw0L3QtNGA?= <send@domen.ru>
User-Agent: Thunderbird 2.0.0.21 (Windows/20090302)
MIME-Version: 1.0
To: rcpt@domen.ru
Subject: =?UTF-8?B?0J/RgNC+0LLQtdGA0LrQsCDRgNCw0LHQvtGC0Ysg0L/QvtGH0YLQvtCy?=
=?UTF-8?B?0L7Qs9C+INGA0L7QsdC+0YLQsDI=?=
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
X-Virus-Scanned: ClamAV using ClamSMTP
Оказалось POP3.RetrieveHeader(3,MsgRecive) в моем случае читает только 3 строки. Т.е.:
For i:=0 to MsgRecive.Headers.Count-1 do
St:=MsgRecive.Headers.Strings[i];
Получаем:
1 = "X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on domen.ru"
2 = "X-Spam-Level: **"
3 = "X-Spam-Status: No, score=2.9 required=5.0 tests=ALL_TRUSTED,DATE_IN_PAST_03_06,"
Т.е. если строка заканчивается на запятую и $0A , а следующая начинается с $09 - компонент считает это концом заголовка. :-(
Вот вам и стандартность заголовка.
Придется ковыряться в коде TidPOP3. Кода много, а опыта и времени не хватает. :-)
Может другой способ посоветуете? Может какие-то еще есть интересные свойства/методы у этого компонента?
← →
Сергей М. © (2009-04-15 12:53) [4]У меня установлен Indy10
На форме - Memo, в нем текст заголовка, скопированного один-в-один из [9]
Запускаю тест:procedure TForm1.Button3Click(Sender: TObject);
var
msg: TIdMessage;
ms: TStream;
begin
ms := TMemoryStream.Create;
Memo.Lines.SaveToStream(ms);
ms.Position := 0;
msg := TIdMessage.Create;
msg.Headers.LoadFromStream(ms);
msg.ProcessHeaders;
ShowMessage(msg.Subject);
ms.Free;
msg.Free;
end;
Вижу огрызок темы "Проверка работы почтов".
Привожу заголовок в соответствие с п.2.2.3 RFC-2822.
Повторяю тот же тест, вижу полную строку темы "Проверка работы почтового робота2".
Как видишь, ни до ни после правки заголовка поле темы не было пустым.
Вывод: индейский парсер заголовка работает корректно.
← →
sasha73 (2009-04-15 17:14) [5]
> Привожу заголовок в соответствие с п.2.2.3 RFC-2822.
В данном случае это не очень важно, так как из заголовка читается только 3 верхние строки.
> msg.Headers.LoadFromStream(ms);
Данный код и у меня отрабатывает нормально и без проблем. Подозреваю что методы Headers.LoadFromStream и RetrieveHeader работают по разному. Так как и у меня на этом письме POP3.RetrieveRaw получает все письмо с заголовком и телом, т.е. все верно.
А значит вывод
> Вывод: индейский парсер заголовка работает корректно.
не совсем точен. ;-)
Спасибо, что уделили время и даже попробовали код. В свою очередь, я не поленился, открыл на рабочем сервер 110-й порт, где можно попробовать:
Procedure TestIndy;
Var
POP3 : TIdPOP3;
MsgRecive : TIdMessage;
Begin
POP3:=TIdPOP3.Create(nil);
MsgRecive:=TIdMessage.Create(nil);
POP3.Host:="91.203.13.3";
POP3.Username:="indy";
POP3.Password:="indypass";
POP3.Connect;
POP3.RetrieveHeader(1,MsgRecive);
MessageBox(0,PChar("\"+MsgRecive.Subject+"/"),"Empty:",mb_OK);
MessageBox(0,PChar("Header string count = "+IntToStr(MsgRecive.Headers.Count)),"Empty:",mb_OK);
POP3.RetrieveHeader(2,MsgRecive);
MessageBox(0,PChar("\"+MsgRecive.Subject+"/"),"Empty:",mb_OK);
MessageBox(0,PChar("Header string count = "+IntToStr(MsgRecive.Headers.Count)),"Empty:",mb_OK);
End;
Это реально работающий сервер, где каждому можно будет попробовать несколько дней поэкспериментировать. Там лежит именно это письмо первое по счету, и второе - точная его копия, но удалена в конце строки "X-Spam-Status: No, score=2.9 required=5.0 tests=ALL_TRUSTED,DATE_IN_PAST_03_06," запятая. Как видно, с ним компонент работает нормально.
Так все же, можно ли как-то заставить этот компонент работать нормально или придется пользоваться чем-то другим?
← →
Сергей М. © (2009-04-15 17:27) [6]
> sasha73 (15.04.09 17:14) [5]
> точная его копия, но удалена в конце строки "X-Spam-Status:
> No, score=2.9 required=5.0 tests=ALL_TRUSTED,DATE_IN_PAST_03_06,
> " запятая
В [4] я не удалял никаких запятых, и при этом поле Тема было непустое...
← →
sasha73 (2009-04-15 18:02) [7]
> В [4] я не удалял никаких запятых, и при этом поле Тема
> было непустое...
Я жек вроде объяснил, что код:
procedure TForm1.Button3Click(Sender: TObject);
var
msg: TIdMessage;
ms: TStream;
begin
ms := TMemoryStream.Create;
Memo.Lines.SaveToStream(ms);
ms.Position := 0;
msg := TIdMessage.Create;
msg.Headers.LoadFromStream(ms);
msg.ProcessHeaders;
ShowMessage(msg.Subject);
ms.Free;
msg.Free;
end;
и у меня отрабатывает верно и без проблем. И объяснил свои догадки, почему. У вас ...Headers.LoadFromStream.. , а у меня ..RetrieveHeader...
Вы выпонили новый код из [5]? Думаю у вас тоже будет ошибка. ;-)
← →
Сергей М. © (2009-04-15 21:38) [8]
> sasha73 (15.04.09 18:02) [7]
Да, я воспроизвел ситуацию, проиллюстрированную в [5].
В ближ.время постараюсь локализовать "засаду".
← →
sasha73 (2009-04-16 09:34) [9]Больше нет идей? :-(
← →
Сергей М. © (2009-04-16 12:08) [10]
> Больше нет идей?
Уже есть)
Все движется к тому, что твой POP3-сервер - кривой.
В ответ на запросRETR 1
сервер отдает оригинальный приведенный тобой заголовок + тело. Именно поэтому почтовые клиенты (включая IdPOP3), по дифолту вызывающие именно RETR, получают нормальный заголовок и тело и так же нормально парсят возвращенные данные.
В ответ же на запросTOP 1 0
тот же сервер отдает искаженный заголовок. Ты можешь убедиться в этом, настроив любой почт.клиент на запрос только заголовков.
Я провел экперимент на ICS TSyncPOOP3Cli и получил те же результаты, которые показал IdPOP3.
← →
Сергей М. © (2009-04-16 12:22) [11]А вот и обещаная "засада":
http://www.temnota.kmv.ru/vm-pop3d/CHANGES
31/Jan/2002 1.1.7
Bug Fix: Changed pop3_top (top.c) so it wouldn"t think headers
were finished, when a header is 80 characters long. (Reported by
Tomi Hakala.)
А у тебя допотопная версия 1.1.6)
Так что прежде чем искать жуков в индейских кущах (хотя их там и действительно немало), сначала ищи эту живность у себя на сервере, регулярно следи за чейнджлогами версий демона и оперативно обновляй)
← →
sasha73 (2009-04-16 14:04) [12]СПАСИБО !
Вы абсолютно правы. Проблема в POP3-сервере, а не в компоненте.
Снимаю шляпу и благодарю за потраченное вермя и поиск истины.
> А у тебя допотопная версия 1.1.6)
А это не совем верно. Я регулярно обновляю порты (это во FreeBSD) и версия этого POP3-сервера заявлена, как финальный релиз. Да и на сайте производителя тоже именно она предложена в разделе "DownLoad".
А 1.1.7 - это текущая разрабатываемая:
virtualmail-pop3d (aka vm-pop3d)
Current development: 1.1.7f (01/Jul/2003)
Хотя соглашусь с Вами - сервер не супер и старенький. Достался мне "по наследству" и удобен, тем что прост, мал и быстр.
Об этой ошибке не задумался и не догадывался, т.к. с него берут почту около 200-х пользователей уже > 2-х лет и о проблемах небыло слышно. Вот сегодня обновил на development. :-)
Еще раз спасибо, теперь буду внимательнее изучать проблему со всех сторон.
← →
Сергей М. © (2009-04-16 14:18) [13]
> sasha73 (16.04.09 14:04) [12]
Ну тогда еще один момент остался - нарушение RFC2822 в части строк<-- этой
X-Spam-Status: No, score=2.9 required=5.0 tests=ALL_TRUSTED,DATE_IN_PAST_03_06,
TVD_SPACE_RATIO autolearn=no version=3.2.5
>From office Mon Apr 13 17:45:41 2009<-- и этой
Subject: =?UTF-8?B?0J/RgNC+0LLQtdGA0LrQsCDRgNCw0LHQvtGC0Ysg0L/QvtGH0YLQvtCy?=
=?UTF-8?B?0L7Qs9C+INGA0L7QsdC+0YLQsDI=?=
Кто нарушает соглашения - твой POP3-сервер ?
Или здесь он ни причем (что получил, то и отдал) ?
← →
Сергей М. © (2009-04-16 20:59) [14]
> версия .. заявлена.. как финальный релиз
"О сколько нам открытий чудных .." (С) ВНП
Я вот тоже свято верил, что версия MT ROS 3.20 - финальная, як була заявлена разработчиками) .. до нек.момента .. пока не получил граблищами по лбу)
Шишку прочесал, успокоился, залез в чейджлог - а там нонче м 3.22 в финале уже числится))
О как)
← →
sasha73 (2009-04-17 13:38) [15]
> Кто нарушает соглашения - твой POP3-сервер ?Или здесь он
> ни причем (что получил, то и отдал) ?
К счастью, хоть тут он не при чем. :-) Это по пути в ящик почтовые клиенты и MTA "балуются". :-) Меня это не смущало, т.к. когда-то неск. лет назад писал почтового робота и разбирал заголовки писем в большом количестве. Очень часто встречались отклонения от стандартов и пришлось их учитывать. Особенно спамеры тогда что-попало слали. Это сейчас их сложно отличить. :-)
Текущая версия этого POP3-севера оказалась нестабильной. Хотя еще не разобирался точно, от чего он падал. Да и это неважно - будет морочить голову, мы его наконец-то заменим. Он и так явно не лидер в этом направлении. :-)
О слежении за версиями, согласен, бывает всякое - нужно стараться следить и внимательно изучать.
Еще раз спасибо, а то я уже собирался перейти на другой компонент или вручную тело разбирать. Хотя, IdPOP3 все такие кое-чем не понравился. В отличии от той версии, что была еще в D6, в D7 MsgRecive.Subject возвращает уже декодированную стоку (переведенную к кодировку Win-1251), а это не всегда хорошо. Т.к. он не знает даже кодировки koi8-r и других некоторых, поэтому пришлось брать тему как MsgRecive.Headers.Values["Subject"] и самому декодировать. В остальном хорошая вещица.
Интересно, можно ли заставить этот компонент не умничать и не декодировать заголовок, или отдельно тему?
← →
app © (2009-04-17 14:04) [16]> sasha73 (17.04.2009 13:38:15) [15]
Это отдельная тема
← →
Сергей М. © (2009-04-17 16:35) [17]
> можно ли заставить этот компонент не умничать и не декодировать
> заголовок, или отдельно тему?
А чем эта фича тебе помешала ?
Или тебе raw-данные заголовков нужны ?
← →
sasha73 (2009-04-17 16:44) [18]
> А чем эта фича тебе помешала ?
Ну я же говорю, она не все кодировки знает, и соотв. выдает неверный результат.
Т.е. когда Subject="=?koi8-r?B?4vTrIOvJxdc=?=" она выдает "âôë ëÉÅ×", т.е. уже и кодировка становится неизвестна (когда она в других полях заголовка уже не указана) и результат неверный.
Как ее заставить не декодировать тему, From и т.д. ? Пока только так получилось:
MsgRecive.Headers.Values["Subject"]
← →
Сергей М. © (2009-04-17 17:33) [19]
> Пока только так получилось
Это ты взял RAW-данные
> Как ее заставить не декодировать тему, From и т.д. ?
Не надо ее "заставлять", надо помочь !)
Читай справку к классу TIdHeaderCoderPlain.
Пример "помощи":
unit MsgHdrCoders;
interface
uses
IdHeaderCoderPlain;
type
TCodeMatrix = array[1..255] of char;
const
FirstCodes =
#1#2#3#4#5#6#7#8#9#10#11#12#13#14#15#16#17#18#19#20#21#22#23#24#25#26#27#28+
#29#30#31" !"#$%&""()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^" +
"_`abcdefghijklmnopqrstuvwxyz{|}~";
cmAnsiToKoi8R: TCodeMatrix = FirstCodes
+ "ЂЃ‚ѓ„…†‡€‰Љ‹ЊЌЋЏђ‘’“”•–—?™љ›њќћџ ЎўЈ¤Ґ¦§Ё©Є«¬®Ї°±Ііґµ¶·Ј—є»јЅѕїбвчздецъй"
+ "клмнопртуфхжигюыэящшьасБВЧЗДЕЦЪЙКЛМНОПРТУФХЖИГЮЫЭЯЩШЬАС";
cmAnsiToKoi8U: TCodeMatrix = FirstCodes
+ "ЂЃ‚ѓ„…†‡€‰Љ‹ЊЌЋЏђ‘’“”•–—?™љ›њќћџ ЎўЈ¤Ґ¦§Ё©Є«¬®Ї°±Ііґµ¶·Ј—є»јЅѕїбвчздецъй"
+ "клмнопртуфхжигюыэящшьасБВЧЗДЕЦЪЙКЛМНОПРТУФХЖИГЮЫЭЯЩШЬАС";
cmKoi8RToAnsi: TCodeMatrix = FirstCodes
+ "-¦-¬L-++T++---¦¦---?¦•v??? ?°?·?=¦-ёг㬬¬LLL---¦¦¦¦Ё¦¦TTT¦¦¦+++©юабцдефгх"
+ "ийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ";
cmKoi8UToAnsi: TCodeMatrix = FirstCodes
+ "-¦-¬L-++T++---¦¦---?¦•v??? ?°?·?=¦-ёєгії¬LLL-ґў¦¦¦¦ЁЄ¦ІЇT¦¦¦+ҐЎ©юабцдефгх"
+ "ийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ";
cmOemDosToAnsi: TCodeMatrix = FirstCodes
+ "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп---¦+¦¦¬¬¦¦¬---¬L+T+-+¦¦L"
+ "г¦T¦=+¦¦TTLL-г++----¦¦-рстуфхцчшщъыьэюяЁёЄєЇїЎў°•·v№¤¦ ";
cmIsoToAnsi: TCodeMatrix = FirstCodes
+ "???????????????????????????????? ЁЂЃЄЅІЇЈЉЊЋЌЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШ"
+ "ЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя№ёђѓєѕіїјљњћќ§ўџ";
type
TIdHeaderCoderKOI8 = class(TIdHeaderCoderPlain)
public
class function Decode(const ACharSet, AData: String): String; override;
class function Encode(const ACharSet, AData: String): String; override;
class function CanHandle(const ACharSet: String): Boolean; override;
end;
function ConvertCharset(AString: String; AMatrix: TCodeMatrix): String;
implementation
uses IdGlobal, IdHeaderCoderBase;
function ConvertCharset(AString: String; AMatrix: TCodeMatrix): String;
var
i: Integer;
begin
Result := "";
for i:= 1 to Length(AString) do
Result := Result + AMatrix[Ord(AString[i])];
end;
{ TIdHeaderCoderKOI8 }
class function TIdHeaderCoderKOI8.CanHandle(const ACharSet: String): Boolean;
begin
Result := TextIsSame(ACharSet, "KOI8-R") or TextIsSame(ACharSet, "KOI8-U");
end;
class function TIdHeaderCoderKOI8.Decode(const ACharSet, AData: String): String;
begin
if TextIsSame(ACharSet, "KOI8-R") then
Result := ConvertCharset(AData, cmKoi8RToAnsi)
else if TextIsSame(ACharSet, "KOI8-U") then
Result := ConvertCharset(AData, cmKoi8UToAnsi);
end;
class function TIdHeaderCoderKOI8.Encode(const ACharSet, AData: String): String;
begin
if TextIsSame(ACharSet, "KOI8-R") then
Result := ConvertCharset(AData, cmAnsiToKoi8R)
else if TextIsSame(ACharSet, "KOI8-U") then
Result := ConvertCharset(AData, cmAnsiToKoi8U);
end;
initialization
RegisterHeaderCoder(TIdHeaderCoderKOI8);
finalization
UnregisterHeaderCoder(TIdHeaderCoderKOI8);
end.
← →
имя (2009-04-18 21:00) [20]Удалено модератором
← →
sasha73 (2009-04-21 13:54) [21]
> Это ты взял RAW-данные
Да, я понимаю.
> Читай справку к классу TIdHeaderCoderPlain.
Пример "помощи":
Спасибо, отлично. То, что нужно.
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2011.08.07;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.003 c