4

I have followed the steps at: https://developers.google.com/gmail/api/quickstart/ios and I can successfully get Email List, but I need to read each one.

This is how I do:

- (void)fetchEmails {
    self.output.text = @"Getting emails...";
    NSString *newAPIStr = @"";
    newAPIStr = [NSString stringWithFormat:@"https://www.googleapis.com/gmail/v1/users/me/profile"];

    NSURL *url = [NSURL URLWithString:newAPIStr];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    [request setHTTPMethod:@"GET"];

    GTMOAuth2Authentication *currentAuth= self.service.authorizer;
    GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
    [myFetcher setAuthorizer:currentAuth];
    [myFetcher beginFetchWithCompletionHandler:^(NSData *retrievedData, NSError *error) {
        if (error != nil)
        {
            // status code or network error
            NSLog(@"Ha ocurrido un error");
        }
        else {
            // succeeded
            NSDictionary* json = [NSJSONSerialization JSONObjectWithData:retrievedData options:kNilOptions error:&error];
            NSLog(@"json==>%@",json);
            userid=[json objectForKey:@"emailAddress"];

            GTLQueryGmail *query = [GTLQueryGmail queryForUsersMessagesList];
            [self.service executeQuery:query delegate:self didFinishSelector:@selector(displayResultMessageListWithTicket:finishedWithObject:error:)];

        }
    }];        
}

I have to call "profile" because I don't know another way to get userid, and then I get the list of emails.

- (void)displayResultMessageListWithTicket:(GTLServiceTicket *)ticket
                    finishedWithObject:(GTLGmailListMessagesResponse *)emailsResponse error:(NSError *)error 
{
    if (error == nil) 
    {
        NSMutableString *labelString = [[NSMutableString alloc] init];

        NSLog(@"emailsResponse =%@",emailsResponse);
        if (emailsResponse.messages.count > 0) 
        {
            [labelString appendString:@"Labels:\n"];
            NSMutableArray *gmailMessageIds = [[NSMutableArray alloc]  init];

            for (GTLGmailMessage *message in emailsResponse.messages)
            {
                NSString *mess = message.identifier;
                [gmailMessageIds addObject:mess];
            }

            GTLBatchQuery *batchQuery = [GTLBatchQuery batchQuery];

            [gmailMessageIds enumerateObjectsUsingBlock:^(NSString *messageId, NSUInteger idx, BOOL *stop) {
                GTLQueryGmail *query = [GTLQueryGmail queryForUsersMessagesGet];
                //query.userId = ;
                query.identifier = [NSString stringWithFormat:@"%llx", [messageId unsignedLongLongValue]];
                query.format = kGTLGmailFormatRaw;

                [batchQuery addQuery:query];
            }];


            [self.service executeQuery:batchQuery completionHandler:^(GTLServiceTicket *ticket, GTLBatchResult *result, NSError *error) {

                NSArray *gmailMessages = result.successes.allValues; // This is an array of GTLGmailMessage objects
                for (GTLGmailMessage *message in gmailMessages)
                {  
                    [labelString appendFormat:@"%@\n", message.JSONString];
                }
            }];

        } else {
            [labelString appendString:@"No emails found."];
        }
        self.output.text = labelString;
    } else {
        [self showAlert:@"Error" message:error.localizedDescription];
    }
}

The problem that I have is that gmailMessages contains 100 items without content

GTLBatchResult 0x7ffc39d66a50 (successes:100 failures:0)

And iterating it... each message has 0 key/value pairs

message GTLGmailMessage *   0 key/value pairs   0x00007ffc39d50700

Exists another way to get each email? I tryied also with:

GTLQueryGmail *query = [GTLQueryGmail queryForUsersMessages];
query.identifier = [NSString stringWithFormat:@"%llx", [messageId unsignedLongLongValue]];
query.format = kGTLGmailFormatRaw;
[self.service executeQuery:query delegate:self didFinishSelector:@selector(displayResultWithTicket:finishedWithObject:error:)];

But I think I have the same problem.

I also have to say that I copied GTLBatchQuery from this post and I have to change NSNumber *messageId to NSString *messageId:

[gmailMessageIds enumerateObjectsUsingBlock:^(NSNumber *messageId, NSUInteger idx, BOOL *stop)
Community
  • 1
  • 1
Aarranz
  • 461
  • 6
  • 20

2 Answers2

3

This code is in swift and works. Pass logic to Objective C is relatively easy.

// MARK: - Construct a query and get a list of upcoming labels from the gmail API
    class func fetchEmails() {
        let appd = UIApplication.sharedApplication().delegate as! AppDelegate
        println("Getting Emails ")
        let query = GTLQueryGmail.queryForUsersMessagesList()
        appd.service.executeQuery(query,
            delegate: self,
            didFinishSelector: "displayResultWithTicket:finishedWithObject:error:"
        )
    }

    //get Emails {id:"15015408a4a88b4e" threadId:"15015408a4a88b4e"}
    class func displayResultWithTicket(ticket : GTLServiceTicket, finishedWithObject listMessageResponse : GTLGmailListMessagesResponse, error : NSError?) {
        let appd = UIApplication.sharedApplication().delegate as! AppDelegate
        if let error = error {
            //show your error
            return
        }

        for dictMessage in listMessageResponse.messages {
            var tmpDict2 = dictMessage as! GTLGmailMessage
            let ident = tmpDict2.identifier

            let query = GTLQueryGmail.queryForUsersMessagesGet()
            query.identifier = ident
//            query.format = "metadata" //default full
            appd.service.executeQuery(query,
                delegate: self,
                didFinishSelector: "displayResultWithTicketEachMessages:finishedWithObject:error:"
            )
        }
    }

    // Get each email
    class func displayResultWithTicketEachMessages(ticket : GTLServiceTicket, finishedWithObject eachMessageResponse : GTLGmailMessage, error : NSError?) {
        if let error = error {
            Utils.showAlert("Error 2", message: error.localizedDescription)
            return
        } else {
            logicForSaveMailInfo(eachMessageResponse)
        }
    }

class func logicForSaveMailInfo(eachMessageResponse: GTLGmailMessage) {
        var labelId = eachMessageResponse.labelIds[0] as! String
        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        if labelId == "INBOX" {
            var mailInformationDict = NSMutableDictionary()
            mailInformationDict.setValue(eachMessageResponse.snippet as String, forKey: "snippet")
            mailInformationDict.setValue(eachMessageResponse.identifier as String, forKey: "gmailId")
            mailInformationDict.setValue(eachMessageResponse.internalDate, forKey: "internaldate")

            let payloadArray = eachMessageResponse.payload.headers as NSArray

            for obj in payloadArray {
                var payloadObj = obj as! GTLGmailMessagePartHeader
                if payloadObj.name == "Subject" {
                    mailInformationDict.setValue(payloadObj.value, forKey: "subject")
                }

                if payloadObj.name == "From" {
                    var fromStr = payloadObj.value
                    var index2 = fromStr.rangeOfString("<", options: .BackwardsSearch)?.startIndex
                    var substring2 = ""
                    if index2 != nil {
                        substring2 = fromStr.substringToIndex(index2!)
                    } else {
                        substring2 = fromStr as String
                    }

                    mailInformationDict.setValue(substring2, forKey: "from")
                }

                if payloadObj.name == "To" {
                    var fromStr = payloadObj.value
                    var index2 = fromStr.rangeOfString("<", options: .BackwardsSearch)?.startIndex
                    var substringTo = ""
                    if index2 != nil {
                        substringTo = fromStr.substringToIndex(index2!)
                    } else {
                        substringTo = fromStr as String
                    }

                    mailInformationDict.setValue(substringTo, forKey: "to")
                }
            }
            var parts = eachMessageResponse.payload.parts
            var decodedBody: NSString?
            if parts != nil {
                let body: AnyObject? = parts[0].valueForKey("body")
                if body!.valueForKey("data") != nil {
                    var base64DataString =  body!.valueForKey("data") as! String
                    base64DataString = base64DataString.stringByReplacingOccurrencesOfString("_", withString: "/", options: NSStringCompareOptions.LiteralSearch, range: nil)
                    base64DataString = base64DataString.stringByReplacingOccurrencesOfString("-", withString: "+", options: NSStringCompareOptions.LiteralSearch, range: nil)

                    let decodedData = NSData(base64EncodedString: base64DataString, options:NSDataBase64DecodingOptions(rawValue: 0))
                    decodedBody = NSString(data: decodedData!, encoding: NSUTF8StringEncoding)
                }

            }
        }
        //Create counter for know when finish
        if appDelegate.emailData.count == messageEmailsCounter {
            println("finish charge emails")
        }
    }

If need help let me know.

jose920405
  • 7,982
  • 6
  • 45
  • 71
  • I wish I could give more upvotes! After looking for hours for an answer this code finally helped me get the body of an email while before it kept returning nil for the payload. Thank you so much man! One question: How did you know that the JSON was in this format? I have been looking for a while and can't find any examples of the JSON mail data. – dhruvm Jul 19 '16 at 23:25
2

when you have this,

`GTLQueryGmail *query = [GTLQueryGmail queryForUsersMessagesGet];`

There are a few more parameters you will need to specify such as

`query.format=@"full"; query.format= @"payload"`

You can read more about this here

Liangjun
  • 601
  • 4
  • 13