Author |
|
buru Newbie
Joined: 19 August 2010 Location: Ukraine
Online Status: Offline Posts: 5
|
Posted: 19 August 2010 at 10:18am | IP Logged
|
|
|
Is it possible to connect with Mailbee.Net IMAP to Gmail IMAP using OAuth? It requires oauthToken, oauthTokenSecret and OAuthConsumer to connect.
Thanks in advance
|
Back to Top |
|
|
Igor AfterLogic Support
Joined: 24 June 2008 Location: United States
Online Status: Offline Posts: 6104
|
Posted: 19 August 2010 at 11:34pm | IP Logged
|
|
|
Amongst the available options, MailBee.NET Objects supports custom SASL authentication mechanisms, so you can set up the one you need, check this documentation page for details.
--
Regards,
Igor, AfterLogic Support
|
Back to Top |
|
|
buru Newbie
Joined: 19 August 2010 Location: Ukraine
Online Status: Offline Posts: 5
|
Posted: 20 August 2010 at 4:37am | IP Logged
|
|
|
Thanks, already implementing custom SaslMethod.
I'll keep you updated whether I succeeded with the implementation or not.
Regards,
buru, Comindwork
|
Back to Top |
|
|
buru Newbie
Joined: 19 August 2010 Location: Ukraine
Online Status: Offline Posts: 5
|
Posted: 30 August 2010 at 9:40am | IP Logged
|
|
|
I've got a problem.
I've generated the initial authentication request string as described in Google's documentation. It is 100% correct, as it is exactly the same as the one generated with Google's python xoauth lib. Then, I supply this request string to the ClientAnswerEncoding.GetBytes() in the first stage of my SaslMethod CreateNextClientAnswer(). However, I'm getting "The server has rejected authentication data sent by the client. The server responded: MBN00000002 NO [ALERT] Invalid credentials (Failure)." as a response from Gmail.
To clarify, here's the main part of my custom SaslMethod:
public class OAuthImapLoginMethod : SaslMethod {
public string UserEmail { get; set; }
public string SaslID { get; set; }
public string InitialRequest { get; set; }
public override void CreateNextClientAnswer() {
switch (Stage) {
case 0:
ClientAnswer = ClientAnswerEncoding.GetBytes(GetInitialRequest());
Stage++;
break;
}
}
public override string GetSaslID() {
return SaslID ?? "XOAUTH";
}
public override bool RequiresCredentials() {
return false;
}
protected string GetInitialRequest() {
return InitialRequest ?? String.Format("GET https://mail.google.com/mail/b/{0}/imap/", UserEmail);
}
public override bool IsSecure() {
return true;
}
}
I've logged low level data and found out that MailBee send correct Base64-encoded request string (the exact same string that xoauth python lib with the same params sends); However, I'm getting this ridiculous exception.
I wasn't able to find out what exact command MailBee is sending on the first request. According to Google documentation, it should be as follows:
[connection begins]
C: C01 CAPABILITY
S: * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA XLIST
CHILDREN XYZZY SASL-IR AUTH=XOAUTH
S: C01 OK Completed
C: A01 AUTHENTICATE XOAUTH base64encoded_initial_request_string
S: A01 OK Success
So, my base64encoded_initial_request_string is correct, I've supplied XOAUTH as a SaslID, so I suppose MailBee should do the rest. What could possibly go wrong in this situation?
For clarification, I'm calling imap.Login() with the following params:
imap.Login(null, null, AuthenticationMethods.SaslUserDefined, AuthenticationOptions.TryUnsupportedMethods, oauthLoginMethod);
Regards,
buru, Comindwork
|
Back to Top |
|
|
Alex AfterLogic Support
Joined: 19 November 2003
Online Status: Offline Posts: 2206
|
Posted: 30 August 2010 at 10:19am | IP Logged
|
|
|
And you're sure that the credentials are correct, right? Because you're getting the exception which means the credentials are incorrect, not that everything is incorrect.
For instance, if there were an error in the request, the server would return BAD, not NO. I just checked this to be sure. NO means that the request is constructed just fine but the credentials are wrong.
Also, am I right that you omitted most of the code here because InitialRequest must certainly be much more complex than just 'String.Format("GET https://mail.google.com/mail/b/{0}/imap/", UserEmail)'
Anyway, you may try to reproduce all the sequence in telnet and then, after you got it right, try the same with MailBee (be sure to enable logging in MailBee to see all the commands sent in or out).
You can get telnetssl (because gmail is ssl-only) from http://www.afterlogic.com/files/telnetssl.zip
telnetssl imap.gmail.com 993 ssl
[server responds with *...]
01 capability
[server responds with *.../01 OK ...]
02 authenticate xoauth
[server responds with +]
base64_token
[server responds with 02 NO, 02 BAD, or 02 OK]
Does it work this way?
Regards,
Alex
|
Back to Top |
|
|
buru Newbie
Joined: 19 August 2010 Location: Ukraine
Online Status: Offline Posts: 5
|
Posted: 31 August 2010 at 3:22am | IP Logged
|
|
|
Yep, surely, I'm supplying the whole signature string as initial request: "GET https://mail.google.com/mail/b/my@emailaddress.com/imap/ oauth_consumer_key="my_consumer_key",oauth_nonce=....".
Tried to connect via telnetssl and got "02 NO [ALERT] Invalid Credentials (Failure)", so, obviously, there's a problem with my initial request.
What's strange here is that if I supply this exact initial request to Google's xoauth.py lib, it manages to successfully authenticate!
Here's the python code:
imap_conn = imaplib.IMAP4_SSL(imap_hostname)
imap_conn.debug = 4
imap_conn.authenticate('XOAUTH', lambda x: xoauth_string)
imap_conn.select('INBOX')
Where xoauth_string is the initial request before base64 encoding.
Here's the dialog between python lib and Gmail:
00:57.14 > BJPA1 AUTHENTICATE XOAUTH
00:57.20 < +
00:57.20 write literal size 476
00:57.47 < * CAPABILITY IMAP4rev1 UNSELECT LITERAL+ IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE
00:57.47 < BJPA1 OK my@emailaddress.com authenticated (Success)
00:57.47 > BJPA2 SELECT INBOX
Maybe you could tell me from this cryptic output how this python lib manages to authenticate using the exact same string which returns "invalid credentials" for both MailBee and direct telnetssl connection. Thanks in advance.
Regards,
buru, Comindwork
|
Back to Top |
|
|
Alex AfterLogic Support
Joined: 19 November 2003
Online Status: Offline Posts: 2206
|
Posted: 31 August 2010 at 3:38am | IP Logged
|
|
|
Seems you forgot to show the most important thing, what's in "write literal size 476". There should be base64 string of 476 bytes length. That's the string to be tried with telnetssl.
Regards,
Alex
|
Back to Top |
|
|
buru Newbie
Joined: 19 August 2010 Location: Ukraine
Online Status: Offline Posts: 5
|
Posted: 31 August 2010 at 4:37am | IP Logged
|
|
|
Well, I can't list this string here for security reasons, as it contains our Google Apps consumer key and consumer secret, but it's exact same string that I supply to MailBee and telnetssh.
I decided to go through all of the params in my initial request string and triple-check them. Finally, I found out that the root of all evil was in timestamp param! It seems that Gmail expects timestamp to be Unix time in seconds, and I supplied it in milliseconds.
Impossible but true: after changing timestamp from milliseconds to seconds MailBee authenticated successfully.
It's still not entirely clear why command line telnetssl won't be authenticated with the string that works for the libs. Probably, base64-encoded strings loses some of the chars while being copy-pasted to cmd.exe.
Thanks for you help. I'm glad the problem is finally solved!
Regards,
buru, Comindwork
|
Back to Top |
|
|
Alex AfterLogic Support
Joined: 19 November 2003
Online Status: Offline Posts: 2206
|
Posted: 31 August 2010 at 6:07am | IP Logged
|
|
|
Congratulations :)
Regards,
Alex
|
Back to Top |
|
|