vanilla php convert base64 to image in email attachment - php

I have a php script that sends me an email. Within this email data, I send base64 image data, but what I would like is that the base64 gets converted into a jpeg which then gets added as an attachment via email.
<?php
header('Access-Control-Allow-Origin: *');
if(isset($_POST['email'])){
$to = 'my#email.com';
$subject = "New submission from ".$_POST['email'];
$message = $_POST['message'];
$image = base64_to_jpeg( $_POST['image'], 'image.jpeg' ); //this is base64 image
$subscribe = $_POST['subscribe'];
$headers = "From: ".$_POST['email']." <".">\r\n"; $headers = "Reply-To: ".$_POST['email']."\r\n";
$headers = "Content-type: text/html; charset=iso-8859-1\r\n";
'X-Mailer: PHP/' . phpversion();
if(mail($to, $subject, $image, $headers)) echo json_encode(['success'=>true]);
else echo json_encode(['success'=>false]);
exit;
}
function base64_to_jpeg($base64_string, $output_file) {
// open the output file for writing
$ifp = fopen( $output_file, 'wb' );
// split the string on commas
// $data[ 0 ] == "data:image/png;base64"
// $data[ 1 ] == <actual base64 string>
$data = explode( ',', $base64_string );
// we could add validation here with ensuring count( $data ) > 1
fwrite( $ifp, base64_decode( $data[ 1 ] ) );
// clean up the file resource
fclose( $ifp );
return $output_file;
}
?>
$image is data:image/png;base64,iVBORw0KGg
The issue I'm having is that when the email gets sent, the email only inclues plain text "image.jpeg" rather than showing the image, or attaching the image...
Any idea how I can fix this?
Thank you.

Passing $image to the body of the mail would obviously send the name, because that's what you're returning from the function.
But if you pass it with an image tag;
mail($to, $subject, '<img src="' . $image . '" alt="'. $image . '">', $headers); // I used PHP template strings to create the img tag
You're surely going to get the data string passed into the mail's body
Here's a screenshot with the link you posted me
This is the complete code I'm running base64_to_jpeg is your function I got from the question
<?php
function base64_to_jpeg($base64_string, $output_file)
{
// open the output file for writing
$ifp = fopen($output_file, 'wb');
// split the string on commas
// $data[ 0 ] == "data:image/png;base64"
// $data[ 1 ] == <actual base64 string>
$data = explode(',', $base64_string);
// we could add validation here with ensuring count( $data ) > 1
fwrite($ifp, base64_decode($data[1]));
// clean up the file resource
fclose($ifp);
return $output_file;
}
$image = base64_to_jpeg(base64_string_from_link, 'image.jpeg')
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Base 64</title>
</head>
<body>
<?php echo '<img src="' . $image . '" alt="' . $image . '">'; ?>
</body>
</html>
I understand your problem now, When you pass the $image to the mail's body, the alt text is showing simply because, the mail doesn't know where to download the image from.
When you're sending images through mail, the image links have to be absolute paths for the mail to know where to download the image from.
Therefore, either you upload that image to your websites file manager and use an absolute path like so, <img src="https://picsum.photos/id/237/200/300">
or
don't convert the image to .jpeg, just pass the base 64 string as the image's src <img src="data:image/png;base64,iVBORw0KGg">
I also saw in your code that you're not concatenating the $headers together rather just resetting the value. (i.e. you're using = instead of .=)

Related

Image into string and back

