Cakephp not sending attachment, only send plain html - cakephp

I am trying to send an attachment with cakephp email, but only plain html sent and not a attachment.
The following code I am using.
$nmessage ="Hello Test\r\n\r\n";
$email = new CakeEmail();
$email->from(array('abc#example.com' => 'Test'));
$email->filePaths = array('/screenshots/');
$email->attachments =array('Google-Maps-9.22.2.jpg');
$email->to('user4#gmail.com');
$email->subject('Register a visit ');
$email->emailFormat('html');
$email->send($nmessage); // or use a template etc

To send attachments you can do it the following ways, first a string with the full path (notice there is no equals symbol, it's a function of the CakeEmail class).
$email->attachments('/full/file/path/file.jpg');
Secondly is the same but wrapped in an array
$email->attachments(array('/full/file/path/file.png'));
Thirdly an array with keys to rename the file
$Email->attachments(array('photo.png' => '/full/some_hash.png'))
And finally you can use nested arrays
$email->attachments(array(
'photo.png' => array(
'file' => '/full/some_hash.png',
'mimetype' => 'image/png',
'contentId' => 'my-unique-id'
)
));
So in summary, don't use $email->attachments = and make sure to provide the full path.
http://book.cakephp.org/2.0/en/core-utility-libraries/email.html#sending-attachments

Related

CakePHP 3.x - File validators on upload always failing

I am working on an image upload. I am trying to do the image verification in the model (like it should, right?), however I can't get the validation to work.
I put the following in src/Model/Table/CommentTable:
public function validationDefault(Validator $validator)
{
//...
$validator->add('photofile', 'upload', [
'rule' => ['uploadedFile', ['maxSize' => 1048576, 'optional' => true, 'types' => ['image/*']]],
'message' => 'Not a valid file'
]);
//...
}
For testing my controller looks like (I hard-coded an existing file):
$comment = $this->Comments->newEntity([
'body' => $data['body'],
'bin_id' => $bin_id,
'user_id' => $this->Auth->user('id'),
'photofile' => 'C:/Users/Robert/Downloads/test.jpg'
]);
This file is only a couple of bytes, yet after debugging $comment is shows an error in 'photofile':
'[errors]' => [
'photofile' => [
'upload' => 'Not a valid file'
]
],
So why is the validator always failing? Am I using it correctly?
Well, it's not an uploaded file, so that's generally the expected behavior. Also a string isn't supported as a valid value at all, the value must either be a file upload array, or as of CakePHP 3.4, an object that implements \Psr\Http\Message\UploadedFileInterface.
For file upload arrays, the uploadedFile validation rule provided by CakePHP will utilize is_uploaded_file(), which will fail for files that haven't actually been uploaded, and you cannot emulate them.
As of CakePHP 3.4 you can use UploadedFileInterface objects as already mentioned. CakePHP requires \Zend\Diactoros\UploadedFile which provides an implementation that you could utilize for testing purposes, like:
$file = 'C:/Users/Robert/Downloads/test.jpg';
$comment = $this->Comments->newEntity([
'body' => $data['body'],
'bin_id' => $bin_id,
'user_id' => $this->Auth->user('id'),
'photofile' => new \Zend\Diactoros\UploadedFile(
$file,
filesize($file),
\UPLOAD_ERR_OK,
pathinfo($file, \PATHINFO_BASENAME),
'image/jpeg'
)
]);
However while this will pass validation, you won't be able to move that file using UploadedFile::moveTo(), as it uses move_uploaded_file(), which again only works with files that have actually been uploaded.
Also regex validation of MIME types only works when passed as a string (this currently isn't documented), and it must be a valid regex including delimiters, like
'types' => '#^image/.+$#'
Alternatively specify the exact types as an array, ie
'types' => ['image/jpeg', 'image/png', /* ... */]
See also
Zend Diactoros API > UploadedFile
CakePHP API > \Cake\Validation\Validation::uploadedFile()

Google App Engine Send Grid PHP attachment

I am trying to add attachments as shown on https://github.com/sendgrid/sendgrid-google-php. But its not working by this way. I think I tried every possible solution but cant make this work. Here is my code.
<?php
require 'SendGrid_loader.php';
// Connect to your SendGrid account
$sendgrid = new SendGrid\SendGrid('myusername', 'mypassword');
// Make a message object
$mail = new SendGrid\Mail();
// Mail arrayi
$emails = array("mailadress1#test.com","mailadress2#test.com");
$names = array("name1", "name2");
// Add recipients and other message details
$mail->setTos($emails)->
setFrom('testsender#test.com')->
setFromName('Test Sender')->
setReplyTo('testemail#test.com')->
setSubject('Test')->
addAttachment("test.jpg")->
addCategory("TEST-GONDERIM")->
addUniqueArgument("BASIN", "YEREL-BASIN")->
addSubstitution("%name%", $names)->
setText('TEXT BODY MESSAGE')->
setHtml('<strong>%name% MERHABA,</br>BODY MESSAGE</strong>');
// Use the Web API to send your message
$sendgrid->send($mail);
?>
I tried to put test.jpg file on the same folder with this php file. Also tried to add like gs://bucket_name/test.jpg but not working. Any ideas. Thanks in advance
Solved with using web api v2 Curl version like this
$fileName = 'filename.pdf';
$image_data = file_get_contents('gs://my-bucket/filename.pdf');
sending part
$params = array(
'api_user' => $user,
'api_key' => $pass,
'x-smtpapi' => json_encode($json_string),
'to' => 'email#yourdomain.com',
'subject' => 'your subject',
'html' => 'testing body',
'text' => 'testing body',
'from' => 'yourmail#yourdomain.com',
'files['.$fileName.']' => $image_data
);
$request = $url.'api/mail.send.json';

How to build a Url with multiple query (?) params with CakePHP 3

I'm working in a redirection for autocomplete some fields, and I'm doing this with simple javascript.
I wanted to print a URL without A tag, then I used Url builder. I've seen documentation and reviewed source code for this method in Router class but I see something that I can't understand.
All works right when I use Url builder with this code:
<?= $this->Url->build(['controller' => 'places', 'action' => 'add', '?' => ['event_id' => $event->id]]) ?>
Url genetared is:
/places/add?event_id=1
But, when I add more params in ? query, I get a & in url, but I didn't find in docs something for elimitate special chars filter.
<?= $this->Url->build(['controller' => 'places', 'action' => 'add', '?' => ['from' => 'events','id' => $event->id]])
// Generates: /places/add?from=events&id=1
// I want: /places/add?from=events&id=1
?>
Is there an option to get & without &? If I put all in one string, I get UTF codes %5D and those. I'm using url in a javascript window.open, then I'm not printing in html body.
I see line 597 in http://api.cakephp.org/3.0/source-class-Cake.Routing.Router.html#509-646, but I don't understand if $url = static::_applyUrlFilters($url); code is changing something.
Thank you!
The URL helper is ment to be used for generating URLs for use in markup contexts, therefore they are being entity encoded using the h() function.
In case you need the plain URLs, don't use the URL helper, but the Router::url() method instead.
use Cake\Routing\Router;
Router::url([
'controller' => 'places',
'action' => 'add',
'?' => [
'from' => 'events',
'id' => $event->id
]
]);

How to set a custom option of type "file" when adding a product to the cart in Magento?

Using my own controller, I'm adding a product to the Magento cart. It has 3 custom options: 2 dropdown options (color and size) and a file option (design). The code adding the product to the cart is
// obtain the shopping cart
$cart = Mage::getSingleton('checkout/cart');
// load the product
$product = Mage::getModel('catalog/product')
->load($productId);
// do some magic to obtain the select ids for color and size ($selectedSize and $selectedColor)
// ...
// define the buy request params
$params = array(
'product' => $productId,
'qty' => $quantity,
'options' => array(
$customOptionSize->getId() => $selectedSize,
$customOptionColor->getId() => $selectedColor,
// set the file option, but how?
),
);
// add this configuration to cart
$cart->addProduct($product, $paramObject);
$cart->save();
// set the cart as updated
Mage::getSingleton('checkout/session')->setCartWasUpdated(true);
My question is: How do I attach a certain file to the design option?
The file has already been transferred to the server side (actually via the request). I could, however, fake uploading if this would be required. But until now I have not found a single source of information on setting file custom options...
My best guess from a tour through the Magento sources, is that the buy request needs some additional data (not in the options, but in the params object), like: option_123_file => something, but what exactly is needed I did not figure out yet. This part of the Magento sources is rather, uhh, not so straight forward. Thanks for any help.
Ok finally figured this out. The params array needs special entry to tell the custom option with the key "options_xx_file_action" what to do with a file ('save_new' or 'save_old'). This would look like:
$params = array(
'product' => $productId,
'qty' => $quantity,
'options' => array(
$customOptionSize->getId() => $selectedSize,
$customOptionColor->getId() => $selectedColor,
),
'options_'.$customOptionDesign->getId().'_file_action'=>'save_new',
);
Obviously, you will need to add the file to the post request (via form or therelike). The name of the file should be "options_xx_file". For example, in my case my $_FILES looked like:
Array (
[options_108_file] => Array
(
[name] => i-like.png
[type] => application/octet-stream
[tmp_name] => C:\xampp\tmp\phpAAB8.tmp
[error] => 0
[size] => 6369
)
)

Using HtmlHelper on Model to insert links in returned errors

I'm working with CakePHP and trying to understand the best ways to make my application consistent and logical.
Now I'm trying to working with Model data validation and handling validation errors in the view, I have a doubt on how should I do if I like to insert some link inside the returned error, for example for a forgotten password.
Is it good to use (if it's possibile) HtmlHelper inside the Model to return consistent links inside my application, or should I think about another way?
<?php
App::import('Helper', 'Html');
class User extends AppModel {
var $name = 'User';
var $validate = array (
'email' => array (
'checkEmail' => array (
'rule' => array('email', true),
'message' => 'Email not valid message.'
),
'checkUnique' => array (
'rule' => 'isUnique',
'message' => 'This email is allready in the db, if you forgot the password, '.(string)$this->Html->link('click here', array('controller' => 'users', 'action' => 'password-recover')).'.'
)
)
// the rest of the code...
This doesn't work because it seems I can't chain the message string with HTML string.
Does exist e smartest way to do that, or should I simply insert the html string without the HtmlHelper?
If you really want HTML in your validation messages CakePHP provides a way to do this, no breaking Cake, no writing a lot of code.
In your $validation just use whatever HTML you would like to have presented to the user.
In your view when you create your FormHelper::input($fieldName, array $options) pass the following array to $options:
$options = array('error' => array(
'attributes' => array('escape' => false)
))
See this page to learn more about the $options['error'] ...options.
Alternatively, if you want all inputs with no HTML escaping you can pass $options['inputDefaults'] when you create the form.
this is a difficult topic because
you might need to break MVC
validation is as in your case usually in $validate and cannot contain dynamic stuff
for 1)
you can also use Router::url() with manual HTML
you can use BBcode or pseudo-markup and translate this into real links in the view/element of the flashmessage
for 2)
use __construct() and $this->validate to use dynamic elements if needed
In PHP, properties of a class (such as $validate) have to be initialized with constant values.
<?php
class User extends AppModel {
public $validate = array(
'email' => array(
'checkUnique' => array(
'rule' => array('isUnique'),
'message' => 'This email address has already been claimed, possibly by you. If this is your email address, use the reset password facility to regain access to your account'
),
),
);
public function beforeValidate($options = array()) {
$this->validate['email']['checkUnique']['message'] = String::insert(
$this->validate['email']['checkUnique']['message'],
array('link' => Router::url(array('action' => 'password-recover')))
);
return true;
}
You are making it hard on yourself. The helpers are not accessible in the model and controller. And for good reason: the M and C shouldn't be concerned with the V.
There are ways to do exactly as you want (but involves considerably more code). Since you ask for the smartest way: What's wrong with just echo the reset password link in the view, after the login form? Just echo 'Forgot your password? '.$this->Html->link('Click here', array('controller' => 'users', 'action' => 'password-recover'));
I don't agree on breaking the MVC logic. I also tried all the array('escape' => false) possible ways (in Form->input, in Form->error and even in the model) and none of them worked with me! (cakephp 2.0)
"Anh Pham" answer is the easiest and simplest way. In addition to that, I returned empty error message from model validation ('errorMessage' => false ; doesn't work in cakePhp 2.0).
Because I wanted to pass a variable to the view to build the link there (MVC), in the controller I check if the field is invalidated:
$invlaidFields = array_keys($this->Model->validationErrors();
if ( in_array('myField', $invalidFields) ){
...
}
In the view, I check if the field was invalidated, I then echo my error message giving it class error-message so it looks the same as the rest error messages.
if ($this->Form->('myFields')) { ... echo '<span class="error-message">error message'. $this->Html->link(...).'</span>'; }
Hope it helps somebody out there.
P.S. It's always a good practice to mention what cakePHP version you are using...
To cakephp2 you can use the following:
//model validation
'company' => array('notempty' => array('rule' => array('notempty'),'message' => "select one company o send email to contact",),)
//front
<?php if ($this->Form->isFieldError('Register.company')): ?>
<span class="text-danger"><?php echo $this->Form->error('Register.company', null, array('escape'=>false)); ?></span>
<?php endif; ?>

Resources