Reading emails with GTLGmailMessage on iOS

I followed the steps below https://developers.google.com/gmail/api/quickstart/ios

, and I can get the email list successfully, but I need to read each one.

This is how I do it:

- (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 need to call "profile" because I don't know any other way to get the user id and then 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];
    }
}

      

I have a problem: gmailMessages contains 100 items with no content

GTLBatchResult 0x7ffc39d66a50 (successes:100 failures:0)

      

And repeating this ... each message has 0 key / value pairs

message GTLGmailMessage *   0 key/value pairs   0x00007ffc39d50700

      

Is there another way to receive each email? I also tried:

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 must also say that I copied the GTLBatchQuery from this post and I need to change NSNumber *messageId

to NSString *messageId

:

[gmailMessageIds enumerateObjectsUsingBlock:^(NSNumber *messageId, NSUInteger idx, BOOL *stop)

      

+3


source to share


2 answers


This code is fast and works. Skipping the logic for 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 you need help, let me know.

+3


source


when you have it,

`GTLQueryGmail *query = [GTLQueryGmail queryForUsersMessagesGet];`
      

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



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

You can learn more about this here

+2


source







All Articles