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.