Вложения электронной почты Base64 не загружаются

Я использую следующий скрипт http://stuporglue.org/recieve-e-mail-and-save-attachments-with-a-php-script/ для обработки моих сообщений, которые отправляются мне, однако кажется, что пользователь отправляет электронное письмо с почтой или Outlook или любым почтовым клиентом, который отправляет вложения base64, которые они не сохраняют в базе данных, а основной текст сообщения также пропускается.

Мне интересно, если кто-нибудь видит ошибку в коде, поскольку я смотрел и не вижу ничего, что торчит.

более пристальный взгляд показывает следующее Mail.app отправляет его base64, как это.

--Apple-Mail=_9E76B10A-4086-43B8-B835-78F184FA43FC Content-Disposition: inline; filename=CV-IT.pdf Content-Type: application/pdf; name="CV-IT.pdf" Content-Transfer-Encoding: base64 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 1NVM1hk3kE1G3rlPZKL2CeZ+Hdp 

а Gmail отправляет его так.

 Content-Type: application/pdf; name="CV-IT.pdf" Content-Disposition: attachment; filename="CV-IT.pdf" Content-Transfer-Encoding: base64 X-Attachment-Id: f_gx86pbon0 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 1NVM1hk3kE1G3rlPZKL2CeZ+Hdp 

Вложение gmail сохраняется, а mail.app – нет.

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

Есть две основные проблемы.

Проблема 1: разделение строк заголовка

Посмотрите на эти заголовки:

 Content-Disposition: inline; filename=CV-IT.pdf Content-Type: application/pdf; name="CV-IT.pdf" 

против

 Content-Type: application/pdf; name="CV-IT.pdf" Content-Disposition: attachment; filename="CV-IT.pdf" 

Теперь рассмотрим ту часть, которая обрабатывает эти строки:

 $info = split("\n",$parts[0]); .. foreach($info as $line) { if( preg_match("/Content-Type: (.*);/",$line,$matches) ) { $type = $matches[1]; } if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/", $line,$matches) ) { $name = time() . "_" . $matches[1]; } .. } 

Это разбивает заголовок в строках, а затем пытается сопоставить каждую строку. Теперь посмотрим на два заголовка. Вторая (рабочая) имеет 2 строки, которые отлично совпадают.

Первый (не работает) имеет 4 (!) Строки. Ни одна из этих 4 строк не соответствует шаблонам.

Есть бесчисленные способы решения этой проблемы, и я возьму быстрый и грязный oneliner. Добавьте эту строку до $info = split("\n",$parts[0]);

 $parts[0] = preg_replace("/\r?\n\s+/"," ",$parts[0]); 

он снова превратит разделенные заголовки в oneliners, ища новые строки, за которыми следуют пробелы, и заменяя их одним пробелом.

Проблема 2: неправильная схема

Предполагая, что вы применили исправление выше, у вас есть этот шаблон:

 if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/", ... 

пытаясь сопоставить эту строку:

 Content-Disposition: inline; filename=CV-IT.pdf 

Здесь две ошибки:

проблема 2a: расположение inline / attachment

Образец явно ищет слово «привязанность», в то время как строка говорит «inline». Это фиксируется путем замены attachment (attachment|inline) , что указывает на альтернативу. (обратите внимание, что это также фиксирует тип расположения)

проблема 2b: двойные кавычки имени файла

Далее шаблон ищет filename="(.*)" , А строка имеет имя файла без кавычек.

Это также не является серьезной проблемой, если вы вставляете ? после " , чтобы указать, что " является обязательным, все будет работать ». Чтобы сделать его идеальным, вы также должны убедиться, что . не будет соответствовать окончанию " если доступно, поэтому замените filename="(.*)" на:

 filename="?([^"]+)"? 

где [^"]+ обозначает« ничего, кроме " .

Поэтому, если вы измените эти строки:

 if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/", $line,$matches) ) { $name = time() . "_" . $matches[1]; } 

в

 if( preg_match('/Content-Disposition: (attachment|inline); filename="?([^"]*)"?/', $line,$matches) ) { $disposition = $matches[1]; $name = time() . "_" . $matches[2]; } 

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

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

Проблема в том, что мой скрипт не ищет встроенный контент, только для прикрепленного контента. С тем, как вы прикрепляете файл, он является встроенным, следовательно,

Content-Disposition: inline; имя_файла = CV-IT.pdf

Если вы прикрепляете его, вместо этого вы увидите Content-Disposition: attachment; имя файла = "CV-IT.pdf"

Обработка Content-Disposition находится вокруг строки 54-64 скрипта на моем сайте (связанного в исходном вопросе).

кажется, вы использовали preg_match, чтобы получить границу почты рядом с строкой 166:

 if (preg_match("/boundary=(.*boundary)$/",$line,$matches)){ $boundary = $matches[1]; 

Вы использовали символ «/» в качестве разделителя шаблона регулярного выражения, и одновременно у вас есть «/» в вашем граничном содержимом.

Поэтому это может быть причиной того, что ваш код не работает.

Попробуй это:

 if (preg_match("{boundary=(.*boundary)$}",$line,$matches)){ $boundary = $matches[1];