首页 > 解决方案 > 如何授权 gmail 使用 botframework 网络频道阅读我的收件箱

问题描述

我正在尝试使用 gmail 服务来读取收件箱数据并将它们显示在我的聊天机器人中。我想使用我的 gmail 帐户进行身份验证。当我在机器人模拟器中测试聊天机器人工作正常时,当我在 web 上部署时问题就开始了。我无法在 web 上进行身份验证。

string jsonPath2 = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "client_secret_webapp.json";


        UserCredential credential;

        string[] Scopes = { GmailService.Scope.GmailReadonly };
        string credPath = System.Environment.GetFolderPath(
           System.Environment.SpecialFolder.Personal);



        using (var stream = new FileStream(jsonPath2, FileMode.Open, FileAccess.Read))
        {
            credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                GoogleClientSecrets.Load(stream).Secrets,
                // This OAuth 2.0 access scope allows for read-only access to the authenticated 
                // user's account, but not other types of account access.
                new[] { GmailService.Scope.GmailReadonly,},
                "xxxx@gmail.com",
                CancellationToken.None,
                new FileDataStore(this.GetType().ToString())
            );
        }
        var gmailService = new GmailService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = this.GetType().ToString()
        });

        log.Info("ApplicationName" + ApplicationName);

        var emailListRequest = gmailService.Users.Messages.List("xxxxx@gmail.com");
        emailListRequest.LabelIds = "INBOX";
        emailListRequest.MaxResults = 1;
        emailListRequest.Q = "is:unread";
        emailListRequest.IncludeSpamTrash = false;




        if (emailListResponse != null && emailListResponse.Messages != null)
        {
            //loop through each email and get what fields you want... 
            foreach (var email in emailListResponse.Messages)
            {

                var emailInfoRequest = gmailService.Users.Messages.Get("xxxxxx@gmail.com", email.Id);

                var emailInfoResponse = emailInfoRequest.Execute();



                if (emailInfoResponse != null)
                {
                    String from = "";
                    String date = "";
                    String subject = "";
                    String body = "";
                    //loop through the headers to get from,date,subject, body  
                    foreach (var mParts in emailInfoResponse.Payload.Headers)
                    {


                        if (mParts.Name == "Date")
                        {
                            date = mParts.Value;
                        }
                        else if (mParts.Name == "From")
                        {
                            from = mParts.Value;
                        }
                        else if (mParts.Name == "Subject")
                        {
                            subject = mParts.Value;
                        }

                        if (date != "" && from != "")
                        {




                            if (emailInfoResponse.Payload.Parts == null && emailInfoResponse.Payload.Body != null)
                                body = DecodeBase64String(emailInfoResponse.Payload.Body.Data);
                            else
                                body = GetNestedBodyParts(emailInfoResponse.Payload.Parts, "");




                        }

                    }
                    await context.PostAsync("Email list for: Date " + date + " :::::::::::  From:  " + from + " ::::::::::::  Subject  " + subject + " : :::::::::::::  Body :  " + body + " Email.id eshte " + email.Id);

                }

            }

        }

    }


    static String DecodeBase64String(string s)
    {
        var ts = s.Replace("-", "+");
        ts = ts.Replace("_", "/");
        var bc = Convert.FromBase64String(ts);
        var tts = Encoding.UTF8.GetString(bc);

        return tts;
    }


    static String GetNestedBodyParts(IList<MessagePart> part, string curr)
    {
        string str = curr;
        if (part == null)
        {
            return str;
        }
        else
        {
            foreach (var parts in part)
            {
                if (parts.Parts == null)
                {
                    if (parts.Body != null && parts.Body.Data != null)
                    {
                        var ts = DecodeBase64String(parts.Body.Data);
                        str += ts;
                    }
                }
                else
                {
                    return GetNestedBodyParts(parts.Parts, str);
                }
            }

            return str;
        }
    }







    private static byte[] FromBase64ForUrlString(string base64ForUrlInput)
    {
        int padChars = (base64ForUrlInput.Length % 4) == 0 ? 0 : (4 - (base64ForUrlInput.Length % 4));
        StringBuilder result = new StringBuilder(base64ForUrlInput, base64ForUrlInput.Length + padChars);
        result.Append(String.Empty.PadRight(padChars, '='));
        result.Replace('-', '+');
        result.Replace('_', '/');
        return Convert.FromBase64String(result.ToString());
    }

