drupal_mail() returns true but unable to send mail - drupal-7

I have written a drupal module with custom form api which will send email to my inbox on each submit. I have written a condition under drupal_mail which returns true but shows an error message "Unable to send e-mail. Contact the site administrator if the problem persists."
Below my code:
function my_module_name_mail($key, &$message, $params)
{
$headers = array(
'MIME-Version' => '1.0',
'Content-Type' => 'text/html; charset=UTF-8;',
'Content-Transfer-Encoding' => '8Bit',
'X-Mailer' => 'Drupal'
);
foreach ($headers as $key => $value) {
$message['headers'][$key] = $value;
}
$message['subject'] = $params['subject'];
$message['body'] = $params['body'];
}
function my_module_name_form_submit($form, &$form_state)
{
$from = $form_state['values']['email'];
$body= 'Name: '.$name.'<br />Email: '.$email;
$to = "my_mail_id#example.com";
$params = array(
'body' => $body,
'subject' => 'Website Information Request',
);
drupal_mail('my_module_name', 'some_mail_key', $to, language_default(), $params, $from, TRUE);
}

Check your Drupal logs for more clues. Enable devel / devel-admin modules. Once you do, drupal_mail will pipe emails to your temp directory, which will help you narrow down if the problem is with your email server or the config.

Related

Is this the correct way to create and post a mutipart form data in CakePhp3?

I am trying to post a mutipart form data in CakePhp3. The form should contain a few information about the user (text fields) and an image.
I'm doing something like this:
$request = [
'fistname'=>$user->firstname,
'lastname'=>'$user->lastname',
'_session'=>'$session'
];
$form = new FormData();
foreach ($request as $key => $value) {
$form->add($key,$request);
}
$file = $form->addFile('upload',fopen(WWW_ROOT.'img/picture.png','r'));
$file->contentId('mypicture'); // <-- not sure what this is
$file->disposition('attachment');
$response = $http->post(
$url,
(string)$form,
['headers' => ['Content-Type' => $form->contentType()]]
);
Is this the correct way to create and post a mutipart form data in CakePhp3?
Thanks for your help.
EDIT
If I post to my own server it seems to be working (thanks #Mary), but I get firstname and lastname replicated (this might be the problem):
object(Cake\Http\ServerRequest) {
trustProxy => false
...
[protected] data => [
'fistname' => [
'fistname' => 'Test',
'lastname' => 'Test'
],
'lastname' => [
'fistname' => 'Test',
'lastname' => 'Test'
],
'upload' => [
'tmp_name' => '/private/var/folders/g5/jjd1vc557bs21hq805lcxjk80000gn/T/phpAVXNqK',
'error' => (int) 0,
'name' => 'SELL5BAE2B6348272_gallery_1.png',
'type' => 'image/png',
'size' => (int) 200231
]
]
...
If I post to the API server it doesn't work.
I did the same with CURL and it works:
$filename = WWW_ROOT.'ufiles/medium/'.$img['image_1'];
$cFile = curl_file_create($filename);
$request = [
'_operation'=>'uploadFile',
'id'=>$ticket_id,
'_session'=>$session,
'file' => $cFile
];
try{
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_URL,$this->crm['endpoint']);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
$response=curl_exec($ch);
curl_close ($ch);
}catch(\Exception $e){
$response = null;
}
Counterquestion: Does it work?
As you can see here, $file->contentId() sets the Content ID or part in a multipart form data request body:
https://github.com/cakephp/cakephp/blob/master/src/Http/Client/FormDataPart.php#L114
I’m not sure about this, but I don’t think you have to set it as it doesn’t seem to be required for multipart/form-data:
https://www.w3.org/TR/2006/REC-xforms-20060314/slice11.html#serialize-form-data
Edit
I did some testing and: It. works. Here is what I tried:
use Cake\Http\Client;
use Cake\Http\Client\FormData;
public function test() {
$request = [
'fistname'=>'Test',
'lastname'=>'Test'
];
$form = new FormData();
$http = new Client();
foreach ($request as $key => $value) {
$form->add($key,$request);
}
$file = $form->addFile('upload',fopen(WWW_ROOT.'img/awards.png','r'));
$file->contentId('mypicture'); // <-- not sure what this is
$file->disposition('attachment');
$response = $http->post(
'http://www.testurl.dev/test',
(string)$form,
['headers' => ['Content-Type' => $form->contentType()]]
);
var_dump($response);
exit;
}
Output of var_dump($response):
object(Cake\Http\Client\Response)#150 (12) {
["code":protected]=>int(200)
…
["headers":protected]=>array(12) {
["Date"]=>array(1) {
[0]=>string(29) "Fri, 28 Sep 2018 12:44:31 GMT"
}
…
}
}
Server access log output:
[28/Sep/2018:14:44:31 +0200] "POST /test HTTP/1.1" 200 6852 "-" "CakePHP"

