2015-06-17 8 views
32

Plötzlich haben wir den obigen Fehler erhalten, ohne dass irgendwelche Änderungen am Skript vorgenommen wurden.Fehler mit PHP mail(): Mehrere oder fehlerhafte Zeilenumbrüche gefunden in additional_header

Host ist 1und1 (ich weiß ...)

Das Skript arbeitet immer noch gut auf einem anderen Server, und so ist mein Verdacht, dass es muss eine Serverkonfiguration ändern gewesen, die dazu geführt hat, obwohl die Gastgeber plädieren Ignoranz.

Es gibt keine Informationen zu dem obigen Fehler in Google, die ich finden kann - hat jemand irgendwelche Ideen? Server läuft Apache, wenn das hilft.

+0

Wo ist Ihr E-Mail-Funktionscode? – Bruce

Antwort

50

Hatte nur das ähnliche Problem.
Es kam aus heiterem Himmel. Kein PHP-Code wurde geändert.

Was wurde geändert: PHP wurde 5.5.25-1 auf 5.5.26 aktualisiert.

Ein Sicherheitsrisiko in PHP mail() Funktion wurde behoben und zusätzliche Zeilenumbrüche in additional_headers sind nicht mehr erlaubt. Weil zusätzliche Zeilenumbrüche bedeuten: jetzt startet die E-Mail-Nachricht (und wir wollen sicher nicht, dass jemand Zeilenumbrüche über Header einfügt, gefolgt von einer bösen Nachricht).

Was zuvor gut geklappt hat, z.B. Nur zusätzliche Zeilenumbrüche nach den Headern oder sogar die gesamte Nachricht an additional_headers übergeben, funktioniert nicht mehr.

Lösung:

  • Sanitize Ihre Header. Keine mehrfache Zeilenumbrüche in additional_headers Argument. Diese zählen als "mehrfache oder fehlerhaft formatierte Zeilenumbrüche": \r\r, \r\0, \r\n\r\n, \n\n, \n\0.
  • Verwenden Sie additional_headers nur für Header. E-Mail-Nachricht (mehrteilig oder nicht, mit ir ohne Anhänge usw.) gehört in message Argument, nicht in Kopfzeilen.

PHP Sicherheit Bugreport: https://bugs.php.net/bug.php?id=68776
C-Code diff wie sein Fest: http://git.php.net/?p=php-src.git;a=blobdiff;f=ext/standard/mail.c;h=448013a472a3466245e64b1cb37a9d1b0f7c007e;hp=1ebc8fecb7ef4c266a341cdc701f0686d6482242;hb=9d168b863e007c4e15ebe4d2eecabdf8b0582e30;hpb=eee8b6c33fc968ef8c496db8fb54e8c9d9d5a8f9

+0

Ich hatte ein zusätzliches abschließendes \ n am Ende meiner zusätzlichen Header ... das Entfernen des Problems löste das Problem . – Yorick

+1

Große Antwort. Leider verwendet ein alter Code \ n \ n in mehrteiligen Mails in zusätzlichen Headern. Könnte jemand eine Lösung für diese Situation bieten? – SteAp

0

Dies ist möglicherweise jemand versucht, nutzen Sie Ihren Code zu injizieren E-Mail-Header.

http://resources.infosecinstitute.com/email-injection/

Ich möchte Sie Zugriffsprotokolle usw. untersuchen vorschlagen und für ungewöhnliche Aktivitäten suchen. Die Tatsache, dass Sie Fehlermeldungen erhalten, bedeutet hoffentlich, dass Ihr Skript nicht kompromittiert wurde und stattdessen ein Fehler auftritt. Sie müssen jedoch sicherstellen, dass.

11

Hatte das gleiche Problem: Entfernte die Mime Grenze und Nachricht aus der Kopfzeile und alles funktionierte.

