PHP - 使用 OAuth 连接邮箱 Office 365

PdM*_*dMM 18 php oauth-2.0

请原谅我在 php 和 stackoverflow 上的业余。我有一个 PHP 脚本,可以从 Office 365 邮箱读取电子邮件,为此我使用标准连接:

$Inbox = imap_open('{Outlook.office365.com:993/imap/ssl}', 'mabal@mydomain.com', 'mypassword');

然后,为了阅读收到的新电子邮件,我使用了以下命令:

$UnRead = imap_search($Inbox, 'UNSEEN');

从 20221001 到 2022 年 10 月 1 日,Microsoft 将删除此身份验证并要求 OAuth2 身份验证。

我在Microsoft Azure注册了我的 Web 应用程序并尝试了多种设置。我做了很多研究,使我能够连接到邮箱以便能够阅读邮件,而无需与用户进行交互。我什么也没找到。

有没有人有一个逐步的解决方案来检索绑定到“imap_open”的变量,或者您是否必须使用完全不同的系统。

感谢您的帮助。

Fox*_*ise 24

这对我和我的同事来说是一次疯狂的旅程,但我们找到了解决方案。

1 - 在 Azure 中配置您的邮箱

(我没有做这部分,所以我无法帮助你更多!)

编辑:感谢parampal-pooni此链接解释了如何在 azure 中进行配置。

你会需要 :

  • 客户端 ID
  • 租户 ID
  • 秘密客户
  • 重定向 Uri(将其设置为 http://localhost/test_imap)

2 - 获取代码以获取令牌

构造这个网址:

$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);
Run Code Online (Sandbox Code Playgroud)

转到链接,使用密码连接到邮箱。完成后,您将被重定向到:http://localhost/test_imap?code=LmpxSnTw...&session_state=b5d713...

保存代码(删除末尾的“&”!)和 url 内的会话状态。 这些代码在几个小时后就过期了!

3 - 获取访问令牌

$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);
Run Code Online (Sandbox Code Playgroud)

响应中给出的 access_token 只能工作几个小时。(如果您的脚本要每天启动,您需要重新创建一个令牌。我将在第 5 部分中向您展示如何操作!将刷新令牌保存在 $oResult 中。如果您没有“refresh_token”您忘记将“offline_access”放入范围中)

编辑:我忘记在这一步中添加redirect_uri,谢谢jose ayram

4 - 连接到邮箱

现在选择您最喜欢的库;)!我们将在此示例中使用 webklex/php-imap ( 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";
}
Run Code Online (Sandbox Code Playgroud)

5 - 每天连接到邮箱

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"]); 
    }
}   
Run Code Online (Sandbox Code Playgroud)

我希望它能帮助你。

  • 谢谢。这对我有用。只是你必须在步骤3中添加redirect_uri (2认同)
  • 你是对的 !我刚刚编辑了我的答案。非常感谢:) https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow (2认同)
  • 就是这个。这是价值数百万美元的解决方案。Microsoft 不支持 client_credential + IMAP 授权,但他们尚未更新其文档以反映此功能仍然不可用。非常感谢您提供这个。 (2认同)
  • 要帮助完成第 1 步,请转到此处:https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app (2认同)