client_id.json

   {"installed":{"client_id":"xxxxxxx- yyyyyy.apps.googleusercontent.com","project_id":"reademailbot","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"yyyyyyyyyyy","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}

编辑:

我尝试添加以下代码:

   var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new 
            ClientSecrets
            {
            ClientId = "xx- 
            xxxxxxxxx.apps.googleusercontent.com",
            ClientSecret = "xxxxxxxxxxxxxxxxxxxxx-lLO"
             },
                                                            new[] { 
            GmailService.Scope.GmailReadonly,

            GmailService.Scope.MailGoogleCom, 
            GmailService.Scope.GmailMetadata 
            },
                                                            "user",

         CancellationToken.None,
                                                            new 
        FileDataStore("Drive.Auth.Store")).Result;

        var gmailService = new Google.Apis.Gmail.v1.GmailService(new 
        BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
        });

但是当我在网上尝试时,我仍然有问题:

错误:redirect_uri_mismatch

请求中的重定向 URI http://127.0.0.1:52158/authorize/与 OAuth 客户端授权的不匹配。要更新授权的重定向 URI,请访问:https ://console.developers.google.com/apis/credentials/oauthclient/673194113721-45u2pgl6m2l74ecf13c51fmmihrsu3jh.apps.googleusercontent.com?project=673194113721

