2016-03-30 3 views
0

Я пытаюсь извлечь сообщение ПЗУ из нескольких частей электронной почты тела или от привязанности, поэтому я использовал: 0B попробовать каждый вариант, как следующее:Как извлечь тело письма и вложение

msgID="" 

#extract message in the attachment if it's plain text 
:0B 
* ^Content-Disposition: *attachment.*(($)[a-z0-9].*)*($)($)\/[a-z0-9+]+=* 
{msgID="$MATCH"} 

#extract message in the body if it's there 
:0EB 
* ^()\/[a-z]+[0-9]+[^\+] 
{msgID = "$MATCH"} 

Но MsgID получил то же сообщение из тела, которое было встроенным кодом изображения, что с ним не так, кто знает лучшее условие для его фильтрации?

Я также должен обнаружить, если подзаголовок в теле текста и в кодировке base64, а затем расшифровать его, как оговорить его с регулярным выражением:

:0B 
* ^Content-Type:text/html; 
* ^Content-Location:text_0.txt 
* ^Content-Transfer-Encoding:base64 
* ^Content-Disposition: *attachment.*(($)[a-z0-9].*)*($)($)\/[a-z0-9+]+=* 
{ msgID= msgId =`printf '%s' "$MATCH" | base64 -d` } 

Он всегда жалуется не матч: ^Content-Type:text/html;

+0

Ваш вопрос и заголовок говорит, что вы хотите извлечь тело и вложение, но код, который вы показываете, не пытается сделать что-либо подобное. Вам следовало бы включить простое примерное сообщение, которое не ведет себя так, как вы ожидаете, а также показать нам, что именно вы пытаетесь извлечь. – tripleee

+0

Кроме того, почему вы ожидаете (почти) того же регулярного выражения, чтобы он не соответствовал одному и тому же тексту? – tripleee

+0

Как уже указывалось ранее (последняя часть) моего ответа на ваш предыдущий почти идентичный вопрос http://stackoverflow.com/a/32733374/874188 объясняет, как найти, когда вложение закодировано в base64 и как тогда декодировать извлеченный текст. – tripleee

ответ

1

Я угадывая, вы пытаетесь сказать, есть два типа входящих сообщений. Один выглядит примерно так:

From: Sender <[email protected]> 
To: You <[email protected]> 
Subject: plain text 

ohmigod0 

И другой сложный MIME многочастному с тем же содержанием:

From: Sender <[email protected]> 
To: Amy X <[email protected]> 
Subject: MIME complexity 
MIME-Version: 1.0 
Content-Type: multipart/related; boundary=12345 

--12345 
Content-type: text/plain; charset="us-ascii" 
Content-transfer-encoding: base64 
Content-disposition: attachment; filename="text_0.txt" 
Content-location: text_0.txt 

b2htaWdvZDA= 
--12345-- 

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

# extract message in the attachment if this is a MIME message 
:0B 
* ^Content-Disposition: *attachment.*(($)[a-z0-9].*)*($))($)\/[a-z0-9+]+=* 
{ msgID="$MATCH" } # hafta have spaces inside the braces 

:0EB # else, do this: assume the first non-empty body line is msgID 
* ^()\/[a-z]+[0-9]+[^\+] 
{ msgID="$MATCH" } # still need spaces inside braces; 
# ... and, as pointed out many times before, cannot have spaces 
# around the equals sign 

Регулярное выражение для крепления является упрощением, но я уже показал вам, как справиться со сложной MIME сообщения в a previous question of yours - если у вас есть несколько случаев (например, в кодировке base64 вложения, или просто приложение с открытым текстом или без MIME), я бы упорядочил их из более сложных (что означает больше функций в регулярном выражении) и последовательно отпадает назад к более простым регулярным выражениям с более высокой вероятностью ложных срабатываний. Вы можете цепочки :0E («else») до тех пор, пока вам нравится - если регулярное выражение успешно выполнено, а следующие рецепты - :0E рецепты, все они будут пропущены.


В ответ на ваше обновление есть две проблемы с вашей попыткой. Во-первых, как вы заметили, первое регулярное выражение не совпадает. У вас нет места после двоеточия, и я предполагаю, что в сообщении, которое вы сопоставляете, есть одно. Вам нужно понять, что каждый символ в регулярном выражении должен точно соответствовать, за исключением метасимволов регулярных выражений, которые имеют особое значение. Вы, как правило, увидеть что-то подобное во многих рецептах Procmail:

* ^Content-Type:[ ]*text/html; 

где пространство между квадратными скобками является пространством и вкладка. Класс символов (материал в квадратных скобках) соответствует одному символу один раз, а звездочка * говорит, чтобы повторить этот шаблон ноль или более раз. Это позволяет произвольное расстояние после двоеточия. Квадратные скобки и звезда являются метасимволами. (Это очень простой материал, который должен быть в любом представлении Procmail, которое вы, возможно, читали.)

Другая проблема заключается в том, что каждое регулярное выражение применяется изолированно. Итак, ваш рецепт говорит, если заголовок Content-Type появляется в любом месте в теле, а заголовок Content-Location появляется где-нибудь еще (как правило, в другом заголовке MIME где-то) и т. Д.Другими словами, ваш рецепт очень подвержен ложным срабатываниям. Вот почему правило, предложенное мной ранее, является настолько сложным: он ищет эти заголовки последовательно, в одном блоке, то есть в одном заголовке MIME (хотя нет ничего, чтобы действительно убедиться, что контекст равен a MIME заголовок части тела, еще немного по этому поводу).