I need to store images into an MSSQL database as part of a form processing which is handled by PHP.
Before that, my client did this task with following C# code:
Dim content As Byte() = ImageToStream(fName)
cnn.Open()
Dim cmd As New SqlCommand("UPDATE lide SET pictPostava = #img WHERE ID = '" & GetValueToTextBox(iRow, "ID") & "'", cnn)
cmd.Parameters.AddWithValue("#img", content)
cmd.ExecuteNonQuery()
cnn.Close()
content = Nothing
Public Function ImageToStream(ByVal fileName As String) As Byte()
Dim stream As New MemoryStream()
tryagain:
Try
Dim image As New Bitmap(fileName)
image.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg)
Catch ex As Exception
GoTo tryagain
End Try
Return stream.ToArray()
End Function
I tried to replicate it via unpack() function based on http://php.net/manual/en/function.mssql-query.php#31688
// convert file
$file = file_get_contents('http://www.sunagency.cz/wp-content/uploads/2017/01/1745083-150x150.jpg');
$unpacked = "0x" . unpack("H*hex", $file);
// get the hexcode of image
print_r( $unpacked['hex'] );
However, he can't restore it. And to be honest, I'm not sure how to revert it back with PHP either - changing header into Image doesn't solve the problem.
// view the packed file
header("Content-type: image/jpeg;");
echo $unpacked['hex'];
Could you help? I have never done this before and would be more than happy to solve the problem.
If somebody gets the same trouble as I did, the way is to completely fake the form values:
$boundary = wp_generate_password(24);
$url = "issues/$issue_id/files.json";
$this->content_type = "multipart/form-data; boundary=$boundary";
$payload = '';
$n = 1;
// Upload files
foreach ($files as $file) {
$payload .= '--' . $boundary;
$payload .= "\r\n";
$payload .= 'Content-Disposition: form-data; name="attachments['.$n.'][file]"; filename="' . basename($file) . '"' . "\r\n";
// $payload .= 'Content-Type: image/jpeg' . "\r\n";
// $payload .= 'Content-Transfer-Encoding: binary' . "\r\n";
$payload .= "\r\n";
$payload .= file_get_contents($file);
$payload .= "\r\n";
$n++;
}
$payload .= '--' . $boundary . '--';
Here are the resources that helped me at that time (answering the question way later than I solved it), but maybe it will help someone in the future.
https://gist.github.com/UmeshSingla/40b5f7b0fb7e0ade0438
Posting raw image data as multipart/form-data in curl

Broken links inside PHP emailer with AngularJS

I have an AngularJS app that sends emails using a PHP document.
The email body includes two links to images that are populated with a JS variables.
Most of the emails arrive good and the links work, but in some of them, the links (both or one of them) will come out broken, looking like this:
https://blabla.com/register/uploads/Frankfurt2018-22-03-2018-16-07-52.!
Or like this:
https://blabla.com/register/uploads/KoelnerListe2%21
Or like this:
https://blabla.com/register/upload!
It's weird cause sometimes is both links, sometimes is only one, and most of the times are correct.
The link variable comes from the Angular app and looks like this:
$scope.sendapplication = function(){
$scope.photoor = "https://blabla.com/register/uploads/"+$scope.photoor;
$scope.photosmall = "https://blabla.com/register/uploads/"+$scope.photo;
$scope.exhibitor = {
'img':$scope.photosmall,
'imgoriginal':$scope.photoor,
};
var $promise=$http.post('emailtest.php',$scope.exhibitor);
$promise.then(function (data) {
...
});
};
And in the php file I do this:
$contentType = explode(';', $_SERVER['CONTENT_TYPE']); // Check all available Content-Type
$rawBody = file_get_contents("php://input"); // Read body
$data = array(); // Initialize default data array
if(in_array('application/json', $contentType)) {
$data = json_decode($rawBody); // Then decode it
$photo = $data->img;
$photooriginal = $data->imgoriginal;
} else {
parse_str($data, $data); // If not JSON, just do same as PHP default method
}
header('Content-Type: application/json; charset=UTF-8');
echo json_encode(array( // Return data
'data' => $data
));
$sabine = 'blabla#gmail.com';
$headerss = "From: ".$galleryname."<".$email.">\r\nReturn-path: ".$email."";
$headerss .= "Reply-To: ".$galleryname."<".$email.">";
$headerss .= "MIME-Version: 1.0\r\n";
$headerss .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
$recipient = $sabine;
$subjects = "Registration for ".$fairumlaut." - ".$galleryname."";
$bodys .= "<p><strong>Original photo</strong>: Link</p>";
$bodys .= "<p><strong>Web resized photo</strong>: Link</p>";
$bodys .= "<p></p>";
mail($recipient, $subjects, $bodys, $headerss);
What could cause such weird behaviour?
wrap the link in urlencode function. This will solve your issue.
update: or if I read your code I would have seen that the links are coming from JS. Try encodeURI().. ;)

Mail Mime image in email body not showing up using MailMime addHtml(...)

