строка в кодировке base64 усекается с помощью вызова fgets при анализе IMAP


Я разбираю электронные письма с помощью Zend_Mail, и, как ни странно, некоторое содержимое усекается без очевидной причины и искажает части электронной почты.

Например

Content-Disposition: attachment; filename="file.sdv"

DQogICAgICBTT05FO0xBTkRJTkdTREE7U0FMR1NEQVRPIDtOQVNKIDtSRURTS0FQICAgICAgICAg
ICAgIDsgRklTS0VTTEFHO1BSRVNFUlYgICA7ICBUSUxTVEFORDsgU1TYUlJFTFNFOyAgS1ZBTElU
RVQ7T01TVFlQRSAgO01JTlNURVBSSVM7ICAgICBWRVJESTsgICBLVkFOVFVNOyAgUlVORFZFS1Qg
IA0KLS0tLS0tLS0tLTstLS0tLS0tLS0tOy0tLS0tLS0tLS07LS0tLS07LS0tLS0tLS0tLS0tLS0t
LS0tLS07LS0tLS0tLS0tLTstLS0tLS0tLS0tOy0tLS0tLS0tLS07LS0tLS0tLS0tLTstLS0tLS0t
LS0tOy0tLS0tLS0tLTstLS0tLS0tLS0tOy0tLS0tLS0tLS07LS0tLS0tLS0tLTstLS0tLS0tLS0t
ICANCiAgICAgICAgIDA7MjAxMC4wOS4wODsyMDEwLjA5LjA4O05vcnNrO0dhcm4gICAgICAgICAg
ICAgICAgOyAgICAgIDEwMjE7RkVSU0sgICAgIDsgICAgICAgMjEwOyAgIDQwMjA5OTk7ICAgICAg
ICAyMDtFZ2Vub3ZlcnQ7ICAgICAgICAgIDsgICAzMDcyLDE2OyAgICAgICAyMTE7ICAgICAyNTMs
MiAgDQogICAgICAgICAwOzIwMTAuMDkuMDg7MjAxMC4wOS4wODtOb3JzaztHYXJuICAgICAgICAg

Усекается до

Content-Disposition: attachment; filename="file.sdv"

DQogICAgICBTT05FO0xBTkRJTkdTREE7U0FMR1NEQVRPIDtOQVNKIDtSRURTS0FQICAgICAgICAg
ICAgIDsgRklTS0VTTEFHO1BSRVNFUlYgICA7ICBUSUxTVEFORDsgU1TYUlJFTFNFOyAgS1ZBTElU
RVQ7T01TVFlQRSAgO01JTlNURVBSSVM7ICAgICBWRVJESTsgICBLVkFOVFVNOyAgUlVORFZFS1Qg
IA0KLS0tLS0tLS0tLTstLS0tLS0tLS0tOy0tLS0tLS0tLS07LS0tLS07LS0tLS0tLS0tLS0tLS0t
LS0tLS07LS0tLS0tLS0tLTstLS0tLS0tLS0tOy0tLS0tLS0tLS07LS0tLS0tLS0tLTstLS0tLS0t
LS

Значение var_dump в каждой строке показывает это.

string(78) "DQogICAgICBTT05FO0xBTkRJTkdTREE7U0FMR1NEQVRPIDtOQVNKIDtSRURTS0FQICAgICAgICAg
"
string(78) "ICAgIDsgRklTS0VTTEFHO1BSRVNFUlYgICA7ICBUSUxTVEFORDsgU1TYUlJFTFNFOyAgS1ZBTElU
"
string(78) "RVQ7T01TVFlQRSAgO01JTlNURVBSSVM7ICAgICBWRVJESTsgICBLVkFOVFVNOyAgUlVORFZFS1Qg
"
string(78) "IA0KLS0tLS0tLS0tLTstLS0tLS0tLS0tOy0tLS0tLS0tLS07LS0tLS07LS0tLS0tLS0tLS0tLS0t
"
string(78) "LS0tLS07LS0tLS0tLS0tLTstLS0tLS0tLS0tOy0tLS0tLS0tLS07LS0tLS0tLS0tLTstLS0tLS0t
"
string(5) "LS)
"
string(17) "TAG5 OK Success
"    

Или в другом электронном письме по адресу

