Tag Archives: imap

Connect to 365 Exchange mailbox with IMAP and OAuth

Source: https://stackoverflow.com/questions/73370661/php-connect-mailbox-office-365-with-oauth

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-poonithis 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 !

When you are on this new page look inside the url, you should have htp:/localhost/test_imap?code=MyCodeIShouldSave&session_state=MySessionIShouldSave This is the $CODE and the $SESSION you are looking for for the step 3

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. (It are in the middle of the output).
If you don’t have the “refresh_token” you have forgot to put “offline_access” in the scope)

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'      => '[email protected]',
    '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'      => '[email protected]',
            '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"]); 
    }
}

It will only connect to the mailbox, you then need to write some more code to get access to the mail. Look at https://github.com/Webklex/php-imap