Mail_Mime 1.8.9
Mail 1.2.0
php 5.4.12
project = run from my localhost dev computer (LAN).
Hello, I am attempting to add an image to my email I am sending out using MailMime. The image never loads. I'll go through the steps below:
Here I am stripping everything off of the image but the image name and extension (ie:noimage.jpg). I then create a link for non image related purposes, I then create the image tag using the stripped image name and extension.
$url = substr($baseImage, 36);
$domainName = DomainNameUtil::getWebSiteDomainName();
$projectPath = DomainNameUtil::getPathToProject();
$productUrl = $domainName . $projectPath . "/client/app/#/products/" . $product->id;
$productLink = "<a href='$productUrl'>$product->name</a>";
$string = "<img src='$url' /><br />";
Here I am sending the message
$mailConfig = MailConfigurationUtil::getMailConfigurationData();
$headers = array (
'From' => $from,
'To' => $to,
'Subject' => $subject
);
$crlf = "\n";
$mime = new Mail_mime(array('eol' => $crlf));
$mime->setHTMLBody($body);
$headers = $mime->headers($headers);
$smtp = Mail::factory('smtp', array (
'host' => $mailConfig->mailServer,
'port' => $mailConfig->port,
'auth' => true,
'username' => $mailConfig->userName,
'password' => $mailConfig->password
));
$productManager = new ProductManager();
$ordersManager = new OrdersManager();
$orderVirtualItem = $ordersManager->getOrderVirtualItemByBoxId($boxId);
$product = $productManager->getProductById($orderVirtualItem->itemId);
$url = $product->baseImage;
$domain = DomainNameUtil::getWebSiteDomainName();
$path = DomainNameUtil::getPathToProject();
$r = substr($url, 5);
$finalUrl = $domain . $path . $r;
$mime->addHTMLImage(file_get_contents($finalUrl),'image/jpeg',basename("noimage"),false, "blackstone");
$body = $mime->get();
$mail = $smtp->send($to, $headers, $body);
In the example above, I know the image is called noimage.jpeg, so in the addHtmlImage above I simply stated the name. I am under the impression that the name used in addHtmlImage has to be the same name as the image name in the image src tag in the html body.
When I actually send my email I get the email and I get some text saying there is an image, but the image tag in my email body does not load.
Also, looking at it under firebug it has a proxy attached to the image src. Also it references it as PROXYADDRESS#http://noimage.jpg
Anyone have experience in this that can help me understand why the image is not loading?
For reference, I saw someone posting this method online and tried copying them. before this I had even tried putting the whole url in the image src and not adding the image to MIME, and it did not work.
i got pretty similar problem here.
What i got so far: it depends on phpversion (and installed Mail_Mime).
Mail_Mime seems to be "broken" under php 5.4.30
If i run my script under php 5.2.17 all images show up correctly
If i run my script under php 5.4.30 all images do not show up correctly
when i compare both sourcecodes, it seems, Mail_Mime under 5.4.30 gets messy with the order of boundarys and the Content-Type:
Content-Type: multipart/alternative; in 5.2.17
Content-Type: multipart/related; in 5.4.30enter image description here
When specifying a context-id (the last parameter to addHtmlImage()) you must reference the image in the html message correctly: <img src="cid:context-id#local" />. Of course replacing context id with your own context id for each image to show.

my CSV attachment is empty! PHP [duplicate]

This question already has an answer here:
PHP attachment in email is empty
(1 answer)
Closed 9 years ago.
Im trying to take data from the database and display it in a CSV file which is both downloadable and emailed to someone. I have managed to get the downloadable file working and it displays all of the correct data. It also sends a CSV file to the necessary person but that CSV file is empty and no data is displayed in it.
Here is my code:
$myroot = "../../";
include($myroot . "inc/functions.php");
// output headers so that the file is downloaded rather than displayed
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=surveys.csv');
$output = fopen('php://output', 'w');
// Create CSV file
fputcsv($output, array('Name', 'Branch', 'Website','Company', 'Question1', 'Question2', 'Question3', 'Question4', 'Question5'));
$mysql_connection = db_connect_enhanced('*****','*****','*****','*****');
$query='SELECT * FROM *****.*****';
$surveys = db_query_into_array_enhanced($mysql_connection, $query);
$count = count($surveys);
$data = array();
for($i=0; $i<=$count; $i++){
$data[] = array($surveys[$i]['FeedbackName'], $surveys[$i]['BranchName'], $surveys[$i]['FeedbackWebsite'], $surveys[$i]['FeedbackCompany'], $surveys[$i]['Question1'], $surveys[$i]['Question2'], $surveys[$i]['Question3'], $surveys[$i]['Question4'], $surveys[$i]['Question5']);
}
foreach( $data as $row )
{
fputcsv($output, $row, ',', '"');
}
fclose($output);
$encoded = chunk_split(base64_encode($output));
// create the email and send it off
$subject = "File you requested from RRWH.com";
$from = "*****#*****.com";
$headers = 'MIME-Version: 1.0' . "\n";
$headers .= 'Content-Type: multipart/mixed;
boundary="----=_NextPart_001_0011_1234ABCD.4321FDAC"' . "\n";
$message = '
This is a multi-part message in MIME format.
------=_NextPart_001_0011_1234ABCD.4321FDAC
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
Hello
We have attached for you the PHP script that you requested from http://rrwh.com/scripts.php
as a zip file.
Regards
------=_NextPart_001_0011_1234ABCD.4321FDAC
Content-Type: application/octet-stream; name="';
$message .= "surveys.csv";
$message .= '"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="';
$message .= "surveys.csv";
$message .= '"
';
$message .= $encoded;
$message .= '
------=_NextPart_001_0011_1234ABCD.4321FDAC--
';
mail("*****#*****.com", $subject, $message, $headers, "-f$from");
I've spent a day and a half on this but I cant see the problem. Could someone please point it out to me as to why the attached CSV file is empty?
i'm getting kind of desperate and stressed out :( please someone help me.
base64_encode() expects the parameter to be a string and you give it a (closed) resource.
Try to read the resource into a string, or use file_get_contents or build your string while you write into the resource.
Update:
Try and replace
foreach( $data as $row )
{
fputcsv($output, $row, ',', '"');
}
fclose($output);
$encoded = chunk_split(base64_encode($output));
by
$myoutput = '"Name","Branch","Website","Company","Question1","Question2","Question3","Question4","Question5"';
foreach( $data as $row )
{
$myoutput .= "\"".implode('","',$row)."\"\n";
fputcsv($output, $row, ',', '"');
}
fclose($output);
$encoded = chunk_split(base64_encode($myoutput));
This way, everything you write into your output you also write into a new variable ($myoutput). Since this is a string you can use it with base64_encode().

