Please forgive my amateurism both in php and on stackoverflow.
I have a PHP script that reads emails from an office 365 mailbox, for this I use a standard connection:
$Inbox = imap_open('{Outlook.office365.com:993/imap/ssl}', 'mabal#mydomain.com', 'mypassword');
Then to read the new emails received, I used the command:
$UnRead = imap_search($Inbox, 'UNSEEN');
Starting 20221001 - October 1, 2022, Microsoft will remove this authentication and require OAuth2 authentication.
I registered my web application at Microsoft Azure and tried several settings. I have done a lot of research that allows me to connect to the mailbox to be able to read the mails without going through an interaction with a user. I've found nothing.
Does anyone have a step-by-step solution to retrieve a variable bound to an "imap_open" or do you have to use a completely different system.
Thanks for your help.
It's been a wild ride for me and my coworkers but we found a solution.
1 - Configure your mail box in Azure
(I didn't do this part so i can't help you more than that ! )
Edit : Thanks to parampal-pooni, this link explains how to configurate in azure.
You will need :
The client Id
The tenant Id
The secret client
The redirect Uri (Set it to http://localhost/test_imap)
2 - Grab a code to get a token
Construct this url :
$TENANT="5-48...";
$CLIENT_ID="c-9c-....";
$SCOPE="https://outlook.office365.com/IMAP.AccessAsUser.All";
$REDIRECT_URI="http://localhost/test_imap";
$authUri = 'https://login.microsoftonline.com/' . $TENANT
. '/oauth2/v2.0/authorize?client_id=' . $CLIENT_ID
. '&scope=' . $SCOPE
. '&redirect_uri=' . urlencode($REDIRECT_URI)
. '&response_type=code'
. '&approval_prompt=auto';
echo($authUri);
Go to the link, connect to the mail box with the passeword.
Once it done, you will be redirect to : http://localhost/test_imap?code=LmpxSnTw...&session_state=b5d713....
Save the code (remove the '&' at the end !) and the session state inside the url.
These codes expired after a few hours !
3 - Get an access token
$CLIENT_ID="c-9c-....";
$CLIENT_SECRET="Y~tN...";
$TENANT="5-48...";
$SCOPE="https://outlook.office365.com/IMAP.AccessAsUser.All offline_access";
$CODE="LmpxSnTw...";
$SESSION="b5d713...";
$REDIRECT_URI="http://localhost/test_imap";
echo "Trying to authenticate the session..";
$url= "https://login.microsoftonline.com/$TENANT/oauth2/v2.0/token";
$param_post_curl = [
'client_id'=>$CLIENT_ID,
'scope'=>$SCOPE,
'code'=>$CODE,
'session_state'=>$SESSION,
'client_secret'=>$CLIENT_SECRET,
'redirect_uri'=>$REDIRECT_URI,
'grant_type'=>'authorization_code' ];
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POSTFIELDS, http_build_query($param_post_curl));
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
$oResult=curl_exec($ch);
echo "result : \n";
var_dump($oResult);
The access_token given in response is going to work only for a few hours. ( If your script is going to be launch on a daily basic you need to recreate a token. I'm going to show you how in the part 5 ! Save the refresh_token inside $oResult. If you don't have the "refresh_token" you have forgot to put "offline_access" in the scope)
Edit : I forgot to add the redirect_uri in this step, thank jose ayram
4 - Connect to the mail box
Now choose your favorite library ;) ! We will use webklex/php-imap for this example (https://github.com/Webklex/php-imap)
include __DIR__.'/vendor/autoload.php';
use Webklex\PHPIMAP\ClientManager;
$access_token="EH.j8s5z8...";
//$cm = new ClientManager($options = ["options" => ["debug" => true]]);
$cm = new ClientManager();
$client = $cm->make([
'host' => 'outlook.office365.com',
'port' => 993,
'encryption' => 'ssl',
'validate_cert' => false,
'username' => 'mymailbox#domain.com',
'password' => $access_token,
'protocol' => 'imap',
'authentication' => "oauth"
]);
try {
//Connect to the IMAP Server
$client->connect();
$folder = $client->getFolder('INBOX');
$all_messages = $folder->query()->all()->get();
//DONE ! :D
} catch (Exception $e) {
echo 'Exception : ', $e->getMessage(), "\n";
}
5 - Connecting to the mail box everyday
include __DIR__.'/vendor/autoload.php';
use Webklex\PHPIMAP\ClientManager;
$CLIENT_ID="c-9c-....";
$CLIENT_SECRET="Y~tN...";
$TENANT="5-48...";
$REFRESH_TOKEN="EebH9H8S7...";
$url= "https://login.microsoftonline.com/$TENANT/oauth2/v2.0/token";
$param_post_curl = [
'client_id'=>$CLIENT_ID,
'client_secret'=>$CLIENT_SECRET,
'refresh_token'=>$REFRESH_TOKEN,
'grant_type'=>'refresh_token' ];
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POSTFIELDS, http_build_query($param_post_curl));
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
//ONLY USE CURLOPT_SSL_VERIFYPEER AT FALSE IF YOU ARE IN LOCALHOST !!!
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, false);// NOT IN LOCALHOST ? ERASE IT !
$oResult=curl_exec($ch);
echo("Trying to get the token.... \n");
if(!empty($oResult)){
echo("Connecting to the mail box... \n");
//The token is a JSON object
$array_php_resul = json_decode($oResult,true);
if( isset($array_php_resul["access_token"]) ){
$access_token = $array_php_resul["access_token"];
//$cm = new ClientManager($options = ["options" => ["debug" => true]]);
$cm = new ClientManager();
$client = $cm->make([
'host' => 'outlook.office365.com',
'port' => 993,
'encryption' => 'ssl',
'validate_cert' => false,
'username' => 'mymailbox#domain.com',
'password' => $access_token,
'protocol' => 'imap',
'authentication' => "oauth"
]);
try {
//Connect to the IMAP Server
$client->connect();
}catch (Exception $e) {
echo 'Exception : ', $e->getMessage(), "\n";
}
}else{
echo('Error : '.$array_php_resul["error_description"]);
}
}
I hope it will help you.
Execute this curl
Replace client_id, client_secret and tenant_id
In scope you can try to use https://outlook.office365.com/.default, https://graph.microsoft.com/.default or https://outlook.office.com/.default
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d 'client_id={CLIENT_ID}&scope=https%3A%2F%2Foutlook.office365.com%2F.default&client_secret={CLIENT_SECRET}&grant_type=client_credentials' 'https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token'
PHP-imap login
<?php
// ....
$instance = new ClientManager();
$this->client = $instance->make([
'host' => "outlook.office365.com",
'port' => "993",
'encryption' => 'ssl',
'validate_cert' => true,
'username' => "email#outlook.com",
'password' => $curlAcessToken, // Access token curl
'protocol' => 'imap',
'authentication' => "oauth",
]);
I'm trying to connect to a web service using PHP's soap client which I can successfully do using Visual Studio, pressing F5 and running the page locally which works a treat.
As soon as I upload the exact same file to my apache web host, I keep getting the error: "failed to load external entity".
Here's my code with the credentials and url taken out...
Any ideas?
<?php
header("Access-Control-Allow-Origin: http://example.com");
header("Access-Control-Request-Method: GET,POST");
ini_set('display_errors', true);
ini_set("soap.wsdl_cache_enabled", "0");
error_reporting(E_ALL);
try
{
$soapclient = new SoapClient('http://example.com');
$params = array ('SystemID' => 'testID','Username' => 'test', 'Password' => 'test');
$response = $soapclient->GetEngineerList($params);
print_r($response);
}
catch(SoapFault $e)
{
print_r($e);
}
strings are not read twice and parsed in single quotes
$soapclient = new SoapClient('$url');
try
$soapclient = new SoapClient($url);
also...do you have $url = ''; anywhere?
UPDATE 1
please try using basic auth to get to your wsdl:
$login = 'bert';
$password = 'berts password';
$client = new SoapClient(
'http://' . urlencode($login) . ':' . urlencode($password) . '#www.server.com/path/to/wsdl',
array(
'login' => $login,
'password' => $password
)
);
I have a function which handles the SOAP based web service.
When I run the function via URL I am getting XML response. but when I run the function through CRON I am not getting xml response.
<?php
$logFile = 'checking'.date('Y-m-d').'.log';
$client = new SoapClient("http://DOMAIN/services/weburl?wsdl",array( "trace" => true, 'use' => SOAP_LITERAL));
$params = array('username' => 'username', 'Password' => 'password', 'delatdate' => '17/06/2015 18:00:00');
try{
$response = $client>-productOnHand($params);
} catch(SoapFault $e){
echo $e->faultcode; echo '<br />';
echo $e->getMessage(); echo '<br />';
}
require_once 'app/Mage.php';
Mage::app();
Mage::log(print_r($response, true), null, $logFile);
Mage::log(print_r($client->__getLastResponse(), true), null, $logFile);
?>
If I run this web page via URL I am getting valid xml response. But when this page is being called through CRON I am not getting valid response.
I fixed this issue.
Before default_socket_timeout was set as 60. I raised it as 600. Now I could able to receive.
I have a really strange problem in PHP with the Facebook API. All this code is working in my testing server (shared hosting). But when I run it in the production server (Heroku) I get an error.
What I am trying to do is to receive realtime updates from Facebook when my app users likes (or unlikes) a new page.
This is the documentation that Facebook provides: https://developers.facebook.com/docs/graph-api/real-time-updates
My code to subscribe:
$facebook = new Facebook(array(
'appId' => $app_id,
'secret' => $app_secret,
'cookie' => true
));
$facebook->api(
"/" . $app_id . "/subscriptions", "POST", array(
'object' => 'user',
'callback_url' => 'http://' . $url . '/rtu/callback',
'fields' => 'likes',
'verify_token' => $rtu_verify_token,
'access_token' => $app_id . "|" . $app_secret
)
);
My code in the callback:
if (isset($_GET['hub_verify_token']) && isset($_GET['hub_challenge'])) {
$rtu_verify_token = Config::get('variables.rtu_verify_token');
if (($_GET['hub_verify_token'] == $rtu_verify_token)) {
echo $_GET['hub_challenge'];
die();
}
}
$data = file_get_contents("php://input");
$json = json_decode($data);
The error:
FacebookApiException (#2200) callback verification failed: Operation
timed out after 6001 milliseconds with 0 bytes received
I have already verify the app_id, url and the app_secret variables.
Again, this works in my testing server, but not in Heroku.
I even tried not to use the Facebook API and make a cURL call, but I got the same error.
I'm thinking that maybe has something to do with Heroku, but i couldn't find any evidence.
Thanks
Your server must be reachable from the internet, and be able to process concurrent requests, because facebook sends verification requests simultaneously.
I'm unable to get any results following to post a tweet from php. I've registered my app with twitter and got my credentials. I've made a page called access_tokens.php, and downloaded an OAuth library called tmhOAuth.php. I'm following an example tutorial exactly, and nothing seems to be appearing - is there any help that can be offered?
access_tokens.php
<?php
$consumer_key = 'xx';
$consumer_secret = 'xx';
$user_token = 'xx';
$user_secret = 'xx';
//xx is the replacement for my actual values
?>
post_tweet.php
<?php
//Load the app's keys into memory
require 'app_tokens.php';
//Load the tmOAuth library
require 'tmhOAuth.php';
//Create an OAuth connection to the Twitter API
$connection = new tmhOAut(array(
'consumer_key' => $consumer_key,
'consumer_secret'=> $consumer_secret,
'user_token' => $user_token,
'user_secret' => $user_secret
));
//Send a tweet
$code = $connection -> request('POST',
$connection -> url('1.1/statuses/update'),
array('status' => 'Hello Twitter'));
//A response code of 200 is a success
if ($code == 200){
print "Tweet sent";
}
else{
print "Error:$code";
}
?>
Find if that OAuth library has support yet, because I tried to do the same thing some months ago and I found some posts telling that since march it couldn't be used no more. Anyway, I'm not sure if it was that library, but if you code twitter related you have to be aware that they change their API often.