LinkedIn Intro: Doing the Impossible on iOS [UPDATED 11/1]
October 23, 2013
Editor’s Note: Since we issued this post, Bishop Fox has extensively tested LinkedIn Intro and clarified a few of their earlier assumptions. You can see Bishop Fox’s post here.
We recently launched LinkedIn Intro — a new product that shows you LinkedIn profiles, right inside the native iPhone mail client. That’s right: we have extended Apple’s built-in iOS Mail app, a feat that many people consider to be impossible. This post is a short summary of how Intro works, and some of the ways we bent technology to our will.
With Intro, you can see at a glance the picture of the person who’s emailing you, learn more about their background, and connect with them on LinkedIn. This is what it looks like:
The iPhone mail app, before and after Intro
How Intro Came to Be
The origins of Intro go back to before the acquisition of Rapportive by LinkedIn. At Rapportive, we had built a browser extension that modified Gmail to show the profile of an email’s sender within the Gmail page. The product was popular, but people kept asking: “I love Rapportive in Gmail, when can I have it on mobile too?”
The magic of Rapportive is that you don’t have to remember to use it. Once you have it installed, it is right there inside your email, showing you everything you need to know about your contacts. You don’t need to fire up a new app or do a search in another browser tab, because the information is right there when you need it. It just feels natural.
At LinkedIn, we want to work wherever our members work. And we know that professionals spend a lot of time on their phone, checking and replying to emails — so we had to figure out how to enhance mobile email, giving professionals the information they need to be brilliant with people.
But how do we do that? Ask any iOS engineer: there is no API for extending the built-in mail app on the iPhone. If you wanted to build something like Rapportive, most people would tell you that it is impossible. Yet we figured it out.
Impossible #1: Extending the iOS Mail Client
Our key insight was this: we cannot extend the mail client, but we can add information to the messages themselves. One way to do this would be to modify the messages on the server — but then the modification would appear on all your clients, both desktop and mobile. That would not be what users want.
Instead, we can add information to messages by using a proxy server.
Rewriting messages using an IMAP proxy
Normally your device connects directly to the servers of your email provider (Gmail, Yahoo, AOL, etc.), but we can configure the device to connect to the Intro proxy server instead.
The Intro proxy server speaks the IMAP protocol just like an email provider, but it doesn’t store messages itself. Instead, it forwards requests from the device to your email provider, and forwards responses from the email provider back to the device. En route, it inserts Intro information at the beginning of each message body — we call this the top bar.
The great thing about this approach: the proxy server can tailor the top bar to the device, since it knows which device is downloading the message. It can adapt the layout to be appropriate to the screen size, and it can take advantage of the client’s latest features, because it doesn’t need to worry about compatibility with other devices.
Our proxy server is written in Ruby using EventMachine, which allows it to efficiently handle many concurrent IMAP connections. We have developed some libraries to make the evented programming model nicer to work with, including Deferrable Gratification and LSpace.
Impossible #2: Interactive UI in Email
Ok, we have a way of adding information about the sender to a message — but so far it’s just a static piece of HTML. The top bar is deliberately minimal, because we don’t want it to get in the way. But wouldn’t it be awesome if you could tap the top bar and see the full LinkedIn profile… without leaving the mail app?
“But that’s impossible,” they cry, “you can’t run JavaScript in the mail client!” And that’s true — any JavaScript in an email is simply ignored. But iOS Mail does have powerful CSS capabilities, since it uses the same rendering engine as Safari.
Recall that CSS has a :hover
state that is triggered when you hover the mouse over an element. This is used for popup menus in the navigation of many websites, or for tooltips. But what do you do on a touchscreen device, where there is no hovering or clicking, only tapping?
A little-known fact about CSS on Mobile Safari: in certain circumstances, tapping a link once simulates a :hover
state on that link, and tapping it twice has the effect of a click. Thanks to this feature, popup menus and tooltips still work on iOS.
With some creativity, we figured out how to use this effect to create an interactive user interface within a message! Just tap the top bar to see the full LinkedIn profile:
With CSS tricks we can embed an entire LinkedIn profile in a message
Impossible #3: Dynamic Content in Email
This :hover
trick allows us to have some interactivity within a message, but for more complex interactions we have to take you to the browser (where we can run a normal web app, without the mail app’s limitations). For example, if you want to connect with your contact on LinkedIn, we take you to Safari.
That’s fine, but it leaves us with a problem: the top bar needs to show if you’re already connected with someone. Say you send an invitation, and the other person accepts — now you’re connected, but if you open the same email again, it still says that you’re not connected!
This is because once a message has been downloaded, an IMAP client may assume that the message will never change. It is cached on the device, and unlike a web page, it never gets refreshed. Now that you’re connected, the top bar content needs to change. How do we update it?
Our solution: the connect button is in a tiny <iframe>
which is refreshed every time you open the message. And if you open the message while your device is offline? No problem: the iframe
is positioned on top of an identical-looking button in the static top bar HTML. If the iframe
fails to load, it simply falls back to the connection status at the time when the message was downloaded.
This allows the top bar to contain dynamic content, even though it’s impossible for the server to modify a message once it has been downloaded by the device.
Using an embedded iframe to keep the connection status up-to-date, within an otherwise static top bar
Impossible #4: Easy Installation
Once we got the IMAP proxy working, we were faced with another problem: how do we configure a device to use the proxy? We cannot expect users to manually enter IMAP and SMTP hostnames, choose the correct TLS settings, etc — it’s too tedious and error-prone.
Fortunately, Apple provides a friendly way of setting up email accounts by using configuration profiles — a facility that is often used in enterprise deployments of iOS devices. Using this technique, we can simply ask the user for their email address and password, autodiscover the email provider settings, and send a configuration profile to the device. The user just needs to tap “ok” a few times, and then they have a new mail account.
Moreover, for Gmail and Google Apps accounts, we can use OAuth, and never need to ask for the user’s password. Even better!
iOS configuration profiles make setup of new email accounts a breeze
Security and Privacy
We understand that operating an email proxy server carries great responsibility. We respect the fact that your email may contain very personal or sensitive information, and we will do everything we can to make sure that it is safe. Our principles and key security measures are detailed in our pledge of privacy.
Conclusion
When we first built Rapportive for Gmail, people thought that we were crazy — writing a browser extension that modified the Gmail page on the fly, effectively writing an application inside someone else’s application! But it turned out to be a great success, and many others have since followed our footsteps and written browser extensions for Gmail.
Similarly, Intro’s approach of proxying IMAP is a novel way of delivering software to users. It operates at the limit of what is technically possible, but it has a big advantage: we can enhance the apps you already use. Of course the idea isn’t limited to the iPhone, so watch out for new platforms coming your way soon :)
This post has only scratched the surface of the interesting challenges we have overcome while building Intro. In follow-up posts we will talk about some of our CSS techniques, testing and monitoring tools, things we do to achieve high performance and high reliability, and more. In the meantime, check out Intro and let us know what you think!
Update, 10/24/13
We wanted to provide additional information about how LinkedIn Intro works, so that we can address some of the questions that have been raised. There are some points that we want to reinforce in order to make sure members understand how this product works:
- You have to opt-in and install Intro before you see LinkedIn profiles in any email.
- Usernames, passwords, OAuth tokens, and email contents are not permanently stored anywhere inside LinkedIn data centers. Instead, these are stored on your iPhone.
- Once you install Intro, a new Mail account is created on your iPhone. Only the email in this new Intro Mail account goes via LinkedIn; other Mail accounts are not affected in any way.
- All communication from the Mail app to the LinkedIn Intro servers is fully encrypted. Likewise, all communication from the LinkedIn Intro servers to your email provider (e.g. Gmail or Yahoo! Mail) is fully encrypted.
- Your emails are only accessed when the Mail app is retrieving emails from your email provider. LinkedIn servers automatically look up the "From" email address, so that Intro can then be inserted into the email.
For any additional questions, please visit the LinkedIn Intro Pledge of Privacy which provides more details. We hope that this gives you all the information about how Intro works. It is our goal to make our members more productive and successful, and we think LinkedIn Intro helps us towards achieving that goal.