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 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用
  • ¥15 C++ yoloV5改写遇到的问题
  • ¥20 win11修改中文用户名路径
  • ¥15 win2012磁盘空间不足,c盘正常,d盘无法写入
  • ¥15 用土力学知识进行土坡稳定性分析与挡土墙设计
  • ¥70 PlayWright在Java上连接CDP关联本地Chrome启动失败,貌似是Windows端口转发问题
  • ¥15 帮我写一个c++工程
  • ¥30 Eclipse官网打不开,官网首页进不去,显示无法访问此页面,求解决方法
  • ¥15 关于smbclient 库的使用