Парсинг тела письма

1,414 views
Skip to first unread message

Andrew Djoga

unread,
Feb 2, 2011, 7:48:12 AM2/2/11
to RubyOnRails to russian
Всем привет.

Занимаюсь приемом почты и возник вопрос про парсинг тела письма.
На сайте есть система комментариев с уведомлениеми на почту.
Пользователь может сделать reply со своего почтового клиента для
ответа.

Как я понял, то стандартизации в оформлении тела письма клиентами при
ответе нет. И каждый это делат по-своему.
http://stackoverflow.com/questions/2424382/parsing-email-text-reply-forward

Большинство клиентов (gmail, hotmail, mac mail) в ответе формируют
сначала тект (сам ответ) в plain text, а затем каждый городит свою
html разметку с ответом и самим сообщением. На сайте мне нужно
показывать только сам ответ.

Так вот, мне бы вполне хватило plain text'а (т.е. до первого html
тега), но есть Hotmail. Из списков и прочего он оставляет лишь текст
для этого самого plain text, когда gmail и компания делают что-то
вроде "1. First item /n 2. Second item /n". Т.е. нет никакого
форматирования у Hotmail'а в plain text секции.

Оставлять html мне не очень хочется, так как приходится вырезать само
письмо, на который был ответ.

Может кто-то занимался подобным и поделится опытом?

Alex L. Demidov

unread,
Feb 2, 2011, 10:11:36 AM2/2/11
to ror...@googlegroups.com
On Wed, Feb 02, 2011 at 04:48:12AM -0800, Andrew Djoga wrote:
> Всем привет.
>
> Занимаюсь приемом почты и возник вопрос про парсинг тела письма.
> На сайте есть система комментариев с уведомлениеми на почту.
> Пользователь может сделать reply со своего почтового клиента для
> ответа.
>
> Как я понял, то стандартизации в оформлении тела письма клиентами при
> ответе нет. И каждый это делат по-своему.
> http://stackoverflow.com/questions/2424382/parsing-email-text-reply-forward
>
> Большинство клиентов (gmail, hotmail, mac mail) в ответе формируют
> сначала тект (сам ответ) в plain text, а затем каждый городит свою
> html разметку с ответом и самим сообщением.

Мне думается что вы тут что-то путаете. То ли две части с форматами
text/plain и text/html в multipart/alternative письме, то ли вас
вводит в заблуждение тот факт, что если в основном тексте письме (по
вашей терминологии, в "ответе") пользователь не использовал никакой
Rich Text разметки, то и в тексте ее не будет. Если же пользователь
вставит в самое начало своего ответа ссылку - то в text/html уже
вполне себе будет <a href=""> в самом начале.

> На сайте мне нужно показывать только сам ответ.

Т.е. вам нужно отделить где в теле письма идет цитата и удалить ее?
Во-первых, если присылаемая в письме информация хоть сколько-нибудь
важна, то совсем удалять ее чревато - пользователи, бывает, вставляя
свой ответ inline в цитату, умудряются сбить разметку, в результате
их текст выглядит как цитата. Лучше сделать как в gmail - цитата по
умолчанию скрыта, но ее можно при желании посмотреть.

> Так вот, мне бы вполне хватило plain text'а (т.е. до первого html
> тега), но есть Hotmail. Из списков и прочего он оставляет лишь текст
> для этого самого plain text, когда gmail и компания делают что-то
> вроде "1. First item /n 2. Second item /n". Т.е. нет никакого
> форматирования у Hotmail'а в plain text секции.
>
> Оставлять html мне не очень хочется, так как приходится вырезать само
> письмо, на который был ответ.

