How to retrieve my Gmail messages using Gmail API?

后端 未结 5 1076
忘掉有多难
忘掉有多难 2020-12-14 04:35

What I want to achieve:


I\'m using the Gmail API and basically I would like to connect to my GMail account to read my emails, of INBOX categ

相关标签:
5条回答
  • 2020-12-14 04:50

    Currently for some reason or another many of the properties are coming back null from any of the requests. We can still get around that if we have a list of the email ids. We then can use these email ids to send out another request to retrieve further details: from, date, subject, and body. @DalmTo was on the right track as well, but not close enough about the headers as it has changed recently which will require a few more requests.

    private async Task getEmails()
    {
        try
        {
            UserCredential credential;
            using (var stream = new FileStream("client_secrets.json", 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, GmailService.Scope.MailGoogleCom, GmailService.Scope.GmailModify },
                    "NAME OF ACCOUNT NOT EMAIL ADDRESS",
                    CancellationToken.None,
                    new FileDataStore(this.GetType().ToString())
                );
            }
    
            var gmailService = new GmailService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = this.GetType().ToString()
            });
    
            var emailListRequest = gmailService.Users.Messages.List("EMAILADDRESSHERE");
            emailListRequest.LabelIds = "INBOX";
            emailListRequest.IncludeSpamTrash = false;
            //emailListRequest.Q = "is:unread"; // This was added because I only wanted unread emails...
    
            // Get our emails
            var emailListResponse = await emailListRequest.ExecuteAsync();
    
            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("EMAIL ADDRESS HERE", email.Id);
                    // Make another request for that email id...
                    var emailInfoResponse = await emailInfoRequest.ExecuteAsync();
    
                    if (emailInfoResponse != null)
                    {
                        String from = "";
                        String date = "";
                        String subject = "";
                        String body = "";
                        // Loop through the headers and get the fields we need...
                        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 = emailInfoResponse.Payload.Body.Data;
                                }
                                else
                                {
                                    body = getNestedParts(emailInfoResponse.Payload.Parts, "");
                                }
                                // Need to replace some characters as the data for the email's body is base64
                                String codedBody = body.Replace("-", "+");
                                codedBody = codedBody.Replace("_", "/");
                                byte[] data = Convert.FromBase64String(codedBody);
                                body = Encoding.UTF8.GetString(data);                               
    
                                // Now you have the data you want...                         
                            }
                        }
                    }                    
                }
            }           
        }
        catch (Exception)
        {
            MessageBox.Show("Failed to get messages!", "Failed Messages!", MessageBoxButtons.OK); 
        }
    }
    
    static String getNestedParts(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)
                    {
                        str += parts.Body.Data;
                    }
                }
                else
                {
                    return getNestedParts(parts.Parts, str);
                }
            }
    
            return str;
        }        
    }
    

    Currently, this method will retrieve all email ids and for each email id get the subject,from, date and body of each email. There are comments throughout the method. If there is something you do not understand, please let me know. On another note: this was tested again before posting this as an answer.

    0 讨论(0)
  • 2020-12-14 04:51

    sorry this is not an answer, i can't add a comment to Zaggler's answer(just joined), so just post as a new answer, Zaggler's answer is very good, but there is a small problem. when the email body has more then one part. the Convert.FromBase64..... doesn't work on two joined base64 strings. so an exception will be occure. better convert then joined the body parts.

    some one ask for the code, and here is the completed tested code. most of them are copied from Zaggler, but i end up with some exceptions. so i traced down to the problem described above.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.IO;
    using Google.Apis.Auth.OAuth2;
    using Google.Apis.Gmail.v1;
    using Google.Apis.Gmail.v1.Data;
    using Google.Apis.Services;
    using Google.Apis.Util.Store;
    
    namespace GmailTests
    {
        class Program
        {
            // If modifying these scopes, delete your previously saved credentials
            // at ~/.credentials/gmail-dotnet-quickstart.json
            static string[] Scopes = { GmailService.Scope.GmailModify };
            static string ApplicationName = "Gmail API .NET Quickstart";
    
            static void Main(string[] args)
            {
                UserCredential credential;
    
                using (var stream =
                    new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
                {
                    string credPath = System.Environment.GetFolderPath(
                        System.Environment.SpecialFolder.Personal);
                    credPath = Path.Combine(credPath, ".credentials/gmail-dotnet-quickstart2.json");
    
                    credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                        GoogleClientSecrets.Load(stream).Secrets,
                        Scopes,
                        "user",
                        CancellationToken.None,
                        new FileDataStore(credPath, true)).Result;
                    Console.WriteLine("Credential file saved to: " + credPath);
                }
    
                // Create Gmail API service.
                var service = new GmailService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = ApplicationName,
                });
    
    
                var re = service.Users.Messages.List("me");
                re.LabelIds = "INBOX";
                re.Q = "is:unread"; //only get unread;
    
                var res = re.Execute();
    
                if (res != null && res.Messages != null)
                {
                    Console.WriteLine("there are {0} emails. press any key to continue!", res.Messages.Count);
                    Console.ReadKey();
    
                    foreach (var email in res.Messages)
                    {
                        var emailInfoReq = service.Users.Messages.Get("me", email.Id);
                        var emailInfoResponse = emailInfoReq.Execute();
    
                        if (emailInfoResponse != null)
                        {
                            String from = "";
                            String date = "";
                            String subject = "";
                            String body = "";
                            //loop through the headers and get the fields we need...
                            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, "");
    
                                    //now you have the data you want....
    
                                }
    
                            }
    
                            //Console.Write(body);
                            Console.WriteLine("{0}  --  {1}  -- {2}", subject, date, email.Id);
                            Console.ReadKey();
                        }
                    }
                }
            }
    
            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;
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-14 04:54

    First: up-vote @codexer 's answer.

    Second, use the following function in his code to decode the base64URL encoded body. Google not only base64 encoded the body, it is also URL encoded :-/

    /// <summary>
        /// Turn a URL encoded base64 encoded string into readable UTF-8 string.
        /// </summary>
        /// <param name="sInput">base64 URL ENCODED string.</param>
        /// <returns>UTF-8 formatted string</returns>
        private string DecodeURLEncodedBase64EncodedString(string sInput)
        {
            string sBase46codedBody = sInput.Replace("-", "+").Replace("_", "/").Replace("=", String.Empty);  //get rid of URL encoding, and pull any current padding off.
            string sPaddedBase46codedBody = sBase46codedBody.PadRight(sBase46codedBody.Length + (4 - sBase46codedBody.Length % 4) % 4, '=');  //re-pad the string so it is correct length.
            byte[] data = Convert.FromBase64String(sPaddedBase46codedBody);
            return Encoding.UTF8.GetString(data);
        }
    
    0 讨论(0)
  • UsersResource.MessagesResource.GetRequest getReq = null;
    Google.Apis.Gmail.v1.Data.Message msg = null;
    getReq = gmailServiceObj.Users.Messages.Get(userEmail, MessageID);
    getReq.Format = UsersResource.MessagesResource.GetRequest.FormatEnum.Raw;
    msg = getReq.Execute();
    string converted = msg.Raw.Replace('-', '+');
    converted = converted.Replace('_', '/');
    
    byte[] decodedByte = Convert.FromBase64String(converted);
    converted = null;
    f_Path = Path.Combine(m_CloudParmsObj.m_strDestinationPath,MessageID + ".eml");
    
    if (!Directory.Exists(m_CloudParmsObj.m_strDestinationPath))
        Directory.CreateDirectory(m_CloudParmsObj.m_strDestinationPath);
    
    // Create eml file
    File.WriteAllBytes(f_Path, decodedByte);
    

    We can get the .eml file with all message properties like this.

    0 讨论(0)
  • 2020-12-14 05:09

    The user parameter in GoogleWebAuthorizationBroker.AuthorizeAsync is just used by FileDatastore to store your credentials check my tutorial Google .net – FileDatastore demystified for more information.

    My VB.net is very rusty like 6 years rusty but in C# you could do something like this

    UsersResource.MessagesResource.ListRequest request = service.Users.Messages.List("Users email address");
    var response = request.Execute();
    
    foreach (var item in response.Messages) {
         Console.WriteLine(item.Payload.Headers);            
     }
    

    MessageResource.ListRequest returns a list of message objects you can loop though them.

    Users.Messages contains header which should have the subject and the to and from.

    I also have a really old C# tutorial on gmail that might help.

    Update to answer your update:

    What happens when you remove:

    .LabelIds = New Repeatable(Of String)({folder.Id})
    

    labelIds string Only return messages with labels that match all of the specified label IDs.

    It appears you are sending a folder id. try using user.lables.list which returns Lists all labels in the user's mailbox

    0 讨论(0)
提交回复
热议问题