DQogICAgICBTT05FO0xBTkRJTkdTREE7U0FMR1NEQVRPIDtOQVNKIDtSRURTS0FQICAgICAgICAg
ICAgIDsgRklTS0VTTEFHO1BSRVNFUlYgICA7ICBUSUxTVEFORDsgU1TYUlJFTFNFOyAgS1ZBTElU
RVQ7T01TVFlQRSAgO01JTlNURVBSSVM7ICAgICBWRVJESTsgICBLVkFOVFVNOyAgUlVORFZFS1Qg
IA0KLS0tLS0tLS0tLTstLS0tLS0tLS0tOy0tLS0tLS0tLS07LS0tLS07LS0tLS0tLS0tLS0tLS0t
LS0tLS07LS0tLS0tLS0tLTstLS0tLS0tLS0tOy0tLS0tLS0tLS07LS0tLS0tLS0tLTstLS0tLS0t
LS0tOy0tLS0tLS0tLTstLS0tLS0tLS0tO

Я не могу понять, почему останавливаюсь на этом. Передачи должны были останавливаться только в конце линии. Это строка, которая получает строку из IMAP Сервер.

$line = @fgets($this->_socket);

Закодированный текст содержит строку типа, но опять же она усечена в разных частях в разных электронных письмах.

----------;----------;----------;-----;--------------------;----------;----------;--

Я пытался добавить размер в fgets(), но безрезультатно. Я также включил/отключил настройку php_ini "auto_detect_line_endings", снова без результата.

Я также открыл отчет об ошибке с помощью ZF, хотя ошибки, похоже, нет в библиотеке.

Видите ли вы что-нибудь странное в этом закодированном строка?

ОБНОВЛЕНИЕ

Новое исследование показывает, что электронные письма усекаются после 584 символов. До сих пор не знаю, почему. Также отправил вопрос в Google. Смотрите здесь.

Плохие заголовки электронной почты:

Delivered-To: [email protected]
Received: by 10.216.3.208 with SMTP id 58cs248812weh;
    Fri, 20 Nov 2009 05:14:14 -0800 (PST)
Received: by 10.204.153.217 with SMTP id l25mr1285471bkw.108.1258722853863;
    Fri, 20 Nov 2009 05:14:13 -0800 (PST)
Return-Path: <>
Received: from MTX4.mbn1.net (mtx4.mbn1.net [213.188.129.252])
    by mx.google.com with SMTP id 2si1800716bwz.60.2009.11.20.05.14.12;
    Fri, 20 Nov 2009 05:14:13 -0800 (PST)
Received-SPF: pass (google.com: best guess record for domain of MTX4.mbn1.net designates         213.188.129.252 as permitted sender) client-ip=213.188.129.252;
Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of MTX4.mbn1.net designates 213.188.129.252 as permitted sender) smtp.mail=
Resent-From: <[email protected]>
Content-Type: multipart/mixed; boundary="===============1703099044=="
MIME-Version: 1.0
From: <[email protected]>
To: <[email protected]>
CC:
Subject: some subject
Message-ID: <[email protected]>
X-OriginalArrivalTime: 20 Nov 2009 13:14:08.0121 (UTC) FILETIME=[5792C690:01CA69E3]
Date: Fri, 20 Nov 2009 14:14:08 +0100
X-STA-Metric: 0 (engine=030)
X-STA-NotSpam: tlf: vedlagt skip:__ 40 fil cc:2**0
X-STA-Spam: header:MIME-Version: charset:us-ascii header:Subject:1 to:2**0 header:From:1
X-BTI-AntiSpam: score:0,sta:0/030,dnsbl:passed,sw:off,bsn:38/passed,spf:off,bsctr:passed/1,dk:off,pbmf:none,ipr:0/3,trusted:no,ts:no,bs:no,ubl:passed
X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply
Resent-Message-Id: <[email protected]>
Resent-Date: Fri, 20 Nov 2009 14:14:11 +0100 (CET)

--===============1703099044==
Content-Type: application/octet-stream
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="file.sdv"

DQpHUlVQUEVOQVZOICAgICAgICAgIDtLSthQRTtQUk9EQU5MO1BBS0tFTlI7TU9UVEFLTkFWTiAg
ICAgICAgICAgICAgICAgICAgO1NPTjtMQU5ESU5HU0RBO1NBTEdTREFUTyA7TkFTSiA7UkVEU0tB
UCAgIDtGSVNLRVNMQUcgO1BSRVNFUlYgICA7VElMU1RBTkQ7U1TYUlJFTFM7S1ZBTElURVQ7TUlO
U1RFUFJJUzsgICAgICAgIFZFUkRJOyAgICAgS1ZBTlRVTTsgICAgUlVORFZFS1QgICAgDQotLS0t
LS0tLS0tLS0tLS0tLS0tLTstLS0tLTstLS0tLS0tOy0tLS0tLS07LS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tOy0tLTstLS0tLS0tLS0tOy0tLS0tLS0tLS07LS0tLS07LS0tLS0tLS0tLTst
LS0tLS0tLS0tOy0tLS0tLS0tLS07LS0tLS0tLS07LS0tLS0tLS07LS0tLS0tLS07LS0tLS0tLS0t
LTstLS0tLS0tLS0tLS0tOy0tLS0tLS0tLS0tLTstLS0tLS0tLS0tLS0gICAgDQpMb3JlbnR6ZW4g
....

