Base64 email attachments are not uploading - php

I am using the following script http://stuporglue.org/recieve-e-mail-and-save-attachments-with-a-php-script/ to handle my emails that get sent to me, however it seems if a user sends an email from mail or outlook or any email client that sends base64 attachments they are not being saved in the data base, and the body text of the email is also skiped.
I am wondering if anyone sees an error in the code, as I have looked and dont see anything that sticks out.
a closer look shows the following
Mail.app sends its base64 like this.
--Apple-Mail=_9E76B10A-4086-43B8-B835-78F184FA43FC
Content-Disposition: inline;
filename=CV-IT.pdf
Content-Type: application/pdf;
name="CV-IT.pdf"
Content-Transfer-Encoding: base64
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
1NVM1hk3kE1G3rlPZKL2CeZ+Hdp
while Gmail sends it like this.
Content-Type: application/pdf; name="CV-IT.pdf"
Content-Disposition: attachment; filename="CV-IT.pdf"
Content-Transfer-Encoding: base64
X-Attachment-Id: f_gx86pbon0
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
1NVM1hk3kE1G3rlPZKL2CeZ+Hdp
The gmail attachment saves while the mail.app does not.

disclaimer the problematic script in question has more issues, which I will not address, and the answer below is meant as a quick fix for the problem at hand, while hoping to enlighten some readers who were not able to diagnose the problems themselves. /disclaimer
There are two main problems.
Problem 1: split header lines
Look at these headers:
Content-Disposition: inline;
filename=CV-IT.pdf
Content-Type: application/pdf;
name="CV-IT.pdf"
versus
Content-Type: application/pdf; name="CV-IT.pdf"
Content-Disposition: attachment; filename="CV-IT.pdf"
Now look at the part that processes these lines:
$info = split("\n",$parts[0]);
..
foreach($info as $line)
{
if( preg_match("/Content-Type: (.*);/",$line,$matches) )
{
$type = $matches[1];
}
if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/",
$line,$matches) ) {
$name = time() . "_" . $matches[1];
}
..
}
This splits the header in lines, and then tries to match every line. Now look at the two headers. The second (working) one has 2 lines, which are perfectly matched.
The first (not working) one has 4 (!) lines. None of these 4 lines matches the patterns.
There are countless ways of tackling this problem, and I'll take a quick&dirty oneliner. Add this line before $info = split("\n",$parts[0]);
$parts[0] = preg_replace("/\r?\n\s+/"," ",$parts[0]);
it will turn the split headers into oneliners again by looking for newlines followed by whitespace, and replacing them with just one space.
Problem 2: wrong pattern
Assuming you applied the fix above, you have this pattern:
if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/", ...
trying to match this line:
Content-Disposition: inline; filename=CV-IT.pdf
Two things go wrong here:
problem 2a: disposition inline/attachment
The pattern clearly looks for the word "attachment", while the line says "inline". This is fixed by replacing attachment by (attachment|inline), which indicates an alternative. (note that this also captures the disposition type)
problem 2b: filename double quotes
The pattern further looks for filename="(.*)", while the line has a filename without the quotes.
This is also no major issue, if you insert ? after the ", to indicate that the " is optional, all will work. To make it perfect, you must also ensure that the . will not match the ending " if available, so replace filename="(.*)" with:
filename="?([^"]+)"?
where [^"]+ stands for 'anything but "'.
So if you change these lines:
if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/",
$line,$matches) ) {
$name = time() . "_" . $matches[1];
}
into
if( preg_match('/Content-Disposition: (attachment|inline); filename="?([^"]*)"?/',
$line,$matches) ) {
$disposition = $matches[1];
$name = time() . "_" . $matches[2];
}
it should work. (note that I changed the pattern to use single quotes, so that you need not escape the double quotes, making things legible)
To make this script fool proof, you should really read the appropriate RFCs, to see what more is to be expected in email headers. This script has a lot of assumptions buried in it.