Not Getting access token from of Gmail Contacts API using Oauth2 while code is in Google App Engine Server

I am using zend-framework2 and google-app-engine server to import all gmail contact list. I am getting authorization code from gmail after login. When hitting curl using this authorization code to get access token, it gives blank array as response.
Also this app is a billed app in google-app-engine. and already set
extension = "curl.so"
in php.ini file. and the credentials which i have given are correct.
// Import Gmail Contacts
$client_id='xxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com';
$client_secret='xxxxxxxxxxxxxx-xxxxxxxxx';
$redirect_uri='http://xxxxxxxxxxxxxxx.appspot.com/u/invite/gmailCallback';
$max_results = 1000;
if(isset($_GET["code"]) && $_GET["code"] != '') {
$auth_code = $_GET["code"];
$fields=array(
'code'=> urlencode($auth_code),
'client_id'=> urlencode($client_id),
'client_secret'=> urlencode($client_secret),
'redirect_uri'=> urlencode($redirect_uri),
'grant_type'=> urlencode('authorization_code')
);
$post = '';
foreach($fields as $key=>$value) { $post .= $key.'='.$value.'&'; }
$post = rtrim($post,'&');
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL,'https://accounts.google.com/o/oauth2/token');
curl_setopt($curl,CURLOPT_POST,5);
curl_setopt($curl,CURLOPT_POSTFIELDS,$post);
curl_setopt($curl, CURLOPT_RETURNTRANSFER,TRUE);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,FALSE);
$result = curl_exec($curl);
//$info = curl_getinfo($curl);
//echo "<pre>"; print_r($info); die;
curl_close($curl);
$response = json_decode($result);
//echo "<pre>"; var_dump($response); die;
if(isset($response->access_token) && $response->access_token != '') {
$accesstoken = $response->access_token;
$url = 'https://www.google.com/m8/feeds/contacts/default/full?max-results='.$max_results.'&oauth_token='.$accesstoken;
//$url = 'https://www.google.com/m8/feeds/contacts/default/full?oauth_token='.$accesstoken;
$xmlresponse = $this->curl_file_get_contents($url);
//At times you get Authorization error from Google.
if((strlen(stristr($xmlresponse,'Authorization required'))>0) && (strlen(stristr($xmlresponse,'Error '))>0)) {
//$returnArr['error_msg'] = "Something went wrong to import contacts!!";
echo '<h2>Something went wrong to import contacts !!</h2>';die;
} else {
$xml = new SimpleXMLElement($xmlresponse);
$xml->registerXPathNamespace('gd', 'http://schemas.google.com/g/2005');
$result = $xml->xpath('//gd:email');
//echo "<pre>"; print_r($result); die;
foreach ($result as $title) {
$emailsArr[] = (string) $title->attributes()->address;
}
}
}
}
Please help.
From previous experience (and this answer) I don't think cURL is enabled on App Engine as C extensions aren't supported.
You'll have to use URL Fetch instead e.g.
$data = ['data' => 'this', 'data2' => 'that'];
$data = http_build_query($data);
$context = [
'http' => [
'method' => 'GET',
'header' => "custom-header: custom-value\r\n" .
"custom-header-two: custom-value-2\r\n",
'content' => $data
]
];
$context = stream_context_create($context);
$result = file_get_contents('http://app.com/path?query=update', false, $context);
App engine supports cURL, but it seems to be buggy. I have the same problem with OAuth authentication via Google. The POST cURL call just returns FALSE without any error message. Here is the official bug report: https://code.google.com/p/googleappengine/issues/detail?id=11985
What you can do now, is to switch to url fetch functions. To make a POST request you can use following function:
protected function _call($url, array $params, $method = 'GET', array $headers = [])
{
$query = http_build_query($params);
$headers_str = '';
if ($headers) {
foreach ($headers as $name => $value) {
$headers_str .= $name . ': ' . $value . "\r\n";
}
}
$headers_str .= "Content-type: "."application/x-www-form-urlencoded"."\r\n";
$options =
array('http'=>
array(
'method' => $method,
'header' => $headers_str,
'content' => $query,
'ignore_errors' => true,
)
);
if ($method === 'POST') {
$options['http']['content'] = $query;
} else if ($query) {
$url .= '?' . $query;
}
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
// check for zipped response and decode it
if (array_search('Content-Encoding: gzip', $http_response_header)) {
$response = gzinflate(substr($response, 10, -8));
}
return $response;
}
Or you can try to use this cURL wrapper library https://github.com/azayarni/purl, which was implemented before GAE provided cURL support. Hope it is helpful:)

