Integrate Sendgrid with Symfony2 - php

I have a problem trying to integrate sendgrid library in Symfony2. We have copied the library inside our bundle and we have included it in a service. If this service is called by an action, the library it is running successfully.
This is the service:
use Symfony\Component\DependencyInjection\ContainerInterface;
require_once(__DIR__.'/SendgridPhp/sendgrid-php.php');
class MailerService extends \Twig_Extension {
protected $container;
private $mailer;
private $templating;
public function __construct(ContainerInterface $container,$mailer,$templating)
{
$this->container= $container;
$this->mailer = $mailer;
$this->templating=$templating;
}
public function sendEmail($to, $from, $subject, $body, $attachment = null)
{
$sendgrid = new \SendGrid($this->container->getParameter('sendgrid_user'), $this->container->getParameter('sendgrid_password'));
$email = new \SendGrid\Email();
$email->setFrom($from)
->setFromName('Name')
->setSubject($subject)
->addTo($to)
->setHtml($body, 'text/html');
$salida = $sendgrid->send($email );
}
}
The problem happens when we call this service from a symfony2 command.
$mailerService = $container->get('mailer.service');
$mailerService->sendEmail($user->getEmail(), $container->getParameter("sender_email"), 'Message', $body);
The error in namespace is the next:
PHP Fatal error: Class 'SendGrid\Email' not found in /var/www/SpainStartup/src/SpainStartup/CommunicationBundle/Services/MailerService.php on line 35
Should we do something special to load the library in command context ?
Thanks in advance

You'll need to autoload the library. The files for third-party code usually go in the vendor folder. You can add it to your composer.json in the require section:
{
"require": {
// Other dependencies...
"sendgrid/sendgrid": "2.0.5"
}
}
Remove what you "copied" in. Then run composer update wherever your composer.json file is located.
After this it should 'just work'.

Instead of using any sendgrid's library, I just worked upon the php example they provided on the api site. This stand-alone php code works flawlessly for me:
sendmail.php
<?php
function sendgridmail($from, $to, $subject, $message, $headers)
{
print_r('entering the function');
$url = 'https://api.sendgrid.com/';
$user='shinujacob';
$pass='mypassword';
$params = array(
'api_user' => $user,
'api_key' => $pass,
'to' => $to,
'subject' => $subject,
'html' => '',
'text' => $message,
'from' => $from,
);
$request = $url.'api/mail.send.json';
// Generate curl request
$session = curl_init($request);
// Tell curl to use HTTP POST
curl_setopt ($session, CURLOPT_POST, true);
// Tell curl that this is the body of the POST
curl_setopt ($session, CURLOPT_POSTFIELDS, $params);
// Tell curl not to return headers, but do return the response
curl_setopt($session, CURLOPT_HEADER, false);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
//print_r('obtaining the response');
// obtain response
$response = curl_exec($session);
print_r('closing curl session');
curl_close($session);
// print everything out
//print_r($response);
}
//only for testing:
/*$to = 'shinujacobrocks#yahoo.com';
$subject = 'Testemail';
$message = 'It works!!';
echo 'To is: ' + $to;
#wp_mail( $to, $subject, $message, array() );
sendgridmail($to, $subject, $message, array());
print_r('Just sent!');*/

Related

Azure Marketplace SaaS fulfilment API- resolving subscription - PHP