$header = "From: ".$from_name." <".$from_mail.">\n"; 
    $header .= "Reply-To: ".$replyto."\n"; 
    $header .= "MIME-Version: 1.0\n"; 
    $header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"\n\n"; 
    $emessage= "--".$uid."\n"; 
    $emessage.= "Content-type:text/plain; charset=iso-8859-1\n"; 
    $emessage.= "Content-Transfer-Encoding: 7bit\n\n"; 
    $emessage .= $message."\n\n"; 
    $emessage.= "--".$uid."\n"; 
    $emessage .= "Content-Type: application/octet-stream; name=\"".$filename."\"\n"; // use different content types here 
    $emessage .= "Content-Transfer-Encoding: base64\n"; 
    $emessage .= "Content-Disposition: attachment; filename=\"".$filename."\"\n\n"; 
    $emessage .= $content."\n\n"; 
    $emessage .= "--".$uid."--"; 
    mail($mailto,$subject,$emessage,$header); 
+0

Dies wurde von Fixed-Fehler # 68776 erstellt (Mail (Mail hat keine Header-Injektion Verhinderung für zusätzliche Header). – Frank

+1

Das funktioniert, aber Mail wird nicht als HTML gesendet. HTML-Tags werden so wie sie sind in der Mail angezeigt. Irgendeine Lösungsmöglichkeit? –

+0

@SunishMenon - Ich benutze - $ Header. = 'Content-Type: Text/HTML; Zeichensatz = ISO-8859-1 '. "\ r \ n"; $ headers. = 'Content-Transfer-Encoding: 8bit'. "\ n \ r \ n"; Sehen Sie meine Antwort unter – Atara

2

Ein weiteres Szenario, das die gleichen neuen Fehler bringt, ist, wenn Sie keine Header an den „mail“ Befehl senden. Früher verwendete es nur einen Standard und gibt nun den irreführenden Fehler: "Mehrere oder falsch formatierte Zeilenumbrüche in additional_header".

Kann durch Zugabe dieses Problem behoben werden:

$header = "From: ".$from_name." <".$from_mail.">\n"; 
$header .= "Reply-To: ".$replyto."\n"; 
$header .= "MIME-Version: 1.0\n"; 

... 

mail($mailto,$subject,$emessage,$header); 
1

Sie in Bug #69874 Can't set empty additional_headers for mail() laufen können, wenn Sie nicht dumm etwas getan haben (das heißt die Header zu sanieren vergessen).

-Test für den Bug

$ php -d display_errors=1 -d display_startup_errors=1 -d error_reporting=30719 -r 'mail("[email protected]","Subject Here", "Message Here",NULL);' 

Warning: mail(): Multiple or malformed newlines found in additional_header in Command line code on line 1 

Alternativ, wenn Sie wissen, Ihre PHP-Version (Hinweis: php -v) Sie the changelog für die Fehlernummer überprüfen (69.874), um zu sehen, ob the fix hat für Ihre Version angewendet.

Eine kurzfristige Lösung ist, um Anrufe an mail() wie diese

function fix_mail( $to , $subject , $message , $additional_headers =NULL, $additional_parameters=NULL) { 
      $to=filter_var($to, FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES| FILTER_FLAG_STRIP_LOW| FILTER_FLAG_STRIP_HIGH); 
      $subject=filter_var($subject, FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES| FILTER_FLAG_STRIP_LOW| FILTER_FLAG_STRIP_HIGH);    

      if (!$additional_headers) 
        return mail( $to , $subject , $message); 

      if (!$additional_parameters) 
        return mail( $to , $subject , $message , $additional_headers); 

      return mail( $to , $subject , $message , $additional_headers, $additional_parameters); 
    } 
5

Keine der oben Genannten ersetzen regeln es für mich - Hauptsache ist, dass Sie nicht etwas anderes als Header-Definitionen in Header setzen müssen. In alten Skripten war alles drin. Verschieben Sie also alle Texte oder Anhänge, die in Kopfzeilen eingefügt wurden, in den Nachrichtentext. Das macht Sinn ..

Dies hat explanation
(Ich denke, es gleiche Lösung wie Frank ist oben plus Davisca der „keine Doppel neuen Linien“ - aber Sie Notwendigkeit verdoppelt neue Linien für Anhänge)

2

