Mailcore 2 integration:
I am working on "Reply", "Reply All" , "Forward" and Move To features. When I started up with "Reply", I could able to get the Reply mail body full message from MCOMessageView class -> content = [(MCOIMAPMessage *) _message htmlRenderingWithFolder:_folder delegate:self]; and displayed in reply compose view.
Now, I need pre-populate "Reply" (Recipient To) email in the compose view. When I tried "_message.header.replyTo", it is giving me like "mailcore::Address:0x17df0c70 getsy sandriya getsypri8796#gmail.com"
But I need to retrieve the mail address(es) alone from this "_message.header.replyTo", it is giving me like "mailcore::Address:0x17df0c70 getsy sandriya getsypri8796#gmail.com"
How to retrieve Reply email address from "mailcore:.........", please advise.
The definitive answer for me is like the following, i made a quick Swift v2.3 example and it run like the following :
let imapsession = MCOIMAPSession()
imapsession.hostname = "YOUR SERVER"
imapsession.port = 993
imapsession.username = "EMAIL"
imapsession.password = "PASS"
imapsession.connectionType = MCOConnectionType.TLS
let requestKind : MCOIMAPMessagesRequestKind = MCOIMAPMessagesRequestKind.Headers
let folder : String = "INBOX"
let uids : MCOIndexSet = MCOIndexSet(range: MCORangeMake(1, UINT64_MAX))
let fetchOperation : MCOIMAPFetchMessagesOperation = imapsession.fetchMessagesOperationWithFolder(folder, requestKind: requestKind, uids: uids)
fetchOperation.start { (err, msg, vanished) -> Void in
print("error from server \(err)")
print("fetched \(msg?[0]) messages")
let msgs = msg
if msgs?.count > 0 {
for m in msgs! {
let MSG: MCOIMAPMessage = m as! MCOIMAPMessage
let op = imapsession.fetchMessageByUIDOperationWithFolder(folder, uid: MSG.uid)
op.start { (err, data) -> Void in
let msgParser = MCOMessageParser(data: data)
let html: String = msgParser.plainTextBodyRendering()
print("*********************")
print("Mail body\(html)")
print("mail sender:\(MSG.header.sender)")
print("mail recipient:\(MSG.header.to)")
print("mail subject:\(MSG.header.subject)")
print("*********************")
}
}
}
}
In the example above i went a bit far and i gather the mail content as text. you can do it in HTML also.
Hope this answer will help you and help other people who fall in the same issue !
Related
Step 1: Link (https://github.com/MailCore/MailCore2)
Step 2: I have added mailcore-framework in my project
Step 3: pod install for UICKeyChainStore in my project done
Step 4: Send mail successfully using MCOSMTPSession, MCOMessageBuilder.
Step 5: My problem is that I am not able to fetch using mailcore. Is there any other framework for fetching mail (inbox)?
Sorry for late answer. I have two apps in the App Store, both of them use MailCore2, so I can explain you a thing or two about that.
Of course you can fetch the emails with MailCore2, this is the code. If you have any other doubt with MailCore2 write about that, I will try to find the answer.
var imapsession:MCOIMAPSession = MCOIMAPSession()
func prepareImapSession()
{
// CONFIGURE THAT DEPENDING OF YOUR NEEDS
imapsession.hostname = imapHostname // String
imapsession.username = userName // String
imapsession.password = password // String
imapsession.port = portIMAP // UInt32 number
imapsession.authType = MCOAuthType.saslLogin
imapsession.connectionType = MCOConnectionType.TLS
}
func useImapWithUIDS()
{
// There is more than one option here, explore depending of your needs
let requestKind : MCOIMAPMessagesRequestKind = .headers
let folder : String = "INBOX"
// HERE ALSO EXPLORE DEPENDING OF YOUR NEEDS, RANGE IT IS THE RANGE OF THE UIDS THAT YOU WANT TO FETCH, I SUGGEST TO YOU TO CHANGE THE // NUMBER ONE IF YOU HAVE A LOWER BOUND TO FETCH EMAIL
let uids : MCOIndexSet = MCOIndexSet(range: MCORangeMake(1, UINT64_MAX))
let fetchOperation = imapsession.fetchMessagesOperation(withFolder: folder, requestKind: requestKind, uids: uids)
fetchOperation?.start
{ (err, msg, vanished) -> Void in
if (err != nil)
{
error = err
NSLog((err?.localizedDescription)!)
}
else
{
guard let msgs = msg as? [MCOIMAPMessage]
else
{
print("ERROR GETTING THE MAILS")
return
}
for i in 0..<msgs.count
{
// THE SUBJECT
let subject = msgs[i].header.subject
// THE uid for this email. The uid is unique for one email
let uid = msgs[i].uid
// The sequenceNumber like the nomber say it is the sequence for the emails in the INBOX from the first one // (sequenceNumber = 1) to the last one , it not represent always the same email. Because if you delete one email then //next one will get the sequence number of that email that was deleted
let sequenceNumber = msgs[i].sequenceNumber
}
}
}
// MARK: - EXTRACT THE CONTENT OF ONE EMAIL, IN THIS FUNCTION YOU NEED THE uid, THE UNIQUE NUMBER FOR ONE EMAIL
func useImapFetchContent(uidToFetch uid: UInt32)
{
let operation: MCOIMAPFetchContentOperation = imapsession.fetchMessageOperation(withFolder: "INBOX", uid: uid)
operation.start { (Error, data) in
if (Error != nil)
{
NSLog("ERROR")
return
}
let messageParser: MCOMessageParser = MCOMessageParser(data: data)
// IF YOU HAVE ATTACHMENTS USE THIS
let attachments = messageParser.attachments() as? [MCOAttachment]
// THEN YOU NEED THIS PROPERTIE, IN THIS EXAMPLE I TAKE THI FIRST, USE WHAT EVER YOU WANT
let attachData = attachments?.first?.data
// FOR THE MESSAGEPARSER YOU CAN EPLORE MORE THAN ONE OPTION TO OBTAIN THE TEXT
let msgPlainBody = messageParser.plainTextBodyRendering()
}
You can give https://github.com/snipsco/Postal a try. This is a framework which aims to provide simple access to common email providers.
I am using mailCore to fetch emails from server. I am done with session setup and basic flow. Now i am stuck in a minor problem and i am unable to figure it out.
Here is code of fetching email headers
let folder: String = "Inbox"
let folderInfoFetch : MCOIMAPFolderInfoOperation = imapSession.folderInfoOperation(folder)
folderInfoFetch.start { (error, folderInfo) in
if (error == nil) {
var numberOfMessages : Int32 = Int32(30)
numberOfMessages -= 1
let request: MCOIMAPMessagesRequestKind = .headers
let messagesNumbers = MCOIndexSet.init(range: MCORange.init(location: UInt64(abs((folderInfo?.messageCount)!-numberOfMessages)) , length: UInt64(numberOfMessages)))
let fetch : MCOIMAPFetchMessagesOperation = self.imapSession.fetchMessagesByNumberOperation(withFolder: folder, requestKind: request, numbers: messagesNumbers)
fetch.start({ (error, fetchedMessages, vanishedMessages) in
if(error != nil)
{
print("Error downloading message headers: \(String(describing: error))")
} else {
if let mails = fetchedMessages as? [MCOIMAPMessage] {
print(mails)
}
}
})
}
This code is successfully returning mail headers. But read/unread flags are missing in this. I have seen many solutions of this problem but they all in objective c.
i-e
MCOIMAPMessagesRequestKind requestKind = MCOIMAPMessagesRequestKindHeaders | MCOIMAPMessagesRequestKindFlags
It's solution is to send multiple types of flags in request. But how i can achieve this in swift ? Any help will be appreciated!
Solution Link : https://github.com/MailCore/mailcore2/issues/409
In swift4.2, I achieved this with the following syntax:
let requestKind: MCOIMAPMessagesRequestKind = [.headers, .flags]
So after banging my head the only solution which worked for me is append flags by taking its union.
let kind = MCOIMAPMessagesRequestKind()
let headers = kind.union(MCOIMAPMessagesRequestKind.headers)
let request = headers.union(MCOIMAPMessagesRequestKind.flags)
I know it's not best but it worked for me.
I am trying to send requests with data to Facebook friends in my app. The requests are successfully sent and I do get notifications. However the message on the notifications is not what I specify (the notification I get is xxxxx sent you a request. I specified Please help me with 5 lives). Also, I can't access any data of the request received.
This is how I'm sending the request:
func sendLifeRequest(index: Int) {
let content = FBSDKGameRequestContent()
content.message = "Please help me with 5 lives"
content.data = "5lives"
let id = facebookFriends[index].id as NSString
var to: [NSString] = [NSString]()
to.append(id)
content.recipients = to
FBSDKGameRequestDialog.show(with: content, delegate: self)
}
This is how I'm trying to get it in the other end:
FBSDKGraphRequest(graphPath: "https://graph.facebook.com/me/apprequests?access_token=" + FBSDKAccessToken.current().tokenString, parameters: nil).start(completionHandler: { (connection, user, requestError) -> Void in
print(requestError) // prints nil
print(user)
})
print(user) prints:
Optional({
id = "https://graph.facebook.com/me/apprequests";
"og_object" = {
id = xxxxxxxxxxxxx;
type = website;
"updated_time" = "2016-10-19T05:32:20+0000";
};
share = {
"comment_count" = 0;
"share_count" = 0;
};
Update: I found out that if I copy the request ID and copy it for graph path it works. Does anyone knows how to get this ID from receivers end
func gameRequestDialog(_ gameRequestDialog: FBSDKGameRequestDialog!, didCompleteWithResults results: [AnyHashable : Any]!) {
print("request sent")
print(results) // copied ID from here
}
and pasted...
FBSDKGraphRequest(graphPath: THE ID HERE, parameters: nil).start(completionHandler: { (connection, user, requestError) -> Void in
print(requestError) // prints nil
print(user)
})
now print user prints:
Optional({
application = {
category = Games;
id = xxxxxxxxxxxx;
link = "https://www.facebook.com/games/?app_id=1841299476156545";
name = "Crazy Traffic Saga";
};
"created_time" = "2016-10-24T21:25:34+0000";
data = 5lives;
from = {
id = xxxxxxxxxxxx;
name = "xxxxxxxxxxxxxx";
};
id = xxxxxxxxxxxx;
message = "Please help me with 5 lives";
})
The problem is I copied when I log in with the user sending and copied to the user receiving. I still can't just access it just by code from the receiver.
Facebook documentation on Game request says:
"In order to read all the requests for a recipient for you can query the graph as shown below using the recipient's USER ACCESS TOKEN. This will return a list of request ids for that user in the app.
GET https://graph.facebook.com/me/apprequests?access_token=[USER ACCESS TOKEN]"
But thats what I was doing at first...
I found it. the request should be "/me/apprequests"
so:
FBSDKGraphRequest(graphPath: "/me/apprequests", parameters: nil).start(completionHandler: { (connection, user, requestError) -> Void in
})
I'm using the MailCore2 at Swift in my iOS application to send message to email in the background without open built-in mail application, But when I'm running app on my device ( real device ) I have this problem:
My complete code for send button:
#IBAction func sendButton(sender: AnyObject) {
var smtpSession = MCOSMTPSession()
smtpSession.hostname = "smtp.gmail.com"
smtpSession.username = "from-email"
smtpSession.password = "password"
smtpSession.port = 465
smtpSession.authType = MCOAuthType.SASLPlain
smtpSession.connectionType = MCOConnectionType.TLS
smtpSession.connectionLogger = {(connectionID, type, data) in
if data != nil {
if let string = NSString(data: data, encoding: NSUTF8StringEncoding){
NSLog("Connectionlogger: \(string)")
}
}
}
var builder = MCOMessageBuilder()
builder.header.to = [MCOAddress(displayName: "AAA", mailbox: "to-email")]
builder.header.from = MCOAddress(displayName: "RRR", mailbox: "from-email")
builder.header.subject = messageTitleTextField.text
var message = messageTextView.text
builder.htmlBody = message
let rfc822Data = builder.data()
let sendOperation = smtpSession.sendOperationWithData(rfc822Data)
sendOperation.start { (error) -> Void in
if (error != nil) {
NSLog("Error sending email: \(error)")
} else {
NSLog("Sent successfully, Thanks!")
}
}
}
Error:
Optional(Error Domain=MCOErrorDomain Code=5 "Unable to authenticate with the current session's credentials." UserInfo={NSLocalizedDescription=Unable to authenticate with the current session's credentials.})
Already I change setting of unsecure app from gmail account but I solved the credentials problem by unlocking gmail account from this link
https://accounts.google.com/DisplayUnlockCaptcha
In my case I had to "Change account access for less secure apps"
https://support.google.com/accounts/answer/6010255?hl=en
If somebody has this problem its quite helpful to know that it is actually problem with security on google side and there it has to be handled...I will leave it because when this happened to me the error didn't say anything I had to search for problem to find out that you have to go to that link on google and find out how to setup it correctly, I wasted time , it will be helpful for others who wants to send mail by smtp with google account
When I send a message using iOS to a PubNub channel, I can use the didReceiveMessage function to get that message and put it in my tableView. However, if I send a message via a client in the Dev Dashboard, message.data.message returns nil after I try to cast it as a String. Here's the function in question:
func client(client: PubNub, didReceiveMessage message: PNMessageResult) {
print("Received: %", message.data.message)
let newMessage:String? = message.data.message as? String
print(newMessage) // returns nil
self.messagesArray.append(newMessage!)
dispatch_async(dispatch_get_main_queue()) {
self.messageTableView.reloadData()
}
}
I get the following response in console from print("Received: %", message.data.message):
Received: % Optional({
text = test;
})
However, print(newMessage) is returning nil. What am I doing wrong?
Thanks!
EDIT: I'm getting the same thing when I try to get messages from the historyForChannel function.
//get history
pubNub.historyForChannel("channelname" as String, withCompletion: { (result, status) -> Void in
print(status)
if status == nil {
if result!.data.messages.count > 0 {
let historyMessages = result!.data.messages.description as? [String]
print(result)
for item in historyMessages!{
self.messagesArray.append(item)
}
}
}
})
historyMessages is nil, even though result prints:
Optional({
Operation = History;
Request = {
Authorization = "not set";
Method = GET;
Origin = "pubsub.pubnub.com";
"POST Body size" = 0;
Secure = YES;
URL = "...redacted";
UUID = "...redacted";
};
Response = {
"Processed data" = {
end = 14609023551682481;
messages = (
"technically ",
{
text = "Well..ok then";
},
hi,
"really ",
{
text = "Well..ok then";
},
How do I get the text from these returned messages?
From behaviour and fact what history fetch printed out status object means what you probably configured your client with cipherKey. That status object which you receive probably has category set to decryption error.
If you want to use encryption - you should use same key for all clients, or they won't be able to decrypt sent messages. If cipherKey is set, client automatically try to decrypt data and it will fail if regular text has been received.
Make sure both (console and iOS client) configured with same cipherKey or if you don't need it, make sure what it not set on any of clients.
Best regards,
Sergey.