I am trying to resolve an azure marketplace subscription using the azure fulfilment api. I have followed the instructions on the Microsoft's SaaS fulfilment api's docs but I am not able to resolve the subscription using PHP.
I am able to get access_token and incidentally I am able to use the token and and use this together with the purchase identification token i get from azure portal when the subscriber is re-directed to the SaaS landing page, to get a successful json response when using postman.
I cannot achieve the same success when using PHP. I get a 403 error - Authorization is missing, incorrect or invalid. I am thinking that the query string bit of authorization parameter is malformed. This has nothing to do with privileges or permissions as I am able to get a successful output on Postman. Here is the code
<?php
use Microsoft\Graph\Graph;
use Microsoft\Graph\Http;
use Microsoft\Graph\Model;
use GuzzleHttp\Client;
class GraphHelper {
private static Client $tokenClient;
private static Client $tokenWebClient;
private static string $clientId = '';
private static string $tenantId = '';
private static string $clientSec = '';
private static string $graphUserScopes = '';
private static Graph $userClient;
private static string $userToken;
private static string $resolveToken;
private static string $subToken= '';
public static function initializeGraphForUserAuth(): void {
GraphHelper::$tokenClient = new Client();
GraphHelper::$clientId = $_ENV['CLIENT_ID'];
GraphHelper::$clientSec = $_ENV['CLIENT_SECRET'];
GraphHelper::$tenantId = $_ENV['TENANT_ID'];
GraphHelper::$graphUserScopes = $_ENV['GRAPH_USER_SCOPES'];
GraphHelper::$userClient = new Graph();
}
public static function getUserToken(): void {
//getting the access token
$accessCodeRequestUrl = 'https://login.microsoftonline.com/'.GraphHelper::$tenantId.'/oauth2/token';
$tokenRequestUrl = 'https://marketplaceapi.microsoft.com/api/saas/subscriptions/resolve?api-version=2018-08-31';
$subToken = $_SESSION['subToken'];
$tokenResponse = GraphHelper::$tokenClient->post($accessCodeRequestUrl, [
'form_params' => [
'client_id' => GraphHelper::$clientId,
'grant_type' => 'client_credentials',
'client_secret' => GraphHelper::$clientSec,
'resource' => '20e940b3-4c77-4b0b-9a53-9e16a1b010a7'
],
// These options are needed to enable getting
// the response body from a 4xx response
'http_errors' => false,
'curl' => [
CURLOPT_FAILONERROR => false
]
]);
if ($tokenResponse->getStatusCode() == 200) {
// Return the access_token
$responseBody = json_decode($tokenResponse->getBody()->getContents());
GraphHelper::$resolveToken = $responseBody->access_token;
$resolveAccessToken= $responseBody->access_token;
} else if ($tokenResponse->getStatusCode() == 400) {
// Check the error in the response body
$responseBody = json_decode($tokenResponse->getBody()->getContents());
if (isset($responseBody->error)) {
$error = $responseBody->error;
// authorization_pending means we should keep polling
if (strcmp($error, 'authorization_pending') != 0) {
throw new Exception('Token endpoint returned '.$error, 100);
}
}
}
//resolving the subscription
$resolveResponse = GraphHelper::$tokenClient->post($tokenRequestUrl, [
'form_params' => [
'content-type' => 'application/json',
'authorization' => 'Bearer '.$resolveAccessToken,
'x-ms-marketplace-token'=> $subToken
],
// These options are needed to enable getting
// the response body from a 4xx response
'http_errors' => false,
'curl' => [
CURLOPT_FAILONERROR => false
]
]);
//test whether there is a reponse
return $resolveResponse->getStatusCode(); // this returns a 403 - Authorization is missing, incorrect or invalid.
}
}
?>
I figured out that I needed to use cUrl for option to include authorization and other headers. Postman did this automatically hence the reason I was able to get results with postman and not with PHP. Eventually this code did it for me.
$subToken = rawurldecode($_SESSION['subToken']);
$ch = curl_init ();
curl_setopt ($ch, CURLOPT_URL, $tokenRequestUrl);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_HTTPHEADER, array ('Authorization: Bearer '.GraphHelper::$resolveToken,
'Content-type: application/json',
'X-ms-marketplace-token:'. $subToken));
curl_setopt($ch, CURLOPT_POST, true);
$results = json_decode (curl_exec ($ch), 1);
if (array_key_exists ('error', $results)){
echo ($results['error']);
die();
}
curl_close($ch);
return $results['subscriptionName'] ;
I found out that the endpoint was not accepting a get request. It threw an error of Subscription resolve not found","target":"subscriptionId","code":"EntityNotFound . However including a post option corrected that and no error was thrown after this. Again when decoding the token from the url - don't use urldecode() use rawurldecode () instead.

Why GuzzleHttp client throws ClientException when using it to make network request on Laravel/Lumen?

