MCOIMAPIdleOperation Issue - objective-c

I am totally new in IOS Development, And I am making a app using MailCore2 api.
Company has told me to use MCOIMApIdleOperation to get the emails from Gmail Server.
I have google all the way to find out solution about this but it is not worth it.
Here is detail about the Problem,
First I want to load the emails from the INBOX folder through MCOIMAPIdleOperation.Below is my code for fetching emails.
- (void)viewDidLoad{
[super viewDidLoad];
//Do any additional setup after loading the view from its nib.
//Made connection with Gmail Imap Server
NSUserDefaults *defaules = [NSUserDefaults standardUserDefaults];
NSString *emailid = [defaules objectForKey:#"emailid" ];
NSString *password = [defaules objectForKey:#"password" ];
session = [[MCOIMAPSession alloc] init];
session.hostname = #"imap.gmail.com";
session.port = 993;
session.username = emailid;
session.password = password;
session.connectionType = MCOConnectionTypeTLS;
idle=[session idleOperationWithFolder:#"INBOX" lastKnownUID:0];
[idle start:^(NSError *err){
MCOIMAPMessagesRequestKind requestKind = (MCOIMAPMessagesRequestKind)
(MCOIMAPMessagesRequestKindHeaders | MCOIMAPMessagesRequestKindStructure |MCOIMAPMessagesRequestKindInternalDate | MCOIMAPMessagesRequestKindHeaderSubject |MCOIMAPMessagesRequestKindFlags);
MCOIMAPFolderInfoOperation *inboxFolderInfo = [session folderInfoOperation:Folder];
NSLog(#"statrt1");
[inboxFolderInfo start:^(NSError *error, MCOIMAPFolderInfo *info)
{
NSLog(#"start2");
BOOL totalNumberOfMessagesDidChange =
self.totalNumberOfInboxMessages != [info messageCount];
self.totalNumberOfInboxMessages = [info messageCount];
NSUInteger numberOfMessagesToLoad =MIN(self.totalNumberOfInboxMessages, nMessages);
if (numberOfMessagesToLoad == 0)
{
self.isLoading = NO;
return;
}
// If total number of messages did not change since last fetch,
// assume nothing was deleted since our last fetch and just
// fetch what we don't have
MCORange fetchRange;
if (!totalNumberOfMessagesDidChange && msgbody.count)
{
numberOfMessagesToLoad -= msgbody.count;
fetchRange = MCORangeMake(self.totalNumberOfInboxMessages -msgbody.count -(numberOfMessagesToLoad - 1),(numberOfMessagesToLoad - 1));
}
// Else just fetch the last N messages
else
{
fetchRange =MCORangeMake(self.totalNumberOfInboxMessages -(numberOfMessagesToLoad - 1),(numberOfMessagesToLoad - 1));
}
MCOIMAPFetchMessagesOperation *imapMessagesFetchOp =[session fetchMessagesByNumberOperationWithFolder:Folder requestKind:requestKind numbers:
[MCOIndexSet indexSetWithRange:fetchRange]];
[imapMessagesFetchOp start:^(NSError *error, NSArray *messages, MCOIndexSet *vanishedMessages)
{
NSSortDescriptor *sort =[NSSortDescriptor sortDescriptorWithKey:#"header.date" ascending:NO];
NSMutableArray *combinedMessages = [NSMutableArray arrayWithArray:messages];
[combinedMessages removeAllObjects];
[combinedMessages addObjectsFromArray:messages];
msgbody=[combinedMessages sortedArrayUsingDescriptors:#[sort]];
[uitable reloadData];
}];
}];
}];
}
By Above code mails are fetched successfully.Problem is when new mail is arrive above code is not running again.what to do so that i can get the new mails when they arrive..
Please help me to solve this issue.

Related

How can I use MailCore to fetch emails using the token I got from gmail?

I am new to IOS developement.I have use oauth 2.0 for authentication and access token.now i want to fetch the emails using token in mailcore2. how can I do it.I had google lots of stuff but it does not worth it . So,Please help to solve this problem..
Thanks in advance. Here is my code.
- (void)viewDidLoad {
[super viewDidLoad];
NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
NSString *accessToken = [def objectForKey:#"sessionToken"];
NSLog(#"Access token:%#",accessToken);//token from google api authentication
session = [[MCOIMAPSession alloc] init];
session.hostname = #"imap.gmail.com";
session.port = 993;
session.authType =MCOAuthTypeXOAuth2;
session.OAuth2Token = accessToken;
session.username = emailId;
session.connectionType = MCOConnectionTypeTLS;
session.password = nil;
[session setConnectionLogger:^(void * connectionID, MCOConnectionLogType type,
NSData * data){
NSLog(#"MCOIMAPSession: [%i] %#", type, [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}];
MCOIMAPMessagesRequestKind requestKind = (MCOIMAPMessagesRequestKind (MCOIMAPMessagesRequestKindHeaders | MCOIMAPMessagesRequestKindStructure |MCOIMAPMessagesRequestKindInternalDate | MCOIMAPMessagesRequestKindHeaderSubject |MCOIMAPMessagesRequestKindFlags);
MCOIMAPFolderInfoOperation *inboxFolderInfo = [session folderInfoOperation:Folder];
[inboxFolderInfo start:^(NSError *error, MCOIMAPFolderInfo *info){
NSLog(#"INFO:%#",info);
}];
}
I got INFO:(null).correct me If i am doing wrong stuff.

write to amazon aws dynamoDB with out a rang key

I am expanding on exploring amazon's DynamoDB with DynamoDBSample, which they release recently with a bundle of libraries and frameworks called awsiossdk v2
So now the question is, if you go to the dynamoDB console on the web, range key is optional. So I have created one table with out range key only with hash but even though every thing look in place it still look for a rang key and app crashes.
One thing I suspect is that:
AWSDynamoDBObjectMapper *dynamoDBObjectMapper = [AWSDynamoDBObjectMapper defaultDynamoDBObjectMapper];
I am using defaultDynamoDBObjectMapper that probably mean hash and range. But I didn’t able to find any other property where the dynamoDBObjectMapper handle a db write with out a range key.
Appreciate it!
Additional Info.
And here is how I am trying two write to it:
AWSDynamoDBObjectMapper *dynamoDBObjectMapper = [AWSDynamoDBObjectMapper defaultDynamoDBObjectMapper];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
NSMutableArray *tasks = [NSMutableArray array];
NSString *lat = [info objectForKey:#"lat"];
NSString *lon = [info objectForKey:#"lon"];
NSMutableArray *geoLocationMutable = [[NSMutableArray alloc]init];
[geoLocationMutable addObject:lat];
[geoLocationMutable addObject:lon];
NSNCurrentStatusTable *currentStatusTableRow = [NSNCurrentStatusTable new];
currentStatusTableRow.uuid = [[UIDevice currentDevice].identifierForVendor UUIDString];
currentStatusTableRow.lastOnlineTime = [[info objectForKey:#"fullTimeNow"] substringFromIndex:2];
currentStatusTableRow.geoLocation = geoLocationMutable;
currentStatusTableRow.latitude = [info objectForKey:#"latNum"];
currentStatusTableRow.longitude = [info objectForKey:#"lonNum"];
[tasks addObject:[dynamoDBObjectMapper save:currentStatusTableRow]];
[[BFTask taskForCompletionOfAllTasks:tasks]
continueWithExecutor:[BFExecutor mainThreadExecutor] withBlock:^id(BFTask *task) {
if (task.error) {
NSLog(#"Error: [%#]", task.error);
[self getNextStep:YES];
}
else
{
[self getNextStep:YES];
}
return nil;
}];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
});
});

iOS XMPP framework get all registered users

In my chat application I want to get all online registered users. So everybody and not only people in my roster which is achieved with this code:
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence {
// a buddy went offline/online
NSString *presenceType = [presence type]; // online/offline
NSString *myUsername = [[sender myJID] user];
NSString *presenceFromUser = [[presence from] user];
if (![presenceFromUser isEqualToString:myUsername]) {
if ([presenceType isEqualToString:#"available"]) {
[_chatDelegate newBuddyOnline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"chat.denederlandsewateren.nl"]];
} else if ([presenceType isEqualToString:#"unavailable"]) {
[_chatDelegate buddyWentOffline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"chat.denederlandsewateren.nl"]];
}
}
}
With this code the users only sees other users who are 'friends' but I need all users registered on this particular domain. Is this possible with ejabberd?
- (void)getAllRegisteredUsers {
NSError *error = [[NSError alloc] init];
NSXMLElement *query = [[NSXMLElement alloc] initWithXMLString:#"<query xmlns='http://jabber.org/protocol/disco#items' node='all users'/>"
error:&error];
XMPPIQ *iq = [XMPPIQ iqWithType:#"get"
to:[XMPPJID jidWithString:#"DOMAIN"]
elementID:[xmppStream generateUUID] child:query];
[xmppStream sendElement:iq];
}
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
{
NSXMLElement *queryElement = [iq elementForName: #"query" xmlns: #"http://jabber.org/protocol/disco#items"];
if (queryElement) {
NSArray *itemElements = [queryElement elementsForName: #"item"];
NSMutableArray *mArray = [[NSMutableArray alloc] init];
for (int i=0; i<[itemElements count]; i++) {
NSString *jid=[[[itemElements objectAtIndex:i] attributeForName:#"jid"] stringValue];
[mArray addObject:jid];
}
}
I had the same issue, I got queryElement as nil as well. I've changed the response code to see the XML like this:
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
{
//DDLogVerbose(#"%#: %# - %#", THIS_FILE, THIS_METHOD, [iq elementID]);
//NSXMLElement *queryElement = [iq elementForName:#"query" xmlns: #"http://jabber.org/protocol/disco#items"];
NSXMLElement *queryElement = [iq elementForName:#"query" xmlns: #"jabber:iq:roster"];
NSLog(#"IQ: %#",iq);
if (queryElement) {
NSArray *itemElements = [queryElement elementsForName: #"item"];
NSMutableArray *mArray = [[NSMutableArray alloc] init];
for (int i=0; i<[itemElements count]; i++) {
NSString *jid=[[[itemElements objectAtIndex:i] attributeForName:#"jid"] stringValue];
NSLog(#"%#",jid);
[mArray addObject:jid];
}
}
return NO;
}
As you may see what I've changed is the xmlns: from this xmlns: #"http://jabber.org/protocol/disco#items" to this xmlns: #"jabber:iq:roster" and that gave me the list of users.
I'm using ejabberd, not sure if this works for all the others XMPP servers.
Also I've found that this gave me the list of the "buddy" users, looks like if you want "all" users you need to make the query as an admin user. Please check this link for more information about it: https://www.ejabberd.im/node/3420
After googling, You can not get all user easily, You must need to create Shared Roster Groups by follow step in the Example 1: everybody can see everybody else after done this you will get all the online users in the below delegate methods.
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence

Create chatroom with XMPP framework and Ejabberd in iOS

Basically I'm trying to create a chatroom with all registered users on my domain using a ejabberd server. So a user can see all other online registered users on that domain when he enters the chatroom.
Until now I've only been able to make all the users 'friends / buddies' visible and deliver a notification when a friend goes online or offline with the help of the XMPP framework:
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence {
// a buddy went offline/online
NSString *presenceType = [presence type]; // online/offline
NSString *myUsername = [[sender myJID] user];
NSString *presenceFromUser = [[presence from] user];
if (![presenceFromUser isEqualToString:myUsername]) {
if ([presenceType isEqualToString:#"available"]) {
[_chatDelegate newBuddyOnline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"chat.denederlandsewateren.nl"]];
} else if ([presenceType isEqualToString:#"unavailable"]) {
[_chatDelegate buddyWentOffline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"chat.denederlandsewateren.nl"]];
}
}
}
I'm able to get a list with all online registered users but I don't know how to notify the user when somebody goes online or offline.
- (void)getAllRegisteredUsers {
xmppRosterMemStorage = [[XMPPRosterMemoryStorage alloc] init];
xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:xmppRosterMemStorage
dispatchQueue:dispatch_get_main_queue()];
[xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
xmppRoster.autoAcceptKnownPresenceSubscriptionRequests = false;
xmppRoster.autoFetchRoster = true;
[xmppRoster activate:xmppStream];
[xmppRoster fetchRoster];
NSError *error = [[NSError alloc] init];
NSXMLElement *query = [[NSXMLElement alloc] initWithXMLString:#"<query xmlns='http://jabber.org/protocol/disco#items' node='all users'/>"
error:&error];
XMPPIQ *iq = [XMPPIQ iqWithType:#"get"
to:[XMPPJID jidWithString:#"chat.denederlandsewateren.nl"]
elementID:[xmppStream generateUUID] child:query];
[xmppStream sendElement:iq];
}
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
{
NSXMLElement *queryElement = [iq elementForName: #"query" xmlns:
#"http://jabber.org/protocol/disco#items"];
if (queryElement) {
NSArray *itemElements = [queryElement elementsForName: #"item"];
NSMutableArray *mArray = [[NSMutableArray alloc] init];
for (int i=0; i<[itemElements count]; i++) {
NSString *jid=[[[itemElements objectAtIndex:i] attributeForName:#"jid"] stringValue];
[mArray addObject:jid];
[xmppRoster addUser:[XMPPJID jidWithString:jid] withNickname:[[jid componentsSeparatedByString:#"#"] objectAtIndex:0]];
}
}
How can I create a chatroom where the user can see all online registered users on one domain using a Ejabberd server and the XMPP framework?

RestKit not adding URL to backForward list when opening UI webview

So the problem I am having is that I'm using RestKit to to authenticate a self signed certificate and deal with user login simultaneously but after the webView opens then that first page is not being added to the backForward list (as far as i can tell). i.e. after i click on a link on that page I cannot go back to the previous page. If I click on another link (3 pages in) i can go back to the second page but still not the first.. Is there a way to manually add the URL to the backForward list when I open the UI Webview? Or any suggestions for other work-arounds?
- (id)initWithURL:(NSURL*)pageURL {
_retainedURL = pageURL;
[_retainedURL retain];
RKClient *client;
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
client = [RKClient clientWithBaseURL: pageURL];
client.username=[userDefaults objectForKey:#"UserName"];
client.password=[userDefaults objectForKey:#"Password"];
client.authenticationType=RKRequestAuthenticationTypeHTTPBasic;
client.disableCertificateValidation= TRUE;
//The below "delegate:self seems to be what is preventing the URL from passing into the forwardBack list (works if it is delegate self but then RestKit breaks
RKRequest *request=[RKRequest requestWithURL:pageURL delegate:self];
[client configureRequest:request];
request.authenticationType = RKRequestAuthenticationTypeHTTPBasic;
request.disableCertificateValidation = TRUE;
self.authenticatedRequest = request;
NSLog(#"%#",[request URLRequest]);
[request sendAsynchronously];
if(self = [super init]) {
self.URL = pageURL;
self.availableActions = SVWebViewControllerAvailableActionsOpenInSafari | SVWebViewControllerAvailableActionsMailLink | SVWebViewControllerAvailableActionsCopyLink;
}
return self;
}
I ended up fixing this error by creating an NSMutableArray array to keep track of the browser history and adding code to handle various things such as the forward and back buttons display. I'm using 2 ints (urlListIndex and urlIndexMax) as well as a BOOL (backFix) for navigation control
- (id)initWithURL:(NSURL*)pageURL {
_retainedURL = pageURL;
[_retainedURL retain];
RKClient *client;
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
client = [RKClient clientWithBaseURL: pageURL];
client.username=[userDefaults objectForKey:#"UserName"];
client.password=[userDefaults objectForKey:#"Password"];
client.authenticationType=RKRequestAuthenticationTypeHTTPBasic;
client.disableCertificateValidation= TRUE;
RKRequest *request=[RKRequest requestWithURL:pageURL];
[client configureRequest:request];
request.delegate = self;
request.authenticationType = RKRequestAuthenticationTypeHTTPBasic;
request.disableCertificateValidation = TRUE;
self.authenticatedRequest = request;
[request sendAsynchronously];
//Instantiate urlList (for web history) and urlListIndex
urlList = [[NSMutableArray alloc] init];
urlListIndex = 0;
if(self = [super init]) {
self.URL = pageURL;
self.availableActions = SVWebViewControllerAvailableActionsOpenInSafari | SVWebViewControllerAvailableActionsMailLink | SVWebViewControllerAvailableActionsCopyLink;
}
return self;
}
- (void)updateToolbarItems {
//check if you are further than the first page. If so, enable the back button
if (urlListIndex > 0)
{
self.backBarButtonItem.enabled = YES;
}
else
{
self.backBarButtonItem.enabled = NO;
}
//Check if there are more total urls in the list than the one you are on. If so, enable the forward button
if (urlListIndex < maxListIndex)
{
self.forwardBarButtonItem.enabled = YES;
}
else
{
self.forwardBarButtonItem.enabled = NO;
}
//Took out the rest for space
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
self.navigationItem.title = [webView stringByEvaluatingJavaScriptFromString:#"document.title"];
NSURL *urlstring = self.mainWebView.request.URL;
//Check to see if the current url is in the list. If not, add it to the list.
if ([urlList containsObject:urlstring])
{}
else
{
//The first url you click doesnt show up normally so an exception is used here with _retainedURL
if (_retainedURL != nil)
{
[urlList addObject:_retainedURL];
_retainedURL = nil;
}
else
{ if (backFix == NO)
{
urlListIndex++;
[urlList addObject:urlstring];
}
}
}
//Keeps track of the max number of URLs in the list
if (urlListIndex > maxListIndex)
{
maxListIndex = urlListIndex;
}
[self updateToolbarItems];
backFix = NO;
}
- (void)goBackClicked:(UIBarButtonItem *)sender {
backFix = YES;
urlListIndex--;
_request = [NSURLRequest requestWithURL:[urlList objectAtIndex:urlListIndex]];
[mainWebView loadRequest:_request];
}
//Handles the forward button by incrementing the urlListIndex and then loading the url for that index.
- (void)goForwardClicked:(UIBarButtonItem *)sender {
urlListIndex++;
_request = [NSURLRequest requestWithURL:[urlList objectAtIndex:urlListIndex]];
[mainWebView loadRequest:_request];
}