Send emails to multiple recipients zend 2

i wan't to send the same mail to multiple recipients retreived from database, using zend framework 2. With my solution i can only display all emails from database but i can't send mails to them. I do not no what's the problem exactly. This is my action in the indexController:
public function eventdetailsAction() {
$id = (int) $this->params()->fromRoute('id', 0);
$this->layout()->setVariable('lang', $this->params()->fromRoute('lang', 'en_US'));
$this->layout()->setVariable('action', $this->params()->fromRoute('action', 'index'));
$request = $this->getRequest();
$aPost = $request->getPost();
if (isset($aPost['invitUser'])) {
$user = new Container('user');
$db = $this->getServiceLocator()->get('db1');
if (!$user->offsetExists('id')) {
$idconnected = '0';
} else {
$user = new Container('user');
$db = $this->getServiceLocator()->get('db1');
if (!$user->offsetExists('id')) {
$idconnected = '0';
} else {
$idconnected = $user->offsetGet('id');
$sql = "SELECT * FROM user";
$statement = $db->query($sql);
$res = $statement->execute();
if ($res instanceof ResultInterface && $res->isQueryResult()) {
$resultSet = new ResultSet;
$resultSet->initialize($res);
$message = new Message();
foreach ($resultSet as $row) {
echo $row->email . PHP_EOL;
$message->addTo($row->email)
->addTo('xxxxx#hotmail.com', 'eee#web.com')
->addFrom('xxxxx#gmail.com')
->setSubject('Invitation for the event : Event Latino');
}
// Setup SMTP transport using LOGIN authentication
$transport = new SmtpTransport();
$options = new SmtpOptions(array(
'host' => 'smtp.gmail.com',
'connection_class' => 'login',
'connection_config' => array(
'ssl' => 'tls',
'username' => 'xxxxx#gmail.com',
'password' => 'xxxxxx'
),
'port' => 587,
));
$html = new MimePart('Invitation for the event: Latin Night, orgonized by Mr. Jony Cornillon. Date : 06/04/2015');
$html->type = "text/html";
$body = new MimeMessage();
$body->addPart($html);
//$body->setParts(array($html));
$message->setBody($body);
$transport->setOptions($options);
$transport->send($message);
}
}
}
}
And this is the error displayed each time:
5.1.2 We weren't able to find the recipient domain. Please check for any
5.1.2 spelling errors, and make sure you didn't enter any spaces, periods,
5.1.2 or other punctuation after the recipient's email address. cj9sm2642949wjc.42 - gsmtp
Any help please. Thanks.

How to split the oauth logic and create the Google Calendar service

I am using php client for Google Calendar API
https://github.com/google/google-api-php-client and CakePHP.
Basically, I just want to manage the events in the calendar.
And I could do it following the example here https://github.com/google/google-api-php-client/blob/master/examples/user-example.php. It worked fine (so, I have no problems with client id, client secret etc).
The only problem is that in the example it's all written in one file - the oauth logic and service specific logic (like retrieving events from calendar). So the redirect uri in google console points to the same file.
The pseudo-code for this is:
//here we create the client which is used for authentication
$client = new Google_Client();
//some of the oauth logic
$client->authenticate($_GET['code']);
//other oauth logic
$service = new Google_Service_Calendar($client);
$events = $service->events->list();
//...
So, as you see, to create a service we need a client (which contains the access token and all the authentication data needed for service).
I want to split it, so that I have the callback where I could retrieve the client and then use it for creating the service. I could have also specify that callback in google console as a redirect uri.
I have a feeling that there should be some standard way which unfortunately I am not aware of. I broke my head thinking about how to do this, so any help is appreciated.
Thanks.
UPDATE
As it often happens, right after posting a question here I managed to do something.
After we get an access token, we need to save it into DB.
Next time, when we want to do something with the api, we create the google client again and just set the access token with the value from the DB. So that we don't need to go through the oauth logic again.
Something like this:
$accessToken = $db->getOne('SELECT token FROM users WHERE id=:id');
$client = new Google_Client();
$client->setClientId($clientId);
$client->setClientSecret($clientSecret);
$client->setRedirectUri($redirectUri);
$client->setAccessType($accessType);
$client->setScopes($scope);
$client->setAccessToken(json_encode($accessToken));
Well, it looks obvious. But still I'd like to get an answer from experts to this question:
is recreating the google client object the right approach?
Thanks.
CakePHP 3.x in Google Calendar API
Follow this steps:
Create google calendar api
https://console.developers.google.com/flows/enableapi?apiid=calendar&pli=1
Composer to install:
"google/apiclient": "^2.0"
Required google calendar api integration
https://console.developers.google.com/flows/enableapi?apiid=calendar&pli=1
https://developers.google.com/google-apps/calendar/quickstart/php
Create project and create secret key and client id Project in set
name and redirect URL
NOTE:- redirect URL must be .com and .org
domain If you develop in local machine then create follow type of
virtual host example.com and example.org Virtual host create then
Follow this step:
Set configuration file in app_globle.php
'Google' => [
'ClientID' => '7441260037.apps.googleusercontent.com',
'ClientSecret' => 'kashdjahdkjshdkjhjAs',
'RedirectUrl' => 'http://' . env("HTTP_HOST") . '/oauth2calendars',
'ClientCredentials' => WWW_ROOT . 'files'. DS.'google.txt',
'Scopes' => implode(' ', [Google_Service_Calendar::CALENDAR, Google_Service_Drive::DRIVE, Google_Service_Drive::DRIVE_FILE, Google_Service_Drive::DRIVE_APPDATA, Google_Service_Drive::DRIVE_METADATA]),
]
Route
$routes->connect('/events/add', ['controller' => 'Events', 'action' => 'add', ['_name' => 'add-event']);
$routes->connect('/events/edit/:id', ['controller' => 'Events', 'action' => 'edit', ['id' => '\d+', 'pass' => ['id'], '_name' => 'edit-event']);
$routes->connect('/events/delete/:id', ['controller' => 'Events', 'action' => 'delete', ['id' => '\d+', 'pass' => ['id'], '_name' => 'delete-event']);
Controller
use Google_Client;
use Google_Service_Calendar;
use Google_Service_Calendar_Event;
use Google_Service_Drive;
use Google_Service_Drive_DriveFile;
Authorize the google Oauth thriugh
/**
* get Google calendar client
*/
private function getClient()
{
$client = new Google_Client();
$client->setAccessType("offline");
$client->setClientId(Configure::read('Google.ClientID'));
$client->setClientSecret(Configure::read('Google.ClientSecret'));
$client->setRedirectUri(Configure::read('Google.RedirectUrl'));
$client->setScopes(Configure::read('Google.Scopes'));
$credentialsPath = Configure::read('Google.Credentials');
if (file_exists($credentialsPath)) {
$accessToken = json_decode(file_get_contents($credentialsPath), true);
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
return $this->redirect($authUrl);
}
$client->setAccessToken($accessToken);
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}
return $client;
}
/**
* Create Google Calendar event
*/
public function createCredentials()
{
$client = new Google_Client();
$client->setAccessType("offline");
$client->setClientId(Configure::read('Google.ClientID'));
$client->setClientSecret(Configure::read('Google.ClientSecret'));
$client->setRedirectUri(Configure::read('Google.RedirectUrl'));
$client->setScopes(Configure::read('Google.Scopes'));
if (isset($this->request->query['code'])) {
$client->authenticate($this->request->query['code']);
$token = json_encode($client->getAccessToken());
$credentialsPath =WWW_ROOT . 'files'. DS.'google.txt';
if (!file_exists(dirname($credentialsPath))) {
mkdir(dirname($credentialsPath), 0700, true);
}
$file = new File($credentialsPath, true);
$file->write($token);
$client->setAccessToken($token);
return $this->redirect(‘/add-event’);
}
}
Add event functionality
Public function add()
{
$client = $this->getClient();
if ($this->request->is('post')) {
$dateStart = new \DateTime($this->request->data['start_date_time'], new \DateTimeZone('Asia/Kolkata'));
$dateStart->setTimezone(new \DateTimeZone('UTC'));
$startDate = $dateStart->format('Y-m-d H:i:s');
$dateEnd = new \DateTime($this->request->data['end_date_time'], new \DateTimeZone('Asia/Kolkata'));
$dateEnd->setTimezone(new \DateTimeZone('UTC'));
$endDate = $dateEnd->format('Y-m-d H:i:s');
$guests = $this->request->data['guests'];
$eventGuest = [];
$service = new Google_Service_Calendar($client);
foreach ($guests as $key => $value) {
$eventGuest[$key]['email'] = $value;
}
$eventData = [
'summary' => $this->request->data['name'],
'location' => $this->request->data['location'],
'description' => $this->request->data['description'],
'start' => [
'dateTime' => date("c", strtotime($startDate)),
],
'end' => [
'dateTime' => date("c", strtotime($endDate)),
],
'attendees' => $eventGuest,
'reminders' => [
'useDefault' => true,
],
'visibility' => 'private',
'privateCopy' => true,
];
$event = new Google_Service_Calendar_Event($eventData);
$sendNotifications = ['sendNotifications' => true];
$calendarId = 'primary';
$eventDataResponse = $service->events->insert($calendarId, $event, $sendNotifications);
}
}

Facebook logged in user as drupal user

I wrote one facebook login module, and I am using facebook php-sdk.
Here is my code:
function facebook_block_block_view($delta='') {
$block = array();
require 'src/facebook.php';
$appid = variable_get('appid_variable', '');
$secret = variable_get('secret_variable', '');
$facebook = new Facebook(array(
'appId' => $appid,
'secret' => $secret,
));
$user = $facebook->getUser();
if ($user) {
try {
// Proceed knowing you have a logged in user who's authenticated.
$user_profile = $facebook->api('/me');
$new_user = array(
'name' => $user_profile['name'],
// 'pass' => 'Password',
'mail' => $user_profile['email'],
'signature_format' => 'full_html',
'status' => 1,
'timezone' => 'America/New_York',
'init' => 'Email',
'roles' => 'Roles',
);
$account= user_save(NULL, $new_user);
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
}
$output=' Login with facebook';
switch($delta) {
case 'facebook_login' :
$block['content'] = $output;
break;
}
return $block;
}
Now I can get user's email and name, and I also can save user's information. But how can I let the facebook user become drupal user, that the user can work as drupal globle user?
Try using the drupal function user_authenticate() to log in the user.
https://api.drupal.org/api/drupal/modules!user!user.module/function/user_authenticate/7

Resources