通过 gmail 的登录令牌的到期时间 api

Expiry time of a login token through gmail api

我有一个测试平台应用程序,它不断运行以下载 gmail 帐户收件箱中的邮件数量。我通过 gmail-api 连接以请求登录令牌并登录帐户。我面临的问题是,在每次迭代中,访问令牌的到期时间为 3600 秒,即它永远不会改变。我是否需要每次都重新下载访问令牌以查看它是否需要刷新,或者 api 是否为我处理了这个?

ImapClientAE.Net 库的一部分。

见以下代码:

try
{
    X509Certificate2 certificate = new X509Certificate2("certificate.p12", "notasecret", X509KeyStorageFlags.Exportable);
    ServiceAccountCredential credential = new ServiceAccountCredential(new ServiceAccountCredential
        .Initializer("Service account address")
    {
        //Note: other scopes can be found here: https://developers.google.com/gmail/api/auth/scopes
        Scopes = new[] { "https://mail.google.com/" },
        User = "email address"
    }.FromCertificate(certificate));

    Task<bool> result = credential.RequestAccessTokenAsync(CancellationToken.None);
    if (!result.Result)
    {
        Console.WriteLine("Failed to connect to gmail!");
    }

    using (ImapClient imap = new ImapClient())
    {
        imap.AuthMethod = ImapClient.AuthMethods.SaslOAuth;

        imap.Connect("imap.gmail.com", 993, true, false);
        if (!imap.IsConnected)
        {
            throw new Exception("Unable to connect to the host");
        }

        imap.Login("email address", credential.Token.AccessToken);
        if (!imap.IsAuthenticated)
        {
            throw new Exception("Currently not authenticated (2)?");
        }

        string sourceMailBox = "Inbox";
        imap.SelectMailbox(sourceMailBox);

        while (true)
        {
            int messageCount = imap.GetMessageCount(sourceMailBox);

            Console.WriteLine("Messages in '" + sourceMailBox + "': " + messageCount);
            Console.WriteLine("Token expires in {0}s", credential.Token.ExpiresInSeconds);

            System.Threading.Thread.Sleep(10000);
        }
    }
}
catch(Exception ex)
{
    Console.Error.WriteLine("IMAP Exception: " + ex.Message);
    Console.Error.WriteLine(ex.ToString());
}

示例输出(注意我没有写出 GetResponse 行):

GetResponse(): '* STATUS "Inbox" (MESSAGES 1)'

GetResponse(): 'xm070 OK Success'

Messages in 'Inbox': 1

Token expires in 3600s

GetResponse(): '* STATUS "Inbox" (MESSAGES 1)'

GetResponse(): 'xm071 OK Success'

Messages in 'Inbox': 1

Token expires in 3600s

在 运行 大约 3100 秒后,它给了我以下异常,我认为这是由于令牌过期造成的。

IMAP Exception: Unable to write data to the transport connection: An established connection was aborted by the software in your host machine.

System.IO.IOException: Unable to write data to the transport connection: An established connection was aborted by the software in your host machine. ---> System.Net.Sockets.SocketException: An established connection was aborted by the software in your host machine

at System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)

at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)

--- End of inner exception stack trace ---

at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)

at System.Net.Security._SslStream.StartWriting(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)

at System.Net.Security._SslStream.ProcessWrite(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)

at System.Net.Security.SslStream.Write(Byte[] buffer, Int32 offset, Int32 count)

at AE.Net.Mail.TextClient.SendCommand(String command)

at AE.Net.Mail.ImapClient.OnLogout()

at AE.Net.Mail.TextClient.Logout()

at AE.Net.Mail.TextClient.Disconnect()

at AE.Net.Mail.TextClient.Dispose(Boolean disposing)

at AE.Net.Mail.ImapClient.Dispose(Boolean disposing)

at AE.Net.Mail.TextClient.Dispose()

at GmailOAuth.Program.DoWork() in

c:\Projects\Development\EmailSystem\GmailOAuth\GmailOAuth\Program.cs:line 82

Documentation Token.ExpiresInSeconds 中指定可以为您提供令牌的到期时间,并且其值不会自动更新。如果您想知道刷新令牌的剩余时间,您必须找出令牌发出时间 (Token.Issued) 和当前时间 (Datetime.Now) 之间的差异,并检查它是否小于令牌的到期时间.

//calculate time to expire by finding difference between current time and time when token is issued

if((DateTime.Now-credential.Token.Issued).TotalSeconds>credential.Token.ExpiresInSeconds) 
{
    //refresh your token
} 
else 
{
    //your method call
}

您也可以使用Token.IsExpired()方法检查token是否过期

if (credential.Token.IsExpired(credential.Flow.Clock))
{
    //refresh your token
} 
else 
{
    //your method call
}