Во-первых, убирайте всю HTML разметку полюбому, иначе словите XSS.
Во-вторых, если в письме есть text/plain часть, то парсить ее
намного проще. Если у вас есть текст на который пользователь
отвечает - то для определения где идет цитата можно воспользоваться
diff'ом. Если нет - то только по разметке. Если письма, на которые
отвечают пользователи, генерируются вами - то можно чуть-чуть
упростить себе жизнь вставляя в них строчку вроде следующего
(навеяно только что пришедшим тикетом с bitbuket'а):

--- please reply above this line ---

--
Alex L. Demidov (ALD9-RIPE).
http://alexeydemidov.com/
Freelance Consulting.

Max Lapshin

unread,
Feb 2, 2011, 10:15:09 AM2/2/11
to ror...@googlegroups.com
Если хочется автоматизировать сохранение Reply, то насколько я понял,
единственный разумный способ, это «отвечайте ниже этой линии»

Выкусить разметку чрезвычайно сложно.

Igor Stepin

unread,
Feb 2, 2011, 10:26:08 AM2/2/11
to ror...@googlegroups.com
Пример реализации в teambox:
http://blog.teambox.com/handling-incoming-email/
https://github.com/teambox/teambox/blob/master/app/controllers/hooks_controller.rb

Если внешний сервис неприемлим (проблемы с выделением бюджета под
него, например), то они же раньше использовали крон-таск:
https://github.com/teambox/teambox/blob/master/lib/tasks/mail.rake
https://github.com/teambox/teambox/blob/master/lib/teambox.rb
https://github.com/teambox/teambox/blob/master/app/models/emailer/incoming.rb

2 февраля 2011 г. 15:48 пользователь Andrew Djoga
<andrew...@gmail.com> написал:

> --
> --
> Данное сообщение отправлено Вам, так как Вы являетесь подписчиком группы "RubyOnRails to russian" на группах Google.
> FAQ группы находится по адресу: http://ru.wikibooks.org/wiki/RubyFAQ
>
>  Для того, чтобы отправить сообщение в эту группу, пошлите его по адресу
> ror...@googlegroups.com
>  Чтобы отменить подписку на эту группу, отправьте сообщение по адресу: ror2ru-un...@googlegroups.com
>  Дополнительные варианты находятся на странице группы http://groups.google.com/group/ror2ru?hl=ru

Igor Stepin

unread,
Feb 2, 2011, 10:33:27 AM2/2/11
to ror...@googlegroups.com
Само преобразование html в plain-text не такое уж и простое, если
действительно нужно. Можно было бы попробовать прикрутить браузерный
движок. Или самому библиотеку парсинга потихоньку писать (html ->
correct html -> dom2text), если качество в начале не критично
(наверняка много разных краевых случаев будет).

2 февраля 2011 г. 15:48 пользователь Andrew Djoga
<andrew...@gmail.com> написал:

Andrew

unread,
Feb 2, 2011, 11:04:59 AM2/2/11
to ror...@googlegroups.com
2011/2/2 Alex L. Demidov <alexey...@gmail.com>

Лучше сделать как в gmail - цитата по
умолчанию скрыта, но ее можно при желании посмотреть.

Каким образом вы определите где цитата? Каждый почтовый клиент обворачивает ее по-своему.
  
Во-первых, убирайте всю HTML разметку полюбому, иначе словите XSS.

Так санитайзеры же есть.
 
Если письма, на которые
отвечают пользователи, генерируются вами - то можно чуть-чуть
упростить себе жизнь вставляя в них строчку вроде следующего
(навеяно только что пришедшим тикетом с bitbuket'а):

--- please reply above this line ---


Да, хорошая идея.  Вот этим и воспользуюсь. Всем спасибо!

Alexander Simonov

unread,
Feb 3, 2011, 4:50:00 AM2/3/11
to ror...@googlegroups.com
хм... а как в Basecamp работает тогда?
я просто делаю reply, пишу текст и всё
как они там делают я хз, но работает с любым клиентом, которые у меня были - Apple Mail, Thunderbird, MS Outlook(насчет Express незнаю, не проверял).
Alexander Simonov
asim...@gmail.com



Alexey Kovyrin

unread,
Feb 3, 2011, 4:53:19 AM2/3/11
to ror...@googlegroups.com
Когда-то приходилось столкнуться, делали тупо:
1) определяли чем было написано мыло
2) выбирали соответствующий парсер, который умел распарсить дефолтный квотинг
3) если не получалось, пробовали пару стандартных вариантов со всякими
эвристиками
4) не получалось и тогда - грустили

2011/2/3 Alexander Simonov <asim...@gmail.com>:

> --
> --
> Данное сообщение отправлено Вам, так как Вы являетесь подписчиком группы "RubyOnRails to russian" на группах Google.
> FAQ группы находится по адресу: http://ru.wikibooks.org/wiki/RubyFAQ
>
>  Для того, чтобы отправить сообщение в эту группу, пошлите его по адресу
> ror...@googlegroups.com
>  Чтобы отменить подписку на эту группу, отправьте сообщение по адресу: ror2ru-un...@googlegroups.com
>  Дополнительные варианты находятся на странице группы http://groups.google.com/group/ror2ru?hl=ru

--
Alexey Kovyrin
http://kovyrin.net/

Alex L. Demidov

unread,
Feb 3, 2011, 6:43:25 AM2/3/11
to ror...@googlegroups.com
On Wed, Feb 02, 2011 at 06:04:59PM +0200, Andrew wrote:
> 2011/2/2 Alex L. Demidov <alexey...@gmail.com>
> >
> >
> > Лучше сделать как в gmail - цитата по
> > умолчанию скрыта, но ее можно при желании посмотреть.
>
>
> Каким образом вы определите где цитата? Каждый почтовый клиент обворачивает
> ее по-своему.

