Only show these results:

Create grants with IMAP authentication

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

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

Before you begin

Before you can create a grant with IMAP authentication, you need the following prerequisites:

Authenticate Yahoo users using IMAP

If you are authenticating Yahoo users, you should use the new v3 Yahoo OAuth method instead of IMAP authentication.

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",
"[email protected]");

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 '{
"provider": "imap",
"settings":
{
"imap_username": "<ICLOUD-EMAIL>",
"imap_password": "<ICLOUD-PASSWORD>",
"imap_host": "imap.mail.me.com",
"imap_port": 993,
"type": "icloud"
}
}'

For more information, see the Custom auth documentation.

Error handling for IMAP Hosted authentication

An IMAP hosted authentication has special and specific error events including invalid_authentication, provider_not_responding and auth_limit_reached. Nylas creates a grant only if both the IMAP settings pass validation, and the provider accepts the end user's login credentials.

  • provider_not_responding: The IMAP provider does not 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 hosted authentication redirects back to your application 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...