如何调试(看似)有问题的 SwiftMailer 附件?

How to debug (seemingly) faulty SwiftMailer attachments?

我在尝试找出我的应用中究竟出了什么问题以及哪里出了问题时遇到了一些问题。

我想做的是通过表单 <input type="file"> 字段上传文件。然后文件被base64编码并附加到邮件中。

症状:

附件已显示在邮件中,但尝试打开它会导致 "File is not .pdf or is corrupt" 错误且无法读取。

附加信息:

邮件中显示的附件(使用 pdf 作为示例,它也正确显示 png 和其他文件类型):

--_=_swift_v4_1422542740_8140c03155128cd497227873a9a9d98c_=_
Content-Type: application/pdf; name=sample.pdf
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=sample.pdf

// chunk of base64

--_=_swift_v4_1422542740_8140c03155128cd497227873a9a9d98c_=_--

编码方式:

public function encode_attachments($files) // $files = $_FILES
{
    $attachments = array();
    $legal_files = array('input', 'ids');
    $msg = array(
        1 => "The uploaded file exceeds the upload_max_filesize directive in php.ini",
        2 => "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form",
        3 => "The uploaded file was only partially uploaded",
        4 => "No file was uploaded",
        6 => "Missing a temporary folder"
    );

    foreach ($legal_files as $file) {
        if (isset($files[$file]) && !empty($files[$file]['tmp_name'])) {
            // get file details we need
            $file_tmp_name = $files[$file]['tmp_name'];
            $file_name = $files[$file]['name'];
            $file_size = $files[$file]['size'];
            $file_error = $files[$file]['error'];

            if ($file_error > 0) {
                throw new Exception($msg[$file_error]);
            } else {
                // read from the uploaded file & base64_encode content for the mail
                $handle = fopen($file_tmp_name, 'r');
                $content = fread($handle, $file_size);

                fclose($handle);

                $encoded_content = chunk_split(base64_encode($content));
                // now we know we have the file contents for attachment
                $attachments[$file_name] = $encoded_content;
            }
        }
    }

    return $attachments;
}

如何在邮件中构建附件(初始部分):

    if (isset($this->attachments) && is_array($this->attachments) && !empty($this->attachments)) {
        foreach ($this->attachments as $file_name => $file_content) {
            $mime_type = File::mime_by_ext(pathinfo($file_name, PATHINFO_EXTENSION));
            $attachment = Swift_Attachment::newInstance($file_content, $file_name, $mime_type ? $mime_type : "text/html");

            // Attach it to the message
            $message->attach($attachment);
        }
    }

我试过的一些东西:

最令人困惑的是,对编码文件内容的 md5 散列在发送的内容和接收的内容之间是不同的。

我真的找不到文件内容可能变形或损坏的地方。难道是我试图通过 SSL 发送它们吗?通过 SwiftMailer 代码并没有透露任何具体内容,如果它是 Swift_OutputByteStream 的实例(但它是一个字符串),它只会对文件内容做一些事情。

常规文本文件打开没有问题,但它们的内容是 base64 编码的(这让我怀疑文件在某个地方被编码了两次,但我无法在任何地方找到它)。图片和pdf文件根本打不开。

如果有人为我指明了正确的方向,我将非常感激(我想这是完全平庸的事情,我总是在平庸的事情上浪费最多的时间)。我会根据需要提供任何其他信息。

编辑:

解决方案相当简单(正如 Marc B 指出的那样)。我所要做的就是停止使用以前的维护者在项目中放置的 SwiftMailer 周围多余的包装器,并恢复为直接调用它的 类。

是的。你做错了。有 NO 需要做你自己的 base64 编码等等。从字面上看,您只需要(为了便于阅读,分成多行):

$swift
  ->attach(Swift_Attachment::fromPath($_FILES['foo']['tmp_name'])
  ->setFilename('Name you want to appear in the email.pdf');

这就是 Swiftmailer 和 PHPMailer 的全部意义所在 - 它们完成了所有繁重的工作,而您只是像老板一样行事:"go there, do this, let me take all the credit"。