Version:
Only show these results:

Create grants with IMAP authentication

This page explains how to authenticate end users to your Nylas application using IMAP auth.

🔍 Nylas creates only one grant per email address in each application. If an end user authenticates with your Nylas application using the email address associated with an existing grant, Nylas re-authenticates the grant instead of creating a new one.

IMAP connections don't require a provider auth app, and they don't include calendar functionality.

New options for Yahoo, Exchange, and iCloud users

If you are authenticating Yahoo, Exchange on-prem, or iCloud users, you can either connect them using IMAP, or use the dedicated connectors for those providers. If you connect using IMAP, you can only access email data from the provider, even if the service also provides calendar features.

If you authenticate Yahoo users, you should implement the new v3 Yahoo OAuth method instead of IMAP authentication to improve reliability.

Create a connector

🔍 IMAP does not support the concept of scopes, so don't list any during the authentication process.

Create a connector by making a call to POST /v3/connectors and setting the provider to imap.

{
"name": "Staging App 1",
"provider": "imap"
}

You can also create a connector using the Nylas SDKs, as in the following examples.

import 'dotenv/config'
import Nylas from 'nylas'

const config = {
apiKey: process.env.NYLAS_API_KEY,
apiUri: process.env.NYLAS_API_URI,
}

const nylas = new Nylas(config)

async function createConnector() {
try {
const connector = await nylas.connectors.create({
requestBody: {
name: 'aol',
provider: 'imap',
}
})

console.log('Connector created:', connector)
} catch (error) {
console.error('Error creating connector:', error)
}
}

createConnector()
from dotenv import load_dotenv
load_dotenv()

import os
import sys
from nylas import Client

nylas = Client(
os.environ.get('NYLAS_API_KEY'),
os.environ.get('NYLAS_API_URI')
)

connector = nylas.connectors.create(
request_body={
"name": "aol",
"provider": "imap"
}
)
require 'nylas'

nylas = Nylas::Client.new(api_key: "<NYLAS_API_KEY>")

request_body = {
name: "aol",
provider: "imap",
}

connector = nylas.connectors.create(request_body: request_body)

puts connector
import com.nylas.NylasClient;
import com.nylas.models.*;

public class connector {
public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
CreateConnectorRequest request = new CreateConnectorRequest.Imap();

nylas.connectors().create(request);
}
}
import com.nylas.NylasClient
import com.nylas.models.CreateConnectorRequest

fun main(args: Array<String>) {
val nylas: NylasClient = NylasClient(apiKey = "<NYLAS_API_KEY>")
val request : CreateConnectorRequest = CreateConnectorRequest.Imap();

nylas.connectors().create(request)
}

Create grants for IMAP users

Nylas v3 offers Hosted OAuth and Custom authentication for the supported IMAP providers.

Hosted OAuth

You can create grants with Hosted OAuth. Learn more about creating grants with Hosted Oauth and an API key and Hosted OAuth and an access token.

You can also start the Hosted auth flow using the Nylas SDKs, as in the examples below.

import 'dotenv/config'
import express from 'express'
import Nylas from 'nylas'

const config = {
clientId: process.env.NYLAS_CLIENT_ID,
clientSecret: process.env.NYLAS_CLIENT_SECRET,
callbackUri: "http://localhost:3000/oauth/exchange",
apiKey: process.env.NYLAS_API_KEY,
apiUri: process.env.NYLAS_API_URI,
}

const nylas = new Nylas({
apiKey: config.apiKey,
apiUri: config.apiUri
})

const app = express()
const port = 3000

// Route to initialize authentication
app.get('/nylas/auth', (req, res) => {
const authUrl = nylas.auth.urlForOAuth2({
clientId: config.clientId,
provider: 'imap',
redirectUri: config.redirectUri,
loginHint: process.env.AOL_IMAP_USERNAME,
state: "state"
})

res.redirect(authUrl)
})

// Callback route Nylas redirects to
app.get('/oauth/exchange', async (req, res) => {
const code = req.query.code

if (!code) {
res.status(400).send('No authorization code returned from Nylas')

return
}

try {
const response = await nylas.auth.exchangeCodeForToken({
clientId: config.clientId,
redirectUri: config.redirectUri,
code,
})

const { grantId } = response

res.status(200)
} catch (error) {
res.status(500).send('Failed to exchange authorization code for token')
}
})
from dotenv import load_dotenv
load_dotenv()

import json
import os

from functools import wraps
from io import BytesIO
from flask import Flask, request, redirect, g
from nylas import Client

nylas = Client(
os.environ.get("NYLAS_CLIENT_ID"),
os.environ.get("NYLAS_API_URI")
)

REDIRECT_CLIENT_URI = 'http://localhost:9000/oauth/exchange'
flask_app = Flask(__name__)
@flask_app.route("/nylas/generate-auth-url", methods=["GET"])

def build_auth_url():
auth_url = nylas.auth.url_for_oauth2(
config={
"client_id": os.environ.get("NYLAS_CLIENT_ID"),
"provider": 'imap',
"redirect_uri": REDIRECT_CLIENT_URI,
"login_hint": os.environ.get("AOL_IMAP_USERNAME"),
"state": "state",
}
)

return redirect(auth_url)

@flask_app.route("/oauth/exchange", methods=["GET"])
def exchange_code_for_token():
code_exchange_response = nylas.auth.exchange_code_for_token(
request={
"code": request.args.get('code'),
"client_id": os.environ.get("NYLAS_CLIENT_ID"),
"redirect_uri": REDIRECT_CLIENT_URI
}
)

return {
'email': code_exchange_response.email,
'grant_id': code_exchange_response.grant_id
}
# frozen_string_literal: true