Потому что мы хотим, чтобы гарантировать, что есть четыре различных заголовков, в любом порядке, регулярное выражение для этого будет огромно: ABCD|ACDB|ACDB|ABDC|ADCB|BACD|... где А регулярное выражение Content-Type заголовка, B является Content-Location регулярными выражениями и т.д. Вы можете обмануть a бит бит и создайте одно регулярное выражение, которое соответствует последовательности из четырех совпадений того же заголовка, определяющего заголовок - это вряд ли вызовет ложные срабатывания (нет разумной причины иметь две копии одного и того же заголовка) и значительно упрощает код, хотя он все еще сложный. Обратите внимание: мы хотим создать одно регулярное выражение, которое соответствует любому из этих четырех заголовков.

^Content-(Type:[ ]text/plain;|\ 
      Location:[ ]*text_0\.txt|\ 
      Transfer-Encoding:[ ]*base64|\ 
      Disposition:[  ]*attachment) 

... после чего любого заголовка, повторяется четыре раза, после чего части MIME тела (который вы имели после заголовка Content-Disposition, немного из контекста, но не сам по себе неправильно).

(Ваш код имеет text/html но если вложение не HTML, как это было предложено формат и имя файла, он должен быть text/plain, так что я буду с этим вместо этого.)

Перед тем, как пойти туда , Я укажу, что синтаксический анализ MIME в Procmail не выполняется много, именно потому, что он стремится взорваться в чрезвычайно сложные регулярные выражения. MIME имеет множество опций, и вам нужно, чтобы каждое регулярное выражение позволяло упускать или включать каждый необязательный элемент. Существуют опции для кодирования вещей (base64 или quoted-printable или вообще не закодированы) и варианты включения или исключения кавычек вокруг многих элементов и варианты использования многостраничного сообщения с одной или несколькими частями тела или просто поместить данные в тело, как и в моем сконструированном первом примере сообщения (которое по-прежнему технически является MIME-сообщением, его подразумеваемый тип содержимого - text/plain; charset="us-ascii", а кодировка передачи содержимого по умолчанию - 7bit, что, как оказалось, обычно является тем, что должно было появляться до того, как MIME всегда должен был выглядеть).

Так что, если вы не в этом, потому что (а) вы действительно, действительно хотите, чтобы узнать самые глубокие тайны Procmail или (б) вы на очень ограниченной системе, в которой есть, потому есть ничего другого вы не можете использовать, я бы всерьез предполагал, что вы переходите на язык с правильным MIME-парсером. Скрипт Python, который декодирует это, будет всего полдюжины строк или около того, и вы получите все нормализованное и красивое декодирование для вас, не нуждаясь в том, чтобы вы изобретали декодирование с котируемым типом или трансляцию набора символов. (Вы можете по-прежнему вызывать скрипт Python из Procmail, если хотите.)

Я также укажу здесь, что правильный MIME-анализатор будет извлекать параметр boundary= из заголовков верхнего уровня в многостраничном сообщении и убедиться, что любое совпадение на заголовках частей тела происходит сразу после разделителя границ. Следующий код Procmail этого не делает, поэтому мы можем получить ложный результат, если сообщение содержит совпадение где-то еще, чем в заголовках части тела MIME (например, если сообщение bounce содержит фрагмент заголовков MIME отскок сообщения, в этом случае вы хотели бы, чтобы рецепт не совпал, но он будет).

:0B 
* ^(Content-(Type:[  ]text/plain;|\ 
      Location:[ ]*text_0\.txt|\ 
      Transfer-Encoding:[ ]*base64|\ 
      Disposition:[  ]*attachment).*(($)[a-z0-9].*)*)($)\ 
    (Content-(Type:[ ]text/plain;|\ 
      Location:[ ]*text_0\.txt|\ 
      Transfer-Encoding:[ ]*base64|\ 
      Disposition:[  ]*attachment).*(($)[a-z0-9].*)*)($)\ 
    (Content-(Type:[ ]text/plain;|\ 
      Location:[ ]*text_0\.txt|\ 
      Transfer-Encoding:[ ]*base64|\ 
      Disposition:[  ]*attachment).*(($)[a-z0-9].*)*)($)\ 
    (Content-(Type:[ ]text/plain;|\ 
      Location:[ ]*text_0\.txt|\ 
      Transfer-Encoding:[ ]*base64|\ 
      Disposition:[  ]*attachment).*(($)[a-z0-9].*)*)($)\ 
    ($)\/[a-z0-9/+]+=* 
{ msgid=`printf '%s' "$MATCH" | base64 -d` } 

:0BE 
* ^^\/[a-z]+[0-9]*[^\+] 
{ msgid="$MATCH" } 

(К сожалению, механизм регулярных выражений Procmail в не оператор {4} повторения, так что мы должны повторить регулярное выражение буквально четыре раза!)

Как было отмечено ранее, Procmail, к сожалению, не знает ничего о MIME. Что касается Procmail, то заголовки верхнего уровня являются заголовками, а все остальное - телом. Были попытки написать MIME-библиотеки или расширения для Procmail, но они не склонны уменьшать сложность, просто перетасовывают ее.

+0

Спасибо! Как определить привязанность к кодировке base64? СМОТРИТЕ измененную запись. Я думаю, лучше отфильтровать его на *^Content-Type: text/html, затем в следующем *^..., но я никогда не передаю первое условие для типа содержимого, а также регулярное выражение, которое вы мне давали с четырьмя строками. @tripleee –

Смежные вопросы