The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
Most major mail providers have moved to OAuth2.0 as their preferred (and, in many cases, only) authentication method for IMAP. Instead of sending your password, you send a short-lived access token that authorizes a specific scope of access to your mailbox.
This vignette shows the exact steps and R code to obtain, use, and refresh an OAuth2.0 access token for the Gmail IMAP server. The same logic applies to other providers (Outlook/Office 365, Yahoo, AOL, …) by swapping the authorization endpoints and scope. The reference for Google’s flow is https://developers.google.com/identity/protocols/oauth2.
We use the httr package to run the OAuth2.0 flow and jsonlite to read the credentials file, so install them first if needed:
install.packages(c("httr", "jsonlite"))IMPORTANT — libcurl version. The libcurl feature that transmits the bearer token is only reliable on libcurl >= 7.65.0 (released 2019-05-22). Check the version the curl R package is linked against:
curl::curl_version()$version## [1] "7.81.0"
If it is older, update libcurl (and reinstall curl) before continuing, otherwise you may get a SASL error during authentication.
The whole process is:
configure_imap(xoauth2_bearer = ...);Steps 1–3 are done once, in the browser; steps 4–6 are R code.
mRpostman), and click Create.You do not need to enable the Gmail API: IMAP access is granted by the OAuth scope https://mail.google.com/, not by the Gmail API. IMAP is enabled by default on Gmail accounts.
Navigate to APIs & Services > OAuth consent screen (in the redesigned console this section is called Google Auth Platform).
User type: choose External and click Create.
Fill in the required fields: App name, User support email, and, at the bottom, a Developer contact email. Save and continue.
Scopes: click Add or remove scopes, then, in the “manually add scopes” box, paste:
https://mail.google.com/
Click Add to table, then Update and Save and continue. (This is a restricted scope; while your app stays in Testing mode it works for test users without Google verification.)
Test users: add the e-mail address of the account you will log in with (e.g. your_user@gmail.com) and save.
The account you authenticate with in Step 4 must be listed here as a test user, otherwise Google returns an access_denied error.
redirect_uri_mismatch in the flow below).The downloaded file looks like this (an "installed" client):
{"installed":{"client_id":"XXXX.apps.googleusercontent.com",
"project_id":"your-project","auth_uri":"https://accounts.google.com/o/oauth2/auth",
"token_uri":"https://oauth2.googleapis.com/token",
"client_secret":"GOCSPX-XXXX","redirect_uris":["http://localhost"]}}Read the client id and secret from it in R:
cred <- jsonlite::fromJSON("path/to/client_secret_XXXX.json")$installedBelow are two ways to get a token. Option A is the shortest and works out of the box on most desktops. Use Option B if Option A fails to start its local web server (common inside RStudio, or on headless/remote machines).
Both request access_type = "offline" so that a refresh token is also returned (see Step 6).
httr’s built-in flow (recommended)httr::oauth2.0_token() opens your browser, runs a local callback server, and caches the token in a .httr-oauth file.
library(httr)
gmail_app <- oauth_app("mRpostman",
key = cred$client_id,
secret = cred$client_secret)
token_obj <- oauth2.0_token(
endpoint = oauth_endpoints("google"),
app = gmail_app,
scope = "https://mail.google.com/",
cache = TRUE
)
token <- token_obj$credentials$access_tokenWhen the browser shows “Google hasn’t verified this app”, click Advanced > Go to <your app> (unsafe) — this is expected while the app is in Testing mode — then Allow.
This avoids the local callback server entirely: you open the authorization URL, approve access, and paste back the code shown in the browser’s address bar.
library(httr)
redirect_uri <- "http://localhost"
scope <- "https://mail.google.com/"
auth_url <- modify_url("https://accounts.google.com/o/oauth2/auth",
query = list(client_id = cred$client_id,
redirect_uri = redirect_uri,
response_type = "code",
scope = scope,
access_type = "offline",
prompt = "consent"))
browseURL(auth_url)After you approve, the browser is redirected to http://localhost/?code=...&scope=.... The page will fail to load (“unable to connect”) — that is fine. Copy the value between code= and &scope from the address bar and paste it below (authorization codes are single-use and expire in minutes, so exchange it right away):
code_in <- "PASTE_THE_CODE_HERE"
resp <- POST("https://oauth2.googleapis.com/token", encode = "form",
body = list(code = code_in,
client_id = cred$client_id,
client_secret = cred$client_secret,
redirect_uri = redirect_uri,
grant_type = "authorization_code"))
token_data <- content(resp)
token <- token_data$access_tokenYour token should be a long string starting with "ya29.". If token is NULL, inspect content(resp) — an invalid_grant error means the code was already used or expired, so re-run browseURL(auth_url) to get a fresh one.
Pass the access token to configure_imap() via the xoauth2_bearer argument (no password):
library(mRpostman)
con <- configure_imap(
url = "imaps://imap.gmail.com",
username = "your_user@gmail.com",
use_ssl = TRUE,
xoauth2_bearer = token
)
con$list_server_capabilities()If this returns the server’s capabilities, you are authenticated and can use any mRpostman method (select_folder(), search_*(), fetch_*(), …).
Access tokens are short-lived (about 1 hour). The refresh token returned in Step 4 (thanks to access_type = "offline") lets you mint a new access token without going through the browser again.
If you used Option A, httr refreshes automatically; you can also force it:
token_obj$refresh()
token <- token_obj$credentials$access_tokenIf you used Option B, exchange the stored refresh token directly:
refresh <- POST("https://oauth2.googleapis.com/token", encode = "form",
body = list(client_id = cred$client_id,
client_secret = cred$client_secret,
grant_type = "refresh_token",
refresh_token = token_data$refresh_token))
token <- content(refresh)$access_tokenThen reopen (or update) the connection with the new token. To swap the token on an existing connection object, use con$reset_xoauth2_bearer(token).
access_denied / “hasn’t been verified by Google”: the account you logged in with is not in the consent screen’s Test users list (Step 2.4), or it is not the account that owns the project. Add it as a test user.redirect_uri_mismatch: your OAuth client is a Web application, not a Desktop app. Recreate it as a Desktop app (Step 3).createTcpServer: address already in use (Option A): the local callback port is busy — often a leftover server from a previous attempt in the same R session. Run httpuv::stopAllServers() and retry; if that fails, fully quit and reopen RStudio (a mere “Restart R” does not release the port), or switch to Option B, which needs no local server.SASL error during authentication: your libcurl is likely older than 7.65.0. Update it and reinstall the curl R package (see the Introduction).oauth_endpoints("google") already fills them in), and set url accordingly, e.g. imaps://outlook.office365.com for Office 365.These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.