LINUX.ORG.RU

Жесть какая-то с почтой. Дальше не знаю, куда копать.

 , , ,


0

1

Задача: почтовая рассылка. Юникод, html+text, PHP. Используется давно проверенный PEAR Mail. Всё прекрасно работает не один год. И вдруг, начинаются жалобы подписчиков с mail.ru на тему «проблемы с кодировкой».

Начинаю разбираться. Действительно, проблемы. После долгой серии экспериментов выясняется, что Mail.ru перестал корректно отрабатывать Content-Type boundary, разделитель блоков в Mime-письме. После ещё серии экспериментов становится ясно, что стандартная форма с многострочным заголовком вида:

Content-Type: multipart/alternative;
 boundary="=_a31d5f9813b277cf61cb88c8fd2adf70"
на Mail.Ru почему-то режется на две строки:
Content-Type: multipart/alternative;

 boundary="=_a31d5f9813b277cf61cb88c8fd2adf70"
Понятно, что после этого всё, начиная с boundary, считается текстом письма. Ну а письмо идёт в юникоде, чарсет запрятан внутри, MailRu для писем без чарсета показывает кои8-р, отсюда ещё и кодировка кривая выходит. Не считая мусора в виде заголовков и html-блока.

Ну, как это дело обойти я не придумал, так что для Mail.Ru просто запретил html, оставив отсылку одного текста, письмо уже не Mime, показывается как надо.

Прошло неделя или две. Вчера делал небольшую внутреннюю рассылку и... опаньки! на @gmail.com вижу мусор с заголовками. С кодировкой всё ок, но мусор... Сперва ассоциация не возникла. Но начал копать глубже — блин, те же симптомы. Только режется теперь многострочник не в content-type, а в subject:

Subject: =?utf-8?B?W9Cc0JDQotCkXSDQldC20LXQtNC90LXQstC90YvQuSDQvtGC0Yc=?=
 =?utf-8?B?0ZHRgiDQt9CwIDI2INCw0L/RgNC10LvRjyAyMDEyINCz0L7QtNCw?=
в
Subject: =?utf-8?B?W9Cc0JDQotCkXSDQldC20LXQtNC90LXQstC90YvQuSDQvtGC0Yc=?=

 =?utf-8?B?0ZHRgiDQt9CwIDI2INCw0L/RgNC10LvRjyAyMDEyINCz0L7QtNCw?=

Чего только не предпринимал... Пока не понял, что если отправить Subject одной строкой, то всё равно порежется на Content-Type, как и ранее на Mail.Ru.

Теперь — барабанная дробь. Ну, то что на локалхосте почта принимается нормально или на @yandex.ru всё пучком — это не интересно. Вот только на GMail.com у меня хостится ещё свой домен. Так вот, например, на balancer@мой-домен-на-gmail.ru приходит мусор. Но один раз сегодня(!) в серии экспериментов письмо прошло в нормальном виде. А на subscribes@мой-домен-на-gmail.ru почта приходит по-прежнему, как и раньше, замечательно.

Такое впечатление, что на Mail.Ru, а теперь и на Gmail (но поэтапно и не на всех серверах) обновляют какой-то софт, который так вот режет по какому-то критерию многострочные заголовки.

Я, прямо, в растерянности.

Никто не сталкивался?

Вот типичный пример «проблемного» полного заголовка:

Return-Path: <balancer@www.aviaport.ru>
X-Original-To: balancer@www.airbase.ru
Delivered-To: balancer@www.airbase.ru
Received: from www.aviaport.ru (unknown [89.108.119.77])
    by www.airbase.ru (Postfix) with ESMTP id E9A9AACEED
    for <balancer@www.airbase.ru>; Fri, 27 Apr 2012 08:10:59 +0400 (MSK)
Received: by www.aviaport.ru (Postfix, from userid 1000)
    id E10DEC06; Fri, 27 Apr 2012 08:10:59 +0400 (MSK)
To: balancer@www.airbase.ru
Subject: =?utf-8?B?W9Cc0JDQotCkXSDQldC20LXQtNC90LXQstC90YvQuSDQvtGC0Yc=?=
 =?utf-8?B?0ZHRgiDQt9CwIDI2INCw0L/RgNC10LvRjyAyMDEyINCz0L7QtNCw?=