В text/plain большинство MUA используют для цитирования символ
угловой скобки или &gt; (">") с небольшими вариациями, от него и
пляшите. Если уж очень хочется парсить text/html, то наверное
придется рисовать XPath выражения для каждого MUA. Муторно конечно,
но количество MUA не превышает нескольких десятков и все зависит от
вашего бюджета и доступного времени, хотя за вечер это сделать точно
не получиться.

>
>
> > Во-первых, убирайте всю HTML разметку полюбому, иначе словите XSS.
> >
>
> Так санитайзеры же есть.

А что по вашему санитайзеры делают, как не убирают HTML разметку?
Только делать это надежнее сразу в том месте, где потенциально
опасный контент входит в систему, а не во view.

Alex L. Demidov

unread,
Feb 3, 2011, 6:45:31 AM2/3/11
to ror...@googlegroups.com
On Wed, Feb 02, 2011 at 06:33:27PM +0300, Igor Stepin wrote:
> Само преобразование html в plain-text не такое уж и простое, если
> действительно нужно. Можно было бы попробовать прикрутить браузерный
> движок. Или самому библиотеку парсинга потихоньку писать (html ->
> correct html -> dom2text), если качество в начале не критично
> (наверняка много разных краевых случаев будет).

В случае почтовых сообщений text/plain обычно уже присутствует
наряду с text/html. Письма html only встречаются достаточно редко
даже в спаме. Для преобразования text/html в text/plain достаточно
пострипать html тэги, поскольку в text/plain вы все равно никакой
разметки (цвет, размер шрифта и т.д.) не сохраните, кроме переводов
строк. Зачем для этого нужен браузерный движок я, честно говоря, не
понимаю.

Victor Ilyukevich

unread,
Feb 3, 2011, 6:51:47 AM2/3/11
to ror...@googlegroups.com
кстати как вариант можно посмотреть реализацию в teambox. Там есть в конфиге опция allow_incoming_email (https://github.com/teambox/teambox#L76). И вот по коду я бы поискал упоминания этой переменной и посмотрел бы как там реализованно.

2011/2/3 Alex L. Demidov <alexey...@gmail.com>
--
--
Данное сообщение отправлено Вам, так как Вы являетесь подписчиком группы "RubyOnRails to russian" на группах Google.
FAQ группы находится по адресу: http://ru.wikibooks.org/wiki/RubyFAQ

 Для того, чтобы отправить сообщение в эту группу, пошлите его по адресу
ror...@googlegroups.com
 Чтобы отменить подписку на эту группу, отправьте сообщение по адресу: ror2ru-un...@googlegroups.com
 Дополнительные варианты находятся на странице группы http://groups.google.com/group/ror2ru?hl=ru



--
Виктор Ильюкевич
http://bestblog.name

Andrew

unread,
Feb 3, 2011, 7:25:37 AM2/3/11
to ror...@googlegroups.com
Спасибо, посмотрел, также делают через "REPLY ABOVE THIS LINE TO POST AN ANSWER".


2011/2/3 Victor Ilyukevich <ilyukevi...@gmail.com>

Andrew

unread,
Feb 3, 2011, 7:36:23 AM2/3/11
to ror...@googlegroups.com
2011/2/3 Alex L. Demidov <alexey...@gmail.com>
> > Во-первых, убирайте всю HTML разметку полюбому, иначе словите XSS.
> >
>
> Так санитайзеры же есть.

А что по вашему санитайзеры делают, как не убирают HTML разметку?

Могут оставлять разрешенные теги/атрибуты и избавлять от XSS.

Alex L. Demidov

unread,
Feb 3, 2011, 9:02:13 AM2/3/11
to ror...@googlegroups.com

Рельсовый sanitize не гарантирует избавления от XSS, он прямо
декларирует что он делает лишь "best effort". Чем больше вы
тегов/атрибутов оставляете, тем больше возможностей протащить что-то
нехорошее. Так же совершенно нет гарантии что санированный html будет
well-formed, т.е. могут просто испортить верстку каким-нибудь
допустимым, но незакрытым тегом.

Maxim Filatov

unread,
Mar 17, 2011, 5:45:53 AM3/17/11
to ror...@googlegroups.com
On 02/02/2011 03:48 PM, Andrew Djoga wrote:
> Может кто-то занимался подобным и поделится опытом?
GitHub'овцы вот вроде занялись:

https://github.com/github/email_reply_parser


--
Best regards,
Maxim Filatov

Reply all
Reply to author
Forward
0 new messages