отказ от ответственности у рассматриваемого проблемного сценария есть больше проблем, на которые я не буду обращать внимание, и ответ ниже предназначен для быстрого решения данной проблемы, в то же время надеясь просветить некоторых читателей, которые не былив состоянии самостоятельно диагностировать проблемы. / disclaimer
Существуют две основные проблемы.
Проблема 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 строк не соответствует шаблонам.
Существует множество способов решения этой проблемы, и я возьму быстрый и грязный вкладыш.Добавьте эту строку перед $info = split("\n",$parts[0]);
$parts[0] = preg_replace("/\r?\n\s+/"," ",$parts[0]);
, она снова превратит разделенные заголовки в однострочные, отыскивая новые строки с последующими пробелами и заменяя их только одним пробелом.
Проблема 2: неправильный шаблон
Предполагая, что вы применили вышеуказанное исправление, у вас есть этот шаблон:
if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/", ...
, пытаясь сопоставить эту строку:
Content-Disposition: inline; filename=CV-IT.pdf
Здесь две вещи идут не так, как надо:
проблема 2a: расположение inline / attachment
Шаблон явно ищет слово «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, чтобы увидеть, чтов заголовках писем следует ожидать большего.Этот скрипт содержит много предположений, похороненных в нем.