X-PHP-Originating-Script: 1000:mail.php
MIME-Version: 1.0
Content-Type: multipart/alternative;
 boundary="=_3ed319f250e0ab88e7dcb38313768187"
From: =?utf-8?B?QXZpYVBvcnQuUnU=?= <list@aviaport.ru>
Message-Id: <20120427041059.E10DEC06@www.aviaport.ru>
Date: Fri, 27 Apr 2012 08:10:59 +0400 (MSK)

--=_3ed319f250e0ab88e7dcb38313768187
Content-Transfer-Encoding: 8bit
Content-Type: text/plain; charset=utf-8

[МАТФ] Ежедневный отчёт за 26 апреля 2012 года
====================================================

Персоны
------------------------------------------------------------
 - Добавлено за сутки: 53
 - Обновлено за сутки: 2

...

Вариаций много пробовал, но всё без толку...

Вот пример «убитого» заголовка на gmail:

Delivered-To: balancer@balancer.ru
Received: by 10.229.45.212 with SMTP id g20csp17644qcf;
        Thu, 26 Apr 2012 20:39:53 -0700 (PDT)
Received: by 10.112.49.131 with SMTP id u3mr5031337lbn.14.1335497993524;
        Thu, 26 Apr 2012 20:39:53 -0700 (PDT)
Return-Path: <balancer@www.aviaport.ru>
Received: from www.aviaport.ru ([89.108.119.77])
        by mx.google.com with ESMTP id r7si1541855lbk.31.2012.04.26.20.39.52;
        Thu, 26 Apr 2012 20:39:53 -0700 (PDT)
Received-SPF: neutral (google.com: 89.108.119.77 is neither permitted nor denied by best guess record for domain of balancer@www.aviaport.ru) client-ip=89.108.119.77;
Authentication-Results: mx.google.com; spf=neutral (google.com: 89.108.119.77 is neither permitted nor denied by best guess record for domain of balancer@www.aviaport.ru) smtp.mail=balancer@www.aviaport.ru
Date: Thu, 26 Apr 2012 20:39:53 -0700 (PDT)
Message-Id: <4f9a1509.c727700a.0ddf.ffffc025SMTPIN_ADDED@mx.google.com>
Received: by www.aviaport.ru (Postfix, from userid 1000)
	id B35DEB9B; Fri, 27 Apr 2012 07:39:52 +0400 (MSK)
To: balancer@balancer.ru
Subject: =?utf-8?B?W9Cc0JDQotCkXSDQldC20LXQtNC90LXQstC90YvQuSDQvtGC0Yc=?=

 =?utf-8?B?0ZHRgiDQt9CwIDI2INCw0L/RgNC10LvRjyAyMDEyINCz0L7QtNCw?=
X-PHP-Originating-Script: 1000:mail.php
MIME-Version: 1.0
Content-Type: multipart/alternative;

 boundary="=_44ee5bffb4ef21f7478791b24d9331a4"
From: =?utf-8?B?QXZpYVBvcnQuUnU=?= <list@aviaport.ru>
Message-Id: <20120427033952.B35DEB9B@www.aviaport.ru>
Date: Fri, 27 Apr 2012 07:39:52 +0400 (MSK)

--=_44ee5bffb4ef21f7478791b24d9331a4

Content-Transfer-Encoding: 8bit

Content-Type: text/plain; charset=utf-8

....

★★★★★

у меня не хотело отправлять / принемать с мейлру моя китайская почта.

GNU-Ubuntu1204LTS ★★★ ()
Ответ на: комментарий от GNU-Ubuntu1204LTS

ещё кто-то юзает мейлру?

Пока проблемы были только у них, меня это не сильно беспокоило. А вот gmail — это уже куда хуже.

KRoN73 ★★★★★ ()
Ответ на: комментарий от KRoN73

И, главное, это похоже на обновление какого-то серверного ПО. И не факт, что не вылезет со временем и на других серверах.

Да, проблема именно на уровне сервера, а не клиента. Убитое письмо читается одинаково криво и через web-клиент, и удалённо. То есть коцается оно при обработке во время приёма.