Email decoding doesn't work in zend mail

I have a script that access the specified email and fetches mail. $temp->getContent() echos the following..
----boundary_2710_edfb8b44-71c8-49ff-a8cb-88c83382c4ee
Content-Type: multipart/alternative;
boundary=--boundary_2709_dde0dd0e-ba35-4469-949d-5392aec65750 --boundary_2709_dde0dd0e-ba35-4469-949d-5392aec65750
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: base64
PGZvcm0gbWV0aG9k.........this part is base64 encoded and it works fine if i copy and decode it separately.......AgICAgICAgICAgDQoNCjwvZm9ybT4=
----boundary_2709_dde0dd0e-ba35-4469-949d-5392aec65750-- ----boundary_2710_edfb8b44-71c8-49ff-a8cb-88c83382c4ee
Content-Type: multipart/mixed; boundary=--boundary_2711_eca4cfc3-fc62-43d6-b9fb-e5295abbfbe8 ----boundary_2711_eca4cfc3-fc62-43d6-b9fb-e5295abbfbe8 Content-Type: application/pdf;
name=redBusTicket.pdf
Content-Transfer-Encoding: base64
Content-Disposition: attachment Content-ID: JVBERi0xLjIgCiXi48/TIAoxIDAgb2JqIAo8PCAKL1R5cGUgL0NhdGFsb2cgCi9QYWdlcyAy IDAgUiAKL1BhZ2VNb2RlIC9Vc2VOb25lIAovVmlld2VyUHJlZ
Between this content there is base64 encoded part and it works fine if i copy and decode it separately. Also there is a attachment in the mail. How can i get the attached file. The following is my code. when i use the base64_decode directly i get no output.. just a blank page..
$storage = new Zend_Mail_Storage_Imap($imap);
$temp = $storage->getMessage($_GET['mailid']);
echo base64_decode($temp->getContent());
the documentation in zend website is not very good. Need some help!!
It works good for me:
foreach ($mail as $message) {
$content = null;
foreach (new RecursiveIteratorIterator($message) as $part) {
if (strtok($part->contentType, ';') == 'text/plain') {
$content = $part;
break;
}
}
if ($content) {
echo "\n encode: " . $content->contentTransferEncoding;
echo "\n date: " . $message->date;
echo "\n subject: \n" . iconv_mime_decode($message->subject, 0, 'UTF-8');
echo "\n plain text part: \n" . mb_convert_encoding(base64_decode($content), 'UTF-8', 'KOI8-R');
}
}
I have something like this to get the base_64 contents from an email. Try to filter out what you dont need.
if ($email->isMultipart() && $partsCount){
for($i = 1; $i < $email->countParts() +1; $i++) {
$part = $email->getPart($i);
$headers = $part->getHeaders();
if (
array_key_exists('content-description', $headers)
|| array_key_exists('content-disposition', $headers)
){
if (array_key_exists('content-description', $headers)) {
$att = $part->getContent();
$filepath = utf8_encode(DATA_PATH . '/' . $part->getHeader('content-description'));
if (is_file($filepath)) {
unlink($filepath); // deletes previous files with same name
}
$file = fopen($filepath, "w");
fwrite($file, base64_decode($att));
fclose($file);
$attachments[] = $filepath;
}
}
}
}

Categories