I am currently building a Financial micro service application using Laravel/Lumen micro framework.Everything have been working perfectly as expected. My problem now is that i am trying to make a network request to my internal services via Api call from ApiGateway using GuzzleHttp client. The problem is that when i make request to the internal service, it always throws an exception of ClientException.
ClientException.
Client error: GET http://127.0.0.1:8081/v1/admin resulted in a 401
Unauthorized response: {"error":"Unauthorized.","code":401}
I have tried to make network request to the same internal services using postman; and it works fine. However, for some reason still fail to work with GuzzleHttp. I don't know what i am doing wrong. Please your assist will be appreciated.
Here is the httpClient.php in ApiGateway.
//Constructor method
public function __construct() {
$this->baseUri = config('services.auth_admin.base_uri');
}
public function httpRequest($method, $requestUrl, $formParams = [], $headers = []) {
//Instantiate the GazzleHttp Client
$client = new Client([
'base_uri' => $this->baseUri,
]);
//Send the request
$response = $client->request($method, $requestUrl, ['form_params' => $formParams, 'headers' => $headers]);
//Return a response
return $response->getBody();
}
//Internal Service Communication in ApiGateway**
public function getAdmin($header) {
return $this->httpRequest('GET', 'admin', $header);
}
InternalServiceController.php
public function getAdmin(Request $request) {
return $this->successResponse($this->authAdminService->getAdmin($request->header()));
}
I am using Lumen version: 5.8 and GuzzleHttp Version: 6.3
You pass your headers as formParams (third index instead of fourth).
Try below:
return $this->httpRequest('GET', 'admin', [], $header);
I am making some assumptions here which I hope should be helpful to you.
PHP does not support skipping optional parameters and thus you should pass an empty array [] when calling httpRequest().
public function httpRequest($method, $requestUrl, $formParams = [], $headers = [], $type='json', $verify = false) {
//Instantiate the GazzleHttp Client
$client = new Client([
'base_uri' => $this->baseUri,
]);
//the request payload to be sent
$payload = [];
if (!$verify) {
$payload['verify'] = $verify; //basically for SSL and TLS
}
//add the body to the specified payload type
$payload[$type] = $formParams;
//check if any headers have been passed and add it as well
if(count($headers) > 0) {
$payload['headers'] = $headers;
}
//Send the request
$response = $client->request($method, $requestUrl, $payload);
//Return a response
return $response->getBody();
}
Now you need to call it in this manner when you are not passing in any form_params or body
//Internal Service Communication in ApiGateway**
public function getAdmin($header) {
return $this->httpRequest('GET', 'admin', [], $header);
}

Symfony 3: Curl GET timeout when used from a controller but work from command side

I try to find a solution to this problem for the past few days but i dont find what is the issue here.
So the problem is simple but realy weird. I cant use curl (GET) from a controller in symfony.
I try to implement a simple form, You enter your mail in a form, send it, then it called the API from haveibeenpwned.com (great site, you should check ! ). The answer is basicly telling you if your mail has been "hacked", by sending you a json format string.
So i try my code in a simple php script. -> OK
Try my code in a command, and use the command on the server. -> OK
I call the command in my controller. -> FAIL
I test my curl script in the controller. -> FAIL
All time the code fail it's always "error : Failed connect to haveibeenpwned.com:443; Operation now in progress"
But since the code actualy work in a simple PHP script, and when i used the command I create on server side, i dont understant why the controller fail.
Here are the command
class checkMailCommand extends ContainerAwareCommand {
protected function configure()
{
$this
->setName('curl:checkMail')
->setDescription('Check Mail')
->addArgument('emailCheck', InputArgument::REQUIRED, 'What\'s the email address we check?');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$account = $input->getArgument('emailCheck');
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://haveibeenpwned.com/api/v2/breachedaccount/".$account,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"User-Agent: Pwnage-Checker-For-Safe-Portal",
"api-version: 2"
),
));
$output->writeln($curl);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err){
$output->writeln("error : ".$err);
}
else{
$output->writeln($response);
}
}
}
and the controller function:
public function checkMailAction(Request $request)
{
$form = $this->createForm(checkMailType::class);
$form->handleRequest($request);
$message = null;
$response = null;
if ($form->isSubmitted() && $form->isValid()) {
$kernel = $this->get('kernel');
$application = new Application($kernel);
$application->setAutoExit(false);
$input = new ArrayInput(array(
'command' => 'curl:checkMail',
'emailCheck' => $form["checkMail"]->getdata()
));
$output = new BufferedOutput();
$application->run($input, $output);
// return the output
$response = $output->fetch();
//$response = json_decode($response, true);
}
return $this->render('EXTgetcurlBundle:hibp:check.html.twig', array(
"message" => $message,
"response" => $response,
"form" => $form->createView(),
));
}
To be very clear, this code is working like a charm when i use it on my server, with the command
php bin/console curl:checkMail [mail]
and when i use it inside a simple test.php" and print_r the result.
If someone have any idea, it would be very appreciate.

