附带文件的PHP电子邮件始终为41B且无法正常工作:

时间:2014-08-31 09:25:32

标签: php email attachment

每当我发送附带附件的电子邮件时,该文件为41B且无效。怎么解决?我试过jpeg和zip,一切都是一样的。该文件的名称和扩展名为41B,无法打开。

这是我的代码:

if($_POST){
    $email_exp = '/^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/';
    if(!empty($_POST['author']) && preg_match($email_exp,($_POST['email']))){
        $mail_to = "example@example.com";
        $from_mail = $_POST['email'];
        $from_name = $_POST['author'];
        $reply_to = "reply@example.com";
        $subject = "Subject";
        $boundary = md5(uniqid(time()));
        $message = "<html><head></head><body>Author: ".$_POST['author']."<br >E-mail: ".$_POST['email']."</body></html>";

        //Set e-mail headers
        $headers = "From: ".$from_name."<".$from_mail.">\r\n";
        $headers .= "Reply-To: ".$reply_to."\r\n";
        $headers .= "MIME-Version: 1.0\r\n";

        $headers .= "Content-Type: multipart/mixed;\r\nboundary=\"".$boundary."\"\r\n";
        $headers .= "This is a multi-part message in MIME format.\r\n";
        $headers .= "--".$boundary."\r\n";

        $headers .= "Content-type:text/html; charset=UTF-8\r\n";
        $headers .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
        $headers .= "$message\r\n";
        $headers .= "--".$boundary."\r\n";

        if(!empty($_FILES['picture1']['name']) || !empty($_FILES['picture2']['name']) || !empty($_FILES['picture3']['name']) || !empty($_FILES['picture4']['name']) || !empty($_FILES['picture5']['name'])){
            $file = array($_FILES['picture1']['tmp_name'], $_FILES['picture1']['name'], $_FILES['picture1']['size'],$_FILES['picture2']['tmp_name'], 
            $_FILES['picture2']['name'],$_FILES['picture2']['size'], $_FILES['picture3']['tmp_name'], $_FILES['picture3']['name'], $_FILES['picture3']['size'], 
            $_FILES['picture4']['tmp_name'], $_FILES['picture4']['name'], $_FILES['picture4']['size'], $_FILES['picture5']['tmp_name'], 
            $_FILES['picture5']['name'], $_FILES['picture5']['size']);
            for($i=0;$i<15;$i+=3){
                if(!empty($file[$i])){
                    $headers .= "Content-Type: application/xml;\r\n name=\"".$file[$i+1]."\"\r\n";
                    $headers .= "Content-Transfer-Encoding: base64\r\n";
                    $headers .= "Content-Disposition: attachment;\r\n filename=\"".$file[$i+1]."\"\r\n";
                    $cnt = $file[$i].$file[$i+2];
                    $content = chunk_split(base64_encode($cnt));
                    $headers .= "\r\n".$content."\r\n";
                    $headers .= "--".$boundary."--\r\n";
                    echo $i;
                }
            }
        }
        if(mail($mail_to, $subject, "", $headers)){
            echo 'MAIL SENT';
        }else {
            echo 'MAIL FAILED';
        }

    }else{
        echo "The fields!";
    }
}

2 个答案:

答案 0 :(得分:0)

解决方案是替换

$cnt = $file[$i].$file[$i+2];

使用:

$cnt = file_get_contents($file[$i]);

答案 1 :(得分:0)

您的代码存在许多问题:


$email_exp = '/^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/';

此正则表达式排除了许多有效的电子邮件地址,例如.museum域中的任何内容,或local-part^_^@domain.example等地址中的"^stack\ exchange$"@domain.example


$from_mail = $_POST['email'];
$from_name = $_POST['author'];
/* ... */
$headers = "From: ".$from_name."<".$from_mail.">\r\n";

您应该确保这些变量中没有控制字符(例如\r\n)。实际上,恶意用户可以轻松地注入他们自己的电子邮件标题(Bcc:或类似的)。


$message = "<html><head></head><body>Author: ".$_POST['author']."<br >E-mail: ".$_POST['email']."</body></html>";

您应该通过htmlspecialchars()运行这些$_POST变量,以防止恶意用户注入任意脚本或其选择的其他元素。


$headers .= "Content-Type: multipart/mixed;\r\nboundary=\"".$boundary."\"\r\n";

这是错误的。您不能将boundary部分放在自己的行上。如果您要打破长标题行,则必须使用Folding White Space,即CR LF SPCR LF HTAB序列("\r\n ""\r\n\t")。


$headers .= "Content-Type: multipart/mixed;\r\nboundary=\"".$boundary."\"\r\n";
$headers .= "This is a multi-part message in MIME format.\r\n";

上面的第一行是标题的结尾。第二行是邮件正文的开头。它们之间必须有一个双"\r\n"。从语义上讲,第二行的所有内容都应该通过第三个($message)参数传递给mail()mail()功能会对标题进行一些修改,这些标题可能会或可能不会干扰您的邮件正文。


$headers .= "Content-Type: application/xml;\r\n name=\"".$file[$i+1]."\"\r\n";
$headers .= "Content-Transfer-Encoding: base64\r\n";
$headers .= "Content-Disposition: attachment;\r\n filename=\"".$file[$i+1]."\"\r\n";

您可能希望确保文件名中没有双引号或控制字符。


$cnt = $file[$i].$file[$i+2];
$content = chunk_split(base64_encode($cnt));

正如您已经注意到的那样,您应该使用$cnt = file_get_contents($file[$i])。为了完整起见,我在这里提到它。


$headers .= "\r\n".$content."\r\n";
$headers .= "--".$boundary."--\r\n";

这是错误的。 "\r\n--" ... "--" close-delimiter 。您应该在每个文件部分之间使用划线边界,并在最后一部分之后使用 close-delimiter 。请参阅下面的语法部分。例如

$headers .= "$message\r\n";
/*$headers .= "--".$boundary."\r\n";*/  /* <--- */

if (!empty /* ... */) {
    $file = /* ... */;

    for($i=0;$i<15;$i+=3){
        if(!empty($file[$i])){
/* ---> */  $headers .= "\r\n--$boundary\r\n";</b>
            $headers .= "Content-Type: application/xml;\r\n name=\"".$file[$i+1]."\"\r\n";
            $headers .= "Content-Transfer-Encoding: base64\r\n";
            $headers .= "Content-Disposition: attachment;\r\n filename=\"".$file[$i+1]."\"\r\n";
            $cnt = file_get_contents ($file[$i]);
            $content = chunk_split(base64_encode($cnt));
            $headers .= "\r\n".$content;
            echo $i;
        }
    }
}
$headers .= "\r\n--$boundary--\r\n";  /* <--- */

MIME语法

根据RFC 2046,这是多部分消息体结构的摘录。(BNF语法略有简化。)

multipart-body := [preamble CRLF]
                  dash-boundary CRLF
                  body-part *encapsulation
                  close-delimiter
                  [CRLF epilogue]

dash-boundary := "--" boundary

body-part := MIME-part-headers [CRLF *OCTET]

encapsulation := delimiter
                 CRLF body-part

delimiter := CRLF dash-boundary

close-delimiter := delimiter "--"

参考