Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 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=?=" она выдает "&#226;&#244;&#235; &#235;&#201;&#197;&#215;", т.е. уже и кодировка становится неизвестна (когда она в других полях заголовка уже не указана) и результат неверный.

  Как ее заставить не декодировать тему, 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
15-1303019199
Inovet
2011-04-17 09:46
2011.08.07
Монеты, посвященные олипиаде в Сочи 2014


15-1303203122
OW
2011-04-19 12:52
2011.08.07
MDI оболочка для любых программ


15-1302899395
Юрий
2011-04-16 00:29
2011.08.07
С днем рождения ! 16 апреля 2011 суббота


15-1303122801
DiamondShark
2011-04-18 14:33
2011.08.07
Мобильные браузеры (WM)


15-1303035864
Пит
2011-04-17 14:24
2011.08.07
Очень нужен совет от тех, кто разбирается в биллинге





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский