Время истечения токена входа в систему через gmail api

У меня есть тестовое приложение, которое постоянно запускается для загрузки количества сообщений в папку "Входящие" учетной записи Gmail. Я подключаюсь через gmail-api, чтобы запросить токен входа и войти в учетную запись. Проблема, с которой я сталкиваюсь, заключается в том, что на каждой итерации время истечения токена доступа составляет 3600 с, то есть оно никогда не меняется. Нужно ли мне каждый раз перезагружать токен доступа, чтобы узнать, нужно ли ему обновляться, или API справится с этим для меня?

ImapClient является частью AE.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(): '* СОСТОЯНИЕ "Входящие" (СООБЩЕНИЯ 1)'

GetResponse (): "xm070 ОК, успех"

Сообщения в папке "Входящие": 1

Срок действия токена истекает через 3600

GetResponse(): '* СОСТОЯНИЕ "Входящие" (СООБЩЕНИЯ 1)'

GetResponse (): "xm071 ОК, успех"

Сообщения в папке "Входящие": 1

Срок действия токена истекает через 3600

После работы в течение примерно 3100 секунд это дало мне следующее исключение, которое, по моему мнению, связано с истечением срока действия токена.

IMAP Exception: Невозможно записать данные в транспортное соединение: установленное соединение было прервано программным обеспечением на вашем хост-компьютере.

System.IO.IOException: невозможно записать данные в транспортное соединение: установленное соединение было прервано программным обеспечением на вашем хост-компьютере. ---> System.Net.Sockets.SocketException: установленное соединение было прервано программным обеспечением на вашем хост-компьютере

в System.Net.Sockets.Socket.Send(буфер Byte[], смещение Int32, размер Int32, SocketFlags socketFlags)

в System.Net.Sockets.NetworkStream.Write(буфер Byte[], смещение Int32, размер Int32)

--- Конец внутренней трассировки стека исключений ---

в System.Net.Sockets.NetworkStream.Write(буфер Byte[], смещение Int32, размер Int32)

в System.Net.Security._SslStream.StartWriting(буфер Byte[], смещение Int32, число Int32, AsyncProtocolRequest asyncRequest)

в System.Net.Security._SslStream.ProcessWrite(буфер Byte[], смещение Int32, число Int32, AsyncProtocolRequest asyncRequest)

в System.Net.Security.SslStream.Write(буфер Byte[], смещение Int32, количество Int32)

в AE.Net.Mail.TextClient.SendCommand(команда String)

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

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

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

в AE.Net.Mail.TextClient.Dispose(логическое удаление)

в AE.Net.Mail.ImapClient.Dispose(логическое удаление)

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

в GmailOAuth.Program.DoWork() в

c:\Projects\Development\EmailSystem\GmailOAuth\GmailOAuth\Program.cs: строка 82

1 ответ

Решение

Как указано в документации 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() способ проверить, не истек ли токен.

if (credential.Token.IsExpired(credential.Flow.Clock))
{
    //refresh your token
} 
else 
{
    //your method call
}
Другие вопросы по тегам