Я угадывая, вы пытаетесь сказать, есть два типа входящих сообщений. Один выглядит примерно так:
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, но они не склонны уменьшать сложность, просто перетасовывают ее.
Ваш вопрос и заголовок говорит, что вы хотите извлечь тело и вложение, но код, который вы показываете, не пытается сделать что-либо подобное. Вам следовало бы включить простое примерное сообщение, которое не ведет себя так, как вы ожидаете, а также показать нам, что именно вы пытаетесь извлечь. – tripleee
Кроме того, почему вы ожидаете (почти) того же регулярного выражения, чтобы он не соответствовал одному и тому же тексту? – tripleee
Как уже указывалось ранее (последняя часть) моего ответа на ваш предыдущий почти идентичный вопрос http://stackoverflow.com/a/32733374/874188 объясняет, как найти, когда вложение закодировано в base64 и как тогда декодировать извлеченный текст. – tripleee