meine PHP-Version - 5.4.43, enthält wahrscheinlich den Fehler # 68776.

auf den gleichen Fehler googeln zeigte [http://fossies.org/diffs/php/5.4.42_vs_5.4.43/ext/standard/mail.c-diff.html]

=> Ich kann keine leeren Zeichenfolgen als E-Mail() Parameter verwenden.

mein alter Code:

$headers = 'From: ' . $frm . "\r\n"; 
$headers .= 'To: ' . $contactEmail . "\r\n"; 
if ($flag) { 
    $headers .= 'To: ' . $contactEmail2 . "\r\n"; 
} 
$headers .= 'Cc: ' . $contactEmailCc . "\r\n"; 
$headers .= 'Bcc: ' . $contactEmailBcc . "\r\n"; 
$headers .= 'Return-Path: ' . $frm . "\r\n"; 
$headers .= 'MIME-Version: 1.0' ."\r\n"; 
$headers .= 'Content-Type: text/HTML; charset=ISO-8859-1' . "\r\n"; 
$headers .= 'Content-Transfer-Encoding: 8bit'. "\n\r\n"; 

$headers .= $htmlText . "\r\n"; 

if (!mail('', $strSubject, '', $headers)) { // !!! note the empty parameters. 

mein neuer Code:

$headers = 'From: ' . $frm . "\r\n"; 
// note: no "To: " !!! 
$headers .= 'Cc: ' . $contactEmailCc . "\r\n"; 
$headers .= 'Bcc: ' . $contactEmailBcc . "\r\n"; 
$headers .= 'Return-Path: ' . $frm . "\r\n"; 
$headers .= 'MIME-Version: 1.0' ."\r\n"; 
$headers .= 'Content-Type: text/HTML; charset=ISO-8859-1' . "\r\n"; 
$headers .= 'Content-Transfer-Encoding: 8bit'. "\n\r\n"; 
// note: no $htmlText !!! 

// note: new parameters: 
$mTo = $contactEmail; 
if ($flag) { 
    $mTo .= ', ' . $contactEmail2; 
} 

$mMessage .= $htmlText . "\r\n"; 

if (!mail($mTo, $strSubject, $mMessage, $headers)) { 
+0

siehe auch https://bugs.php.net/bug.php?id=69874 – Atara

35

Keine der oben genannten Antworten für mich dieses Problem gelöst. Also, ich erweiterte meine Suche auf "Mail mit Anhang und HTML-Nachrichten Probleme." Ich habe Informationen aus ein paar verschiedenen Posts zusammengetragen und das ist mir eingefallen. Es ermöglicht BEIDE HTML-E-Mail und einen Anhang.

Mein ursprünglicher Header-Code:

$header = "From: ".$from_name." <".$from_mail.">\r\n"; 
$header .= "Reply-To: ".$replyto."\r\n"; 
$header .= "MIME-Version: 1.0\r\n"; 
$header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"\r\n"; 
$header .= "--".$uid."\r\n"; 
$header .= "Content-Type: text/html; charset=ISO-8859-1\r\n"; 
$header .= "Content-Transfer-Encoding: 8bit\r\n"; 
$header .= $body."\r\n"; 
$header .= "--".$uid."\r\n"; 
$header .= "Content-Type: application/pdf; name=\"".$filename."\"\r\n"; 
$header .= "Content-Transfer-Encoding: base64\r\n"; 
$header .= "Content-Disposition: attachment; filename=\"".$filename."\"\r\n"; 
$header .= $content."\r\n"; 
$header .= "--".$uid."--"; 

if (mail($mail_to, $subject, "", $header)) 
{ 
    return "mail_success"; 
} 
else 
{ 
    return "mail_error"; 
} 

Mein neuer Code (gesamt): Beachten Sie, dass $ Körper die HTML ist, die durch eine andere Funktion zusammengesetzt wird.

$file = $path.$filename; 
$file_size = filesize($file); 
$handle = fopen($file, "r"); 
$content = fread($handle, $file_size); 
fclose($handle); 

$content = chunk_split(base64_encode($content)); 
$uid = md5(uniqid(time())); 
$name = basename($file); 

$eol = PHP_EOL; 

// Basic headers 
$header = "From: ".$from_name." <".$from_mail.">".$eol; 
$header .= "Reply-To: ".$replyto.$eol; 
$header .= "MIME-Version: 1.0\r\n"; 
$header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\""; 

// Put everything else in $message 
$message = "--".$uid.$eol; 
$message .= "Content-Type: text/html; charset=ISO-8859-1".$eol; 
$message .= "Content-Transfer-Encoding: 8bit".$eol.$eol; 
$message .= $body.$eol; 
$message .= "--".$uid.$eol; 
$message .= "Content-Type: application/pdf; name=\"".$filename."\"".$eol; 
$message .= "Content-Transfer-Encoding: base64".$eol; 
$message .= "Content-Disposition: attachment; filename=\"".$filename."\"".$eol; 
$message .= $content.$eol; 
$message .= "--".$uid."--"; 

if (mail($mail_to, $subject, $message, $header)) 
{ 
    return "mail_success"; 
} 
else 
{ 
    return "mail_error"; 
} 

Zwei wichtige Änderungen hier. (1) entfernte alle mehrteiligen Sachen aus den Headern in $ message. (2) entfernte alle "\ r \ n" Sachen und fügte $eol = PHP_EOL; dem Code hinzu.

Zusammen haben diese Änderungen mir erlaubt, erneut HTML-E-Mail mit Anhängen zu senden.

+1

Das funktionierte, aber ich habe Probleme beim Senden mehrerer Anhänge – RedRory

+4

Vorsicht, vor dem Inhalt müssen Sie eine Newline (Zeilenumbrüche nach dem letzten Header) haben sollte es sein ... $ Nachricht. = "Content-Disposition: Anlage; Dateiname = \" ". $ Dateiname." \ "". $ Eol. $ Eol; $ message. = $ Content. $ Eol; –

+0

Es hat mein Problem gelöst, aber können Sie mir für mehrere Anhänge helfen? –

2

Dies wird Ihr Problem lösen. Ich habe ein bisschen Franks Code geändert. Dieser Code unterstützt Anhang und HTML.

<?php 

$filename = "certificate.jpg"; 
$path  = "/home/omnibl/subdomains/test/certificate/certimage/"; 
$file  = $path . $filename; 
$file_size = filesize($file); 
$handle = fopen($file, "r"); 
$content = fread($handle, $file_size); 
fclose($handle); 

$content = chunk_split(base64_encode($content)); 
$uid  = md5(uniqid(time())); 
$name = basename($file); 

$eol  = PHP_EOL; 
$subject = "Mail Out Certificate"; 
$message = '<h1>Hi i m mashpy</h1>'; 

$from_name = "[email protected]"; 
$from_mail = "[email protected]"; 
$replyto = "[email protected]"; 
$mailto = "[email protected]"; 
$header = "From: " . $from_name . " <" . $from_mail . ">\n"; 
$header .= "Reply-To: " . $replyto . "\n"; 
$header .= "MIME-Version: 1.0\n"; 
$header .= "Content-Type: multipart/mixed; boundary=\"" . $uid . "\"\n\n"; 
$emessage = "--" . $uid . "\n"; 
$emessage .= "Content-type:text/html; charset=iso-8859-1\n"; 
$emessage .= "Content-Transfer-Encoding: 7bit\n\n"; 
$emessage .= $message . "\n\n"; 
$emessage .= "--" . $uid . "\n"; 
$emessage .= "Content-Type: application/octet-stream; name=\"" . $filename . "\"\n"; // use different content types here 
$emessage .= "Content-Transfer-Encoding: base64\n"; 
$emessage .= "Content-Disposition: attachment; filename=\"" . $filename . "\"\n\n"; 
$emessage .= $content . "\n\n"; 
$emessage .= "--" . $uid . "--"; 
mail($mailto, $subject, $emessage, $header); 
+1

Großartig ... musste nur in einer PHP-Migration von 5.4.32 auf 5.4.40 beheben – GeorgeKaf