Slim framework get the data from a form

I try to make a simple form with SLIM framework.
I don't know how to display the posted data. I want just to try to echo it.
I heard that I need to use extra library RESPECT, I think SLIM can do such small thing.
here is my code :
require '../../vendor/slim/slim/Slim/Slim.php';
\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim();
$app->get('/', function() use ($app){
$app->render('form.php');
});
$app->post('/', function() use ($app){
$req = $app->request();
$errors = array();
$params = array(
'email' => array(
'name'=>'Email',
'required'=>true,
'max_length'=>64,
),
'subject' => array(
'name'=>'Subject',
'required'=>true,
'max_length'=>256,
),
);
//submit_to_db($email, $subject, $message);
$app->flash('message','Form submitted!');
$app->redirect('./');
});
$app->run();
In Slim 2, you can access to your posted data using post() method of request():
$app->post('/', function () use ($app) {
$request = $app->request();
$email = $request->post('Email');
$subject = $request->post('Subject');
echo "Email: $email<br/>";
echo "Subject: $subject";
});
In Slim 3, the request is passed to the callback/controller/etc. and you can call getParam() which fetches the value from body or query string (in that order):
$app->post('/', function ($request, $response, $args) {
$email = $request->getParam('Email');
$subject = $request->getParam('Subject');
echo "Email: $email<br/>";
echo "Subject: $subject";
});
Starting from Slim 3.1 there are also getParsedBodyParam() and getFetchParam() which fetch only from body or query string. (PR #1620)
Just as a reminder, you can provide a default value: $request->getParam('Email', 'default_value')

Sending email does not work when I use my helper in Yii php

I'm using Yii framework while my question is probably intended to PHP expert.
I have created a controller to send email from my web application, it works fine.
Given that, I intend to use email in several sontrollers in my app, I wanted to created a helper but that does not work. Email is not sent. (I'm using swiftmailer)
The code of the working controller is the following:
<?php
class MailController extends Controller
{
/**
* Declares class-based actions.
*/
public function actionSendemail() {
// Plain text content
$plainTextContent = "This is my first line ;-)\nThis is my second row of text";
// Get mailer
$SM = Yii::app()->swiftMailer;
// New transport mailHost= localhost, mailPort = 25
$Transport = $SM->smtpTransport(Yii::app()->params['mailHost'], Yii::app()->params['mailPort']);
// Mailer
$Mailer = $SM->mailer($Transport);
// New message
$Message = $SM
->newMessage('My subject')
->setFrom(array('test1#localhost.localdomain' => 'Example Name'))
->setTo(array('myemail#domain.com' => 'Recipient Name'))
// ->addPart($content, 'text/html')
->setBody($plainTextContent);
// Send mail
$result = $Mailer->send($Message);
}
}
The helper code is the following
<?php
// protected/components/Email.php
class Email {
public static function sendEmail($subject, $from, $to, $body)
{
// Get mailer
$SM = Yii::app()->swiftMailer;
// New transport
$Transport = $SM->smtpTransport(Yii::app()->params['mailHost'], Yii::app()->params['mailPort']);
// Mailer
$Mailer = $SM->mailer($Transport);
// New message
$Message = $SM
->newMessage($subject)
->setFrom(array($from => 'Example Name'))
->setTo(array($to => 'Recipient Name'))
// ->addPart($content, 'text/html')
->setBody($body);
// Send mail
$result = $Mailer->send($Message);
}
}
the way I call it is the following
$subject= 'My subject';
$from = Yii::app()->params['adminEmail']; // adminEmai is a globalparam like above controller
$to='xxxx#xxx.com';
$body='my body';
Email::sendEmail($subject, $from, $to, $body);
when I run this code, I have no error, but I dont receive the email.
Thank you for your help.
I found my error.
my global parameters in config.php was not set correctly.
So content I put in the from field was not recognized by my hmailserver which is configured for the moment with the content test1#localhost.localdomain
sorry for the question and thanks

Categories