The problem is that my script is not looking for inline content, only for attached content. With the way you have attached the file, it is inline, hence the
Content-Disposition: inline;
filename=CV-IT.pdf
If you attach it, you would instead see
Content-Disposition: attachment; filename="CV-IT.pdf"
The Content-Disposition handling is around line 54-64 of the script on my site (linked in original question).

seems you used preg_match to get the boundary of the mail near line 166:
if (preg_match("/boundary=(.*boundary)$/",$line,$matches)){
$boundary = $matches[1];
You used the "/" character as delimiter of pattern of regular expression and you have the "/" in your boundary content at the same time.
So this may be the reason why your code does not work.
Try this:
if (preg_match("{boundary=(.*boundary)$}",$line,$matches)){
$boundary = $matches[1];

Related

Sending encrypted mail from php with non-ASCII Content-type

I am trying the below code to send encrypted mail where the cleartext is text/html and charset is utf-8.
For what it's worth, I cannot manage to get the mail displayed correctly (in MS Outlook).
As you may notice, I (meanwhile) try to have the relevant Content-Type: header both prepended to the data file to be encrypted and present in the headers parameter of the call to openssl_pkcs7_encrypt (and tried various other combinations as well).
While the desired content-type applies to the message when it is sent unencrypted, it simply does not work with encrypted messages. The result is always as if the "inner" Content-Type had been text/plain;charset=ascii.
I experimented with prepending the header to the data file before encryption only because I think I found some suggestion similar here on SE for a similar situation. But apparently this only makes the header line appear as part of the decrypted message (in other words, the file submitted to openssl_pkcs7_encrypt should really only be the "pure" content (as I had orginally suspected).
But having it in the headers parameter does not help, either: In the headers present in the enncryped file, there is a header added with the correct "outer" S/MIME content type, which overrides my "inner" content type given.
Question: Where and how in the combination of openssl_pkcs7_encrypt() and mail() should I specify the "inner" Content-Type of my encrypted message?
$hdr_to = implode(',',$empfaenger);
$hdr_subject = '=?UTF-8?q?' . quoted_printable_encode($subject) . '?=';
$other_headers = array(
"From" => $hdr_from,
"Content-Type" => "text/html; charset=utf-8",
"X-Mailer" => "PHP/".phpversion()
);
$mailbody = wordwrap($_REQUEST['message']);
//write msg to disk
$msg_fn = tempnam("/tmp","MSG");
$enc_fn = tempnam("/tmp","ENC");
$fp = fopen($msg_fn, "w");
fwrite($fp, 'Content-Type: ' . $other_headers['Content-Type'] . CRLF . CRLF);
fwrite($fp, $mailbody);
fclose($fp);
// Encrypt message
$enc_ok = openssl_pkcs7_encrypt($msg_fn,$enc_fn,$pubkeys,$other_headers,PKCS7_TEXT,1);
//$enc_ok = false; // for debugging: simulate encryption failure
if (!$enc_ok) {
// Will try to send unencrypted instead
} else {
// Seperate headers and body for mail()
$data = str_replace("\n",CRLF,file_get_contents($enc_fn));
$parts = explode(CRLF.CRLF, $data, 2);
$mailbody = $parts[1];
$other_headers = $parts[0];
}
// Send mail
$mail_ok = mail($hdr_to, $hdr_subject, $mailbody, $other_headers);
The problem was the PKCS7_TEXT flag given as parameter to the encryption function.
My intended media type was text/html; charset=utf-8, i.e.,
of type text
of subtype html
with parameter charset=utf-8
and superficially, the type matches what the name PKCS7_TEXT suggests. However, this flag is described as:
Adds text/plain content type headers to encrypted/signed message. If decrypting or verifying, it strips those headers from the output - if the decrypted or verified message is not of MIME type text/plain then an error will occur.
To be precise, it seems that said header and a blank line (to separate it from the message body) are prepended, which turns any previously existing header lines (Content-Type: or other) into part of the body.
So the simple solution is to not use the PKCS7_TEXT flag (unless your message is really plain ASCII² text).
² It may also be okay for latin-1 text, but I won't count on it. After all the description quoted above suggests that an error will occur; then again, UTF-8 text gets decrypted successfully (i.e., without an explicit error), but exhibits the usual codepage related display artefacts .

Generate text file with new line using PHP running in windows 2000 using mozilla version 10

I am using PHP to generate a text file that is used in a computer with windows 2000 OS and mozilla firefox browser(its old dont ask why please). The file is generate correctly and runes smoothly on windows 10 and latest version of fire fox.
My problem now is that the new line does not render in the old version(windows 2000 OS and firefox 10)
I have tried using the ff:
1. /n
2. /r/n
3. <br>
4. $string = "This\r\nis\n\ra\nstring\r"; echo nl2br($string);
5. PHP_EOL
All not generating the desired output. It is just appending the BR as text
CODE IS :
header("Content-Type: text/html; charset=UTF-8");
header("Content-Type: multipart/form-data; boundary=something");
header("Content-Length: ".strlen($data)."");
header("Content-Disposition: attachment; filename=".$_GET['name']."");
echo nl2br(base64_decode($data));
sample text is : "Assembly Lot Summary Report " . "\r\n" . "\r\n" ;
FYI : Notepad(only) is used to open the text file
if you want to have new line the same way you have in text editor when you hit enter key then the header should be:
Content-Type: text/plain
instead of
Content-Type: text/html;
so the web browser exactly knows that you want to pass a text file.
You may double check if the new line is returned to the browser by just examining the page source - go to meun > edit > view source or hit CTR+U
I would also try to remove this line:
header("Content-Type: multipart/form-data; boundary=something");
and see if it helps.
for generating new line from php you can use:
echo "\n";
or
echo PHP_EOL;
it will give you new line that depends on web server operating system - so different for Linux, different for Windows.
these are incorrect in PHP: /r or /n. you need to use backslash and they only work if double quotes "\n" are used more read.
more read on text/plain

parsing email attachments in php

I have a .forward.postix that is piping incoming emails to a shell account, and consequently to a PHP script that parses the emails - awesome.
As of now, and based on everything I've seen online, I'm using the explode('From: ', $email); approach to split everything down into the vars I need for my database.
Enter attachments! Using the same approach, I'm doing this to pull out a jpg attachment - but it appears not every email client formats the raw source the same way and it's causing some headaches!
$contentType1 = explode('Content-type: image/jpg;', $email); //start ContentType
$contentType2 = explode("--Boundary_", $contentType1[1]); //end ContentType
$jpg1 = explode("\n\n", $contentType2[0]); //double return starts base64 blob
$jpg2 = explode("\n\n", $jpg1[1]); //double return marks end of base64 blob
$image = base64_decode($jpg2[0]); //decode base64 blob into jpg raw
Here's my issue:
Not all mail clients - like GMail for example - list an attachment as 'Content-type: image/jpg'. GMail puts in 'Content-Type: IMAGE/JPEG' and sometimes sends it as 'Content-Type: image/jpeg'! Which don't match my explode...
My Question: Does someone know a better way of finding the bounds of a base64 blob? or maybe a case-insensitive way of exploding the 'Content-Type:' so I can then try against image/jpg or image-jpeg to see what matches?
You can try to split your string using preg_split(). Maybe something like this
$pattern = '#content-type: image/jpe?g#i';
$split_array = preg_split($pattern, $email);

Pass Variable using $_GET to PHP Download Script

I have the following URL:
http://www.solutionssoftwarematrix.com/download.php?filename=CreatingandMarketingthePerfectYouTubeVideo.zip
I am trying to pass the string variable in to the PHP script (below) when someone clicks the link above.
Here is the script (download.php):
http://www.devshed.com/c/a/PHP/Simple-and-Secure-PHP-Download-Script-with-Limits-Tutorial/1/
THE LINES BELOW with BOLD AREAS are where my $_GET FUNCTION is BEING ADDED, however, I keep receiving parse errors OR it does not pull the filename, and the download does not work.
header("Content-type:application/pdf");
header('Content-Disposition: attachment;filename="http://www.yourdomain.com/ebookfordownloads/$_GET['$filename']"');
readfile("/your/absolute/server/path/html/ebookfordownloads/$_GET['$filename']");
header("Content-type:application/pdf");
header('Content-Disposition: attachment; filename="http://www.yourdomain.com/ebookfordownloads/$_GET['$filename']"');
readfile("/your/absolute/server/path/html/ebookfordownloads/$_GET['$filename']");
There are multiple problems:
This syntax is invalid: '$_GET['$filename ... The apostrophe before '$filename closes the string. What you probably want to do is downloads/' . $_GET[$filename] -- concatenation
This syntax is also invalid: "downloads/$_GET['$filename" -- with array access in a quoted string, you cannot have an apostrophe. Again, concatenation is your best bet: "downloads/" . $_GET[$filename]
I'm not sure whether you want $_GET['$filename'] or $_GET[$filename] or $_GET['filename']. There is a very important difference between the three.
Your code has a large vulnerability if a user can set $filename somehow (or the filename get parameter, if that is what you intend to use).
You are not getting basic PHP string functionality. To add variables like that, you'll have to use this:
readfile("/your/absolute/server/path/html/ebookfordownloads/{$_GET['$filename']}");
or concat them:
readfile("/your/absolute/server/path/html/ebookfordownloads/".$_GET['$filename']);
Not to mention the Very Big Security Hole when using user input ($_GET variables) verbatim in your code. Do validation before you use the given information.
Suppose this is how it should be:
header("Content-type:application/pdf");
header('Content-Disposition: attachment;filename="http://www.yourdomain.com/ebookfordownloads/' . $_GET['filename'] . '"');
readfile("/your/absolute/server/path/html/ebookfordownloads/" . $_GET['filename']);
header("Content-type:application/pdf");
header('Content-Disposition: attachment; filename="http://www.yourdomain.com/ebookfordownloads/' . $_GET['filename'] . '"');
readfile("/your/absolute/server/path/html/ebookfordownloads/" . $_GET['filename'] );
Take a look at string concatenation in PHP.
Also: $_GET['$filename'] means that you are asking PHP to get everything after ?$filename= in url. But your url has no $filename parameter, only filename, so it should be modified to $_GET['filename']. Or, if you have a name of parameter stored in variable called $filename like this: $filename = 'filename', it should be changed to $_GET[$filename]

CRLF (\r\n) in PHP's header() function

Why/when does one has to use CRLF's at the end of header in PHP?
Here is one example (it's not necessarily correct):
header("method: POST\r\n");
header('Host: '.get_option('transact_url')."\r\n");
header('Content-type: application/x-www-form-urlencoded');
header('Content-length: '.strlen($transaction)."\r\n");
header($transaction."\r\n\r\n");
header("Connection: close\r\n\r\n");
header("Location: ".$key_client_url."\r\n");
You should never do manual line-breaks inside of header(). The current implementation removes line-breaks so you're safe, but this could change in future (although there's no reason why it should be changed).
If it's PHP, this code is nonsense.
header() function is used to send answer headers, while some of these headers are request ones.
You can see this code because one who wrote it has no clue.
Got my log-in's all mixed, so I'm posting, although this a comment for halfdan. Feel free to correct it, if someone can.
link
I saw that in the link and nobody mentioned about what you've just told me, so I thought it has something to do with Linux line-endings. Granted, it was the only time I saw "\r\n" in header().
Halfdan is correct.
Here is the explanation.
The request line and headers must all end with CRLF (that is, a carriage return followed by a line feed). The empty line must consist of only and no other whitespace.
Request = Request-Line ; Section 5.1
*(( general-header ; Section 4.5
| request-header ; Section 5.3
| entity-header ) CRLF) ; Section 7.1
CRLF
[ message-body ] ; Section 4.3
source: w3c.org - Hypertext Transfer Protocol -- HTTP/1.1
There was a way to add \r\n to header in php 4, which was vulnerability that could be exploited, using CRLF injection attacks see PHP HTTP Header Multiple Vulnerabilities.

Categories