require 'nylas'
require 'sinatra'

set :show_exceptions, :after_handler

error 404 do
'No authorization code returned from Nylas'
end

error 500 do
'Failed to exchange authorization code for token'
end

nylas = Nylas::Client.new(api_key: "<NYLAS_API_KEY>")

get '/nylas/auth' do
config = {
client_id: "<NYLAS_CLIENT_ID>",
provider: 'imap',
redirect_uri: 'http://localhost:4567/oauth/exchange',
login_hint: '<AOL_IMAP_USER>',
state: "<state>"
}

url = nylas.auth.url_for_oauth2(config)
redirect url
end

get '/oauth/exchange' do
code = params[:code]
status 404 if code.nil?

begin
response = nylas.auth.exchange_code_for_token({
client_id: "<NYLAS_CLIENT_ID>",
redirect_uri: 'http://localhost:4567/oauth/exchange',
code: code
})
rescue StandardError
status 500
else
puts response

grant_id = response[:grant_id]
email = response[:email]

"Grant_Id: #{grant_id} \n Email: #{email}"
end
end
import java.util.*;
import static spark.Spark.*;
import com.nylas.NylasClient;
import com.nylas.models.*;

public class AuthRequest {
public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();

get("/nylas/auth", (request, response) -> {
List<String> scope = new ArrayList<>();
UrlForAuthenticationConfig config = new UrlForAuthenticationConfig(
"<NYLAS_CLIENT_ID>",
"http://localhost:4567/oauth/exchange",
AccessType.ONLINE,
AuthProvider.IMAP,
Prompt.DETECT,
scope,
true,
"sQ6vFQN",
"example@aol.com");

String url = nylas.auth().urlForOAuth2(config);

response.redirect(url);

return null;
});

get("/oauth/exchange", (request, response) -> {
String code = request.queryParams("code");

if(code == null) { response.status(401);}
assert code != null;

CodeExchangeRequest codeRequest = new CodeExchangeRequest(
"http://localhost:4567/oauth/exchange",
code,
"<NYLAS_CLIENT_ID>",
"nylas");

try {
CodeExchangeResponse codeResponse = nylas.auth().exchangeCodeForToken(codeRequest);

return "%s".formatted(codeResponse);
} catch(Exception e) {
return "%s".formatted(e);
}
});
}
}
import com.nylas.NylasClient
import com.nylas.models.AccessType
import com.nylas.models.AuthProvider
import com.nylas.models.Prompt
import com.nylas.models.UrlForAuthenticationConfig
import spark.kotlin.Http
import spark.kotlin.ignite

fun main(args: Array<String>) {
val nylas: NylasClient = NylasClient(apiKey = "<NYLAS_API_KEY>")
val http: Http = ignite()

http.get("/nylas/auth") {
val scope = listOf("https://www.googleapis.com/auth/userinfo.email")
val config : UrlForAuthenticationConfig = UrlForAuthenticationConfig(
"<NYLAS_CLIENT_ID>",
"http://localhost:4567/oauth/exchange",
AccessType.ONLINE,
AuthProvider.IMAP,
Prompt.DETECT,
scope,
true,
"sQ6vFQN",
"<email_to_connect>")

val url = nylas.auth().urlForOAuth2(config)

response.redirect(url)
}
}

http.get("/oauth/exchange") {
val code : String = request.queryParams("code")

if(code == "") { response.status(401) }

val codeRequest : CodeExchangeRequest = CodeExchangeRequest(
"http://localhost:4567/oauth/exchange",
code,
"<NYLAS_CLIENT_ID>",
"nylas"
)

try {
val codeResponse : CodeExchangeResponse =
nylas.auth().exchangeCodeForToken(codeRequest)
codeResponse
} catch (e : Exception) {
e
}
}

Custom authentication

You can create grants with Custom authentication (POST /v3/connect/custom) if you already have a password or app password for the end user.

The example below shows how to make a Custom authentication request with the correct provider and settings. The rest of the authentication process follows the same process as for non-IMAP grant creation.

curl -X POST https://api.us.nylas.com/v3/connect/custom \
--header 'Authorization: Bearer <NYLAS_API_KEY>' \
--header 'Content-Type: application/json' \
--data-raw '{
"provider": "imap",
"settings": {
"imap_username": "<IMAP_USERNAME>",
"imap_password": "<IMAP_PASSWORD>",
"imap_host": "imap.mail.me.com",
"imap_port": 993,
"smtp_host": "smtp.mail.me.com",
"smtp_port": 465
}
}'

For more information, see the Custom auth documentation.

Static IP support for IMAP accounts

Some email servers in secure environments only accept connections and data from a known list of sender IP addresses. If you need to connect to a server with these settings, you can add static IP support to your Nylas plan.

When you add static IP support to your plan, Nylas uses only a specific set of static IPs when connecting your application's users. You can then provide the administrators of those email servers with an allowlist of Nylas IPs so the user can authenticate with that server.

Static IP support is currently available for IMAP. Support for Exchange on-premises servers is coming soon.

To add static IP support to your Nylas account, contact your account representative or Nylas support.

Error handling for IMAP Hosted authentication

Nylas creates a grant only if both the IMAP settings are validated and the provider accepts the end user's login credentials. When an error occurs, the redirect_uri includes an error_type query parameter when the auth process is complete. The possible error_type values are...

  • provider_not_responding: The IMAP provider didn't respond to the login request from Nylas.
  • invalid_authentication: The provider responded with an incorrect credential error. Nylas prompts the user with an error message.
  • auth_limit_reached: The user entered an incorrect password three times. Nylas redirects back to your application's redirect_uri with the error code instead of showing an error message.

What's next?

Now that you have an IMAP connector and a grant, you can...