Для тех, кого интересует ответ, а не (бывшая) награда, больше подсказок.

Gmail возвращает короткое значение в ответ на RFC822.SIZE, что может привести к усечению сообщений. (Они отключены на один байт для каждой строки заголовка, по-видимому, нет подсчет двух символов для CR/LF.)

Author: Elzo Valugi, 2011-03-16

5 answers

Я думаю, что вы ищете не в том месте.

Сервер imap выдает вам усеченное почтовое сообщение, а затем возвращает его строку состояния TAG5 OK Success.

Я не понимаю, как ваша (/php) обработка сокета приведет к исчезновению потока на несколько кб, чтобы волшебным образом исправить поток прямо перед этой строкой состояния.

Таким образом, либо сообщение усекается само по себе (вы проверили содержимое сообщения каким-либо другим способом?), либо сервер imap просто сломанный.

Первое, что я бы сделал, это:

  • найдите достаточно тихую среду для размещения вашего проекта, где вы можете strace -f -s 10240 -p <pid> процесс apache для проверки взаимодействия сокетов (при условии, что среда linux/apache)
  • и/или: использовать tcpdump, ethereal или эквивалент, чтобы проверить, что поступает на линию

Я предполагаю, что вы увидите точно такие же усеченные строки, поступающие по проводу. Это означает, что вы можете переключить свое внимание на imap сервер.

Убеждение себя в том, что вы ищете в нужном месте, может сэкономить много времени.

 5
Author: mvds, 2011-03-25 21:17:58

1: попробуйте удалить @ для большей детализации

2: попробуйте использовать http://www.php.net/manual/en/function .fread.php вместо fgets

Это может иметь какое-то отношение к серверу IMAP, потому что я вижу TAG5 OK Success как ответ, даже если его там не должно быть.

 2
Author: Quamis, 2011-03-25 12:40:26

Вы пробовали выдавать другие fgets и посмотреть, получите ли вы остальные данные? Возможно, вы получаете электронное письмо, состоящее из нескольких частей, для которого потребуется несколько запросов.

Но, несмотря на это, вы используете функции, предназначенные для доступа к файлам в сети. Обычно это работает нормально, но в зависимости от сети могут возникнуть проблемы. Например, вы можете использовать file_get_contents для извлечения веб-страницы. Но если проблема вызывает перенаправление, то она завершается неудачей. Но использование curl будет намного больше успешно.

Если вы действительно хотите прочитать сетевой сокет, вам следует попробовать socket_read. Это разработано с учетом сети, как curl.

 0
Author: Brent Baisley, 2011-03-20 00:51:18

Не знаю Zend и совсем забыл о PHP, но раньше играл с MIME и HTTP (C++).

Я предлагаю вам начать искать способ добавления записи заголовка длиной содержимого . Это дает подсказку "декодеру/загрузчику сообщений" ожидать определенного размера содержимого (полезной нагрузки сообщения). (Не уверен, что IMAP делает это)

В приведенном выше коде я бы попытался убедить fgets считывать определенный объем ожидаемых данных из сети. Возможно, данные буферизованы или еще не отправлено по сети (асинхронная связь), и fgets считывает только внутренний буфер, останавливаясь, таким образом, до того, как было прочитано все сообщение.

  • Чтобы убедиться, так ли это, отправьте небольшое сообщение, которое подпадает под ваш "критический момент 584".
  • Выполните трассировку сети, чтобы увидеть, действительно ли все данные передаются. (Вам, вероятно, потребуется выполнить некоторую локальную настройку)

Код, на который вы ссылаетесь, находится здесь?

 0
Author: Derick Schoonbee, 2011-03-20 01:35:57

Скорее всего, одно из ваших серверных устройств скомпрометировано, и поэтому вы хотите полностью изменить его или просто заменить модули оперативной памяти или дисководы. У меня есть некоторый опыт работы с кодировкой на основе Интернета и почты, и я могу подтвердить вам, что строка в кодировке base64 очень безопасна. По крайней мере, он использует алгоритм отображения текстур.

 0
Author: Bytemain, 2011-03-25 10:38:32