编辑 2:

  string[] Scopes = { GmailService.Scope.GmailReadonly };
        string ApplicationName = "IkanbiBot";


        var secrets = new ClientSecrets
        {
            ClientId = ConfigurationSettings.AppSettings["GMailClientId"],
            ClientSecret = ConfigurationSettings.AppSettings["GMailClientSecret"]
        };

        var token = new Google.Apis.Auth.OAuth2.Responses.TokenResponse { RefreshToken = ConfigurationSettings.AppSettings["GmailRefreshToken"] };
        var credential = new UserCredential(new GoogleAuthorizationCodeFlow(
            new GoogleAuthorizationCodeFlow.Initializer
            {
                ClientSecrets = secrets
            }), "xxxx@gmail.com", token);

        var gmailService = new GmailService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = this.GetType().ToString()
        });

        log4net.ILog log2 = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        await context.PostAsync("Aplication name is ..." + ApplicationName);

        await context.PostAsync("secret name is ..." + secrets.ClientId + "_____   and  .... " + secrets.ClientSecret + " ++++ token is " + token.RefreshToken);

        var emailListRequest = gmailService.Users.Messages.List("xxxxx@gmail.com");
        emailListRequest.LabelIds = "INBOX";
        emailListRequest.MaxResults = 1;
        emailListRequest.Q = "is:unread";
        emailListRequest.IncludeSpamTrash = false;

        // Get our emails
        // Get our emails
        var emailListResponse = emailListRequest.Execute();

        //get our emails 

        log2.Info(emailListResponse.Messages);

       await context.PostAsync("emailListResponse  is ..." + emailListResponse.Messages.Count);
        if (emailListResponse != null && emailListResponse.Messages != null)
        {
            //loop through each email and get what fields you want... 
            foreach (var email in emailListResponse.Messages)
            {

                var emailInfoRequest = gmailService.Users.Messages.Get("botikanbi@gmail.com", email.Id);

                var emailInfoResponse = emailInfoRequest.Execute();



                if (emailInfoResponse != null)
                {
                    String from = "";
                    String date = "";
                    String subject = "";
                    String body = "";
                    //loop through the headers to get from,date,subject, body  
                    foreach (var mParts in emailInfoResponse.Payload.Headers)
                    {


                        if (mParts.Name == "Date")
                        {
                            date = mParts.Value;
                        }
                        else if (mParts.Name == "From")
                        {
                            from = mParts.Value;
                        }
                        else if (mParts.Name == "Subject")
                        {
                            subject = mParts.Value;
                        }

                        if (date != "" && from != "")
                        {




                            if (emailInfoResponse.Payload.Parts == null && emailInfoResponse.Payload.Body != null)
                                body = DecodeBase64String(emailInfoResponse.Payload.Body.Data);
                            else
                                body = GetNestedBodyParts(emailInfoResponse.Payload.Parts, "");




                        }

                    }
                    await context.PostAsync("Email list for: Date " + date + " :::::::::::  From:  " + from + " ::::::::::::  Subject  " + subject + " : :::::::::::::  Body :  " + body + " Email.id eshte " + email.Id);

                }

            }

        }

    }


    static String DecodeBase64String(string s)
    {
        var ts = s.Replace("-", "+");
        ts = ts.Replace("_", "/");
        var bc = Convert.FromBase64String(ts);
        var tts = Encoding.UTF8.GetString(bc);

        return tts;
    }


    static String GetNestedBodyParts(IList<MessagePart> part, string curr)
    {
        string str = curr;
        if (part == null)
        {
            return str;
        }
        else
        {
            foreach (var parts in part)
            {
                if (parts.Parts == null)
                {
                    if (parts.Body != null && parts.Body.Data != null)
                    {
                        var ts = DecodeBase64String(parts.Body.Data);
                        str += ts;
                    }
                }
                else
                {
                    return GetNestedBodyParts(parts.Parts, str);
                }
            }

            return str;
        }
    }







    private static byte[] FromBase64ForUrlString(string base64ForUrlInput)
    {
        int padChars = (base64ForUrlInput.Length % 4) == 0 ? 0 : (4 - (base64ForUrlInput.Length % 4));
        StringBuilder result = new StringBuilder(base64ForUrlInput, base64ForUrlInput.Length + padChars);
        result.Append(String.Empty.PadRight(padChars, '='));
        result.Replace('-', '+');
        result.Replace('_', '/');
        return Convert.FromBase64String(result.ToString());
    }


}

}

现在我正在使用这段代码。我从机器人那里得到答案,直到:“秘密名称是......”+secrets.ClientId +“_____ 和....”+secrets.ClientSecret +“++++ 令牌是”+token.RefreshToken 但是尝试时停止阅读电子邮件:(

你能帮我看看这是怎么回事吗?

标签: c#google-oauthbotframeworkgmail-api

解决方案


有几种方法可以向 google 进行身份验证。

  • 移动
  • 网络
  • 服务帐号
  • 本机应用程序。

您为上述每种身份验证类型创建的客户端是不同的。使用它们的代码也不同。

GoogleWebAuthorizationBroker.AuthorizeAsync用于验证已安装的应用程序。它不适用于 Web 应用程序。

对于 Web 应用程序,您应该遵循Web 应用程序 (ASP.NET MVC)并使用GoogleAuthorizationCodeFlow

  private static readonly IAuthorizationCodeFlow flow =
        new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
            {
                ClientSecrets = new ClientSecrets
                {
                    ClientId = "PUT_CLIENT_ID_HERE",
                    ClientSecret = "PUT_CLIENT_SECRET_HERE"
                },
                Scopes = new[] {  GmailService.Scope.GmailReadonly },
                DataStore = new FileDataStore(this.GetType().ToString()
            });

redirect_uri_mismatch

为了使用 api,您的客户端必须正确设置。在谷歌开发者控制台中,您只需在客户端的设置中添加正确的重定向 uri,它就会起作用。它必须完全匹配,http://127.0.0.1:52158/authorize/ 以确保 Visual Studio 不会在您身上创建随机端口号。


推荐阅读