KRoN73 ★★★★★ ()

куда копать.

В поддержку обращался?

Думаю они заинтересованы в том что бы твоя почта ходила через них.

sin_a ★★★★★ ()
Ответ на: комментарий от KRoN73

Тебе не показалось, что бьются строки, у которых строка продолжения начинается не с табуляции?

ABW ★★★★ ()
Ответ на: комментарий от sin_a

В поддержку обращался?

Нет пока. Нет чётких доказательств, что на нашей стороне всё хорошо.

Забавно, только что шеф отписал, что рассылка с баннерной системы пришла вдруг тоже битой. А это уже система не наша, обычный OpenX. И шлёт почту не через PEAR Mail, а прямо через php-шную функцию mail().

Нужно ещё проверить, как с этим делом с других машин дело обстоит. Во время экспериментов с Mail.Ru у меня возникло смутное, возможно и неверное, конечно, предположение, что заголовки письма в каких-то случаях антивирусный серверный софт у них портит.

KRoN73 ★★★★★ ()
Ответ на: комментарий от ABW

Тебе не показалось, что бьются строки, у которых строка продолжения начинается не с табуляции?

Нет. В первой серии экспериментов все варианты перепробовал, даже хотел упростить процедуру, отсылая готовое письмо в сыром виде: Как отправить готовое письмо в формате maildir?

Как так отсылать не придумал, так что ковырялся прямо в PEAR_Mail библиотеках, меняя форматы отступа, вид самого делимитера и т.п.

Увы, ничего не помогало.

Более того, отсылал на Mail.Ru тогда почту с аттачами для тестов из Opera, Thunderbird, Gmail и смотрел заголовки — они достаточно разнообразны (в т.ч. по формату отступа, по формату разделителей), но показываются корректно. Разницы со своими письмами так и не нашёл :) Нужно бы научиться отсылать сырой raw-формат (скажем, готовое письмо из Оперы самому перепослать), но с сокетами возиться ломало, а готового решения не нашёл.

KRoN73 ★★★★★ ()

на Mail.Ru почему-то режется на две строки:

А какие там переносы изначально? Может проблема в том, что заголовок формируется с переносом в виде \r\n, вместо одного \n? А mail.ru «поправили» парсер, отсюда и проблема?

andreyu ★★★★★ ()
Ответ на: комментарий от andreyu

Штатно идёт \n, но я пробовал и \r\n посылать на всякий случай. Пофиг :) Да и режет именно вторую строку многострочного параметра.

И, как теперь выяснилось, уже не только в одной моей библиотеке.

KRoN73 ★★★★★ ()
Ответ на: комментарий от KRoN73

А что на выходе библиотеки? Хотелось бы посмотреть на это дело в hex.

andreyu ★★★★★ ()
Ответ на: комментарий от andreyu

А что на выходе библиотеки?

Ну, она потом всё равно не RAW шлёт, а php-функцию Mail дёргает. Или прямо sendmail. В обоих варианта одно и то же выходит. Ещё вариант с прямым соединением на SMTP есть, его не пробовал.

А что получает сервер без искажений — я шапку одного письма выше привёл. Это с моего сервера, где голый postfix.

Хотелось бы посмотреть на это дело в hex

Чистый utf-8, переводы строк юниксовые, управляющих символов нет.

KRoN73 ★★★★★ ()
Ответ на: комментарий от KRoN73

Вот это странно. У меня пока идей нет. Решите проблему, поделитесь инфой.

andreyu ★★★★★ ()
Ответ на: комментарий от KRoN73

Я бы советовал сделать дамп tcp-трафика и в нём посмотреть что именно передаётся серверу Gmail. Смотреть не всё письмо, а строку «Subject», может там в конце пробелы или ещё что.

tcpdump это хлопотно, но тогда хотя бы будет чёткая уверенность в том, что передаётся SMTP-серверу. Postfix, вроде, может записать письмо немного «причесав» заголовки.

mky ★★★★★ ()
Ответ на: комментарий от mky

Смотреть не всё письмо, а строку «Subject», может там в конце пробелы или ещё что.

Ну так пробелы в конце по RFC не запрещены, вроде.

Но тоже надо попробовать будет.

KRoN73 ★★★★★ ()
Ответ на: комментарий от KRoN73

Нет, пробелы не запрещены. Но с другой стороны, у вас в Subject'е письма стоят «Encoded-Word» (RFC 2047), там написано, что они не более 75 символов и делятся последовательностью «CRLF SPACE», и не уточняется, допустима ли там последовательность FWS (Folding white space из rfc 2822).

mky ★★★★★ ()

Похоже, всё-таки, эпидемия :D

Сейчас мне в ящик свалились два письма-нотификации от post-tracker.ru с той самой характерной ошибкой. До вчерашнего дня всё ходило нормально :) Правда, ошибка в коде имеет иной вид:

Delivered-To: balancer@balancer.ru
Received: by 10.229.45.212 with SMTP id g20csp58426qcf;
        Fri, 27 Apr 2012 12:05:50 -0700 (PDT)
Received: by 10.152.162.68 with SMTP id xy4mr12555693lab.49.1335553549757;
        Fri, 27 Apr 2012 12:05:49 -0700 (PDT)
Return-Path: <www-data@server.alexxnb.ru>
Received: from server (server.alexxnb.ru. [93.190.202.42])
        by mx.google.com with ESMTP id j10si4368732lbg.77.2012.04.27.12.05.49;
        Fri, 27 Apr 2012 12:05:49 -0700 (PDT)
Received-SPF: pass (google.com: best guess record for domain of www-data@server.alexxnb.ru designates 93.190.202.42 as permitted sender) client-ip=93.190.202.42;
Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of www-data@server.alexxnb.ru designates 93.190.202.42 as permitted sender) smtp.mail=www-data@server.alexxnb.ru
Date: Fri, 27 Apr 2012 12:05:49 -0700 (PDT)
Message-Id: <4f9aee0d.4a1a700a.5665.2d00SMTPIN_ADDED@mx.google.com>
Received: by server (Postfix, from userid 33)
	id D93CA683396; Fri, 27 Apr 2012 23:05:33 +0400 (MSK)
To: balancer@balancer.ru
Subject: =?UTF-8?B?UkMwNTY0MzU3MzdISzogMjcuMDQuMjAxMiDQktGA0YPRh9C10L3QuNC1INCw0LTRgNC10YHQsNGC0YMgKNCc0J7QodCa0JLQkCAzMTUp=?=
X-PHP-Originating-Script: 1001:class_mail.php
Content-type: text/plain; charset=UTF-8

From: "=?UTF-8?B?UG9zdC1UcmFja2VyLnJ1=?=" <no-reply@post-tracker.ru>
Message-Id: <20120427190533.D93CA683396@server>
Date: Fri, 27 Apr 2012 23:05:33 +0400 (MSK)

Здравствуйте!
...

Т.е. тут пустое поле влезло между двумя обычными строками. Ну и, соответствено, это «From» лезет уже в тексте письма.

KRoN73 ★★★★★ ()

Всё, докопался до сути.

В общем, если вызывать конструктор PERA Main_mime без параметров, он начинает разделять строки не через \n, а через \r\n. Хотя параметры друг от друга отделяет автодетектируя текущу систему.

Обычно UNIX-мейлеры, как я понял, просто тупо выкидывают \r, поэтому всё работает нормально. А в maildir на своём хосте полученное письмо падает уже с \n вместо \r\n, потому всё выглядит без лишних символов.

А вот с некоторых пор, сперва Mail.Ru, а теперь, видимо, и Google, стали переходить на что-то, что \r воспринимает как обычный перевод строки, т.е. \r\n превращается в двойной перевод строки.

В общем, конструктор вызывать теперь нужно явно указывая тип перевода строк:

$mime = new Mail_mime("\n");

У себя-то уже исправил, но в массе сторонних PHP-решений этот момент теперь ещё долго будет позволять любоваться письмами с кусками хедера в изуродованном теле письма. На западных форумах народ тоже уже задаётся этим вопросом, например: http://www.linode.com/forums/viewtopic.php?p=50146

Будьте внимательны :)

KRoN73 ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.