douzhaocheng4533 2015-01-29 17:09
浏览 25
已采纳

如何调试(貌似)错误的SwiftMailer附件?

I'm having a bit of a problem with trying to figure out what and where exactly goes wrong in my app.

What I'm trying to do is upload a file through form <input type="file"> field. Then the file is being base64 encoded and attached to the mail.

Symptoms:

The attached file is shown in the mail but trying to open it results in "File is not .pdf or is corrupt" error and is unreadable.

Additional information:

Attachmeant as appears in the mail (using pdf as sample, it properly displays file types for png and others too):

--_=_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_=_--

Encoding method:

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;
}

How the attachments are being constructed within the mail (initial part):

    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);
        }
    }

Some things I tried:

What's the most baffling is the fact that md5 hash over the encoded file contents is different between what's being sent and what's being received.

I really can't seem to find a place where the file contents could be malformed or corrupted. Could it be the fact that I'm trying to send them over SSL? Going through the SwiftMailer code doesn't reveal anything specific, it would only do something with the file contents if it were an instance of Swift_OutputByteStream (but it's a string).

Regular text files are opened no problem but their content is base64encoded (which rised my suspicion that somewhere along the way the file is being encoded twice, but I can't find it anywhere). Images and pdf files aren't opened at all.

Would be really thankful if someone pointed me in the right direction (I guess it's something completely banal, I always waste the most time on banal things). I'll provide any additional information as required.

Edit:

The solution was fairly simple (as Marc B pointed out). All I had to do was stop using the superfluous wrappers around the SwiftMailer put in the project by previous maintainers and revert back to calling its classes directly.

  • 写回答

1条回答 默认 最新

  • dsbruqxgt820011351 2015-01-29 17:20
    关注

    Yes. You're doing it all wrong. There is NO need to do your own base64 encoding and whatnot. Literally all you'd need is (split into multiple lines for legibility):

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

    That's the whole point of Swiftmailer and PHPMailer - they do all the heavy work and you just act like the boss: "go there, do this, let me take all the credit".

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 MATLAB动图问题
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名