Connecting to IMAP Server
Nowadays STARTTLS command is the preferred way to start TLS encryption for the connection. Unfortunately a lot of servers block port 143 and only allow port 993 (imaps), because this is easier to implement in firewall and it avoids the problems of bad clients sending passwords in plaintext.
Some clients allow users to select between "no encryption", "SSL" and "TLS". However many users don't have a clue what the difference between SSL and TLS is. In fact it's even incorrect to refer to imaps port as SSL, because it most likely uses TLS protocol as well. I think the non-advanced user interface for this configuration should be a single checkbox:
- [ ] Allow insecure connections (without SSL/TLS).
There should also be an advanced UI where the power users could specify exactly if they want imaps or STARTTLS and what port to use.
If this box is checked, the client would initially figure out how to perform the encryption and then cache it for later use. If it ever fails to connect, it could do this check all over again in case server configuration had changed (perhaps asking from user first if it is wanted).
- Connect to port 143. Wait one second (or so) for the connection to establish.
- If 143 didn't answer soon enough, connect to port 993 (without killing the 143 connection).
- If connection to port 993 succeeded but port 143 didn't, use 993.
- If connection to port 143 succeeds (even if 993 connection was already started), look for STARTTLS in CAPABILITY (see the next section)
- If you see STARTTLS in capabilities, execute it. If it succeeds, use 143.
- If there is no STARTTLS capability, connect to port 993. If it succeeds, use it.
- If there is no STARTTLS capability and port 993 doesn't answer, fail.
Some IMAP servers advertise CAPABILITY already in the OK greeting:
* OK [CAPABILITY IMAP4rev1 STARTTLS] Hello.
If you see it, don't waste time executing CAPABILITY command. After performing STARTTLS, the capabilities may change. Especially important is that AUTH=PLAIN might show up after that:
* OK [CAPABILITY IMAP4rev1 STARTTLS] Hello. 1 STARTTLS 1 OK Begin TLS negotiation now. <<<TLS negotiation>>> 2 CAPABILITY * CAPABILITY IMAP4rev1 AUTH=PLAIN 2 OK
Capabilities may also change after user has logged in. Different users may even have different capabilities. Some servers announce the new capabilities after LOGIN/AUTHENTICATE:
1 LOGIN user pass 1 OK [CAPABILITY IMAP4REV1 UIDPLUS] Logged in.
If you didn't get the capability, ask for it yourself.
The most important thing is: If you see LOGINDISABLED in capabilities, NEVER try to perform plaintext authentication. It is guaranteed to fail and your client just sent the password unencrypted over the internet.
So how do you authenticate?
- If you see AUTH=x in capabilities where x is something you can handle and it's not LOGIN or PLAIN, use it.
- Some misconfigured servers may fail it anyway, so it might be worth trying the next method in list after a failure.
- If you see AUTH=PLAIN and there is no LOGINDISABLED capability, use either LOGIN command or AUTHENTICATE PLAIN.
- LOGIN command is preferred over AUTHENTICATE PLAIN because it avoids one round-trip (unless SASL-IR is also advertised).
- AUTHENTICATE PLAIN supports logging in as another user ("master user login"), but normally you don't need to use it.
- If you see LOGINDISABLED and STARTTLS in capabilities, perform STARTTLS even if it wasn't required. After STARTTLS you should be able to authenticate.
- If you still see only LOGINDISABLED and no non-plaintext AUTH=x mechanisms that you can handle, fail the authentication.
If you see SASL-IR in capabilities, you can send SASL initial response in AUTHENTICATE command. Do this when possible (and useful) to avoid one round-trip.
You may wish to support also login referrals, but they are quite rarely used.