RDCOM client no longer supported. Trying to email report using Azure token but getting errors.

Problem: Im a fairly novice user running a script in RStudio, and it emailed out a report using outmail from the RDCOMClient library. I installed and updated RStudio and am getting error messages that RDCOMClient is no longer supported. An AI query recommended I try to setup the report to send through Microsoft Azure with token and client secret. Though Ive created a file with the client secret and have provided RStudio the path, it claims the file with the secret doesn`t exist. Any guidance you can offer? The script with errors is pasted below:

------------------------------------------------------------

BLK Tactical VP Daily Holdings + HTML Report + Graph Email

Consolidated Script with GUARANTEED Runtime Secret Loading #

options(stringsAsFactors = FALSE)
Sys.setenv(RSTUDIO_PANDOC = C:/Program Files/RStudio/bin/rstudio-pandoc)

suppressPackageStartupMessages({

  • library(rmarkdown)
  • library(tidyverse)
  • library(openxlsx)
  • library(lubridate)
  • library(AzureAuth)
  • library(httr)
  • library(jsonlite)
  • library(base64enc)
  • })
    There were 11 warnings (use warnings() to see them)

============================================================

0) RUNTIME GRAPH SECRET LOADING (GUARANTEED FIX)

============================================================

GRAPH_SECRET_FILE <- Y:/R/BLK/secure/graph_client_secret.txt

if (!file.exists(GRAPH_SECRET_FILE)) {

  • stop(Graph secret file not found: , GRAPH_SECRET_FILE) }
    Error: Graph secret file not found: Y:/R/BLK/secure/graph_client_secret.txt

client_secret <- trimws(readLines(GRAPH_SECRET_FILE, warn = FALSE))
Error in file(con, r) : cannot open the connection In addition: Warning message:
In file(con, r) :
cannot open file Y:/R/BLK/secure/graph_client_secret.txt: No such file or directory

if (!nzchar(client_secret)) {

  • stop(Graph client secret file exists but is empty) }
    Error: object client_secret not found

Sys.setenv(

  • BLK_GRAPH_TENANT_ID = 46e16835-c804-41de-be3c-55835d14dee4,
  • BLK_GRAPH_CLIENT_ID = aee4dd30-675d-45d8-b658-1d4bd198d0b3,
  • BLK_GRAPH_CLIENT_SECRET = client_secret
  • )
    Error in Sys.setenv(BLK_GRAPH_TENANT_ID = 46e16835-c804-41de-be3c-55835d14dee4, :
    object client_secret not found

Hard fail if this ever breaks again

stopifnot(nzchar(Sys.getenv(BLK_GRAPH_CLIENT_SECRET)))
Error: nzchar(Sys.getenv(BLK_GRAPH_CLIENT_SECRET)) is not TRUE

============================================================

1) PATHS

============================================================

in_zip <- Y:/R/BLK/Temp/attachment.zip
temp_dir <- Y:/R/BLK/Temp
in_csv <- file.path(temp_dir, BLK TA Daily Holdings - Prior Close.csv)

out_dir <- Y:/R/BLK/Outputs
rmd_in <- Y:/R/BLK/Inputs/BLK_TA_Calc.Rmd

if (!dir.exists(out_dir)) dir.create(out_dir, recursive = TRUE)

============================================================

2) UNZIP + READ CSV

============================================================

if (!file.exists(in_zip)) stop(Input zip not found: , in_zip)
unzip(in_zip, exdir = temp_dir)

if (!file.exists(in_csv)) stop(Holdings CSV not found: , in_csv)

blk_raw <- read.csv(in_csv, stringsAsFactors = FALSE, check.names =
FALSE)

normalize_names <- function(x) {

  • x |> trimws() |> tolower() |> gsub([^a-z0-9]+, _, _) |>
  • gsub(^_|_$, ``, _)
    Error: unexpected > in:
    normalize_names <- function(x) { x |>

}
Error: unexpected } in }
names(blk_raw) <- normalize_names(names(blk_raw))
Error in normalize_names(names(blk_raw)) :
could not find function normalize_names

required_cols <- c(

  • period_end_date,
  • cusip_number,
  • asset_class,
  • security_name,
  • base_market_value,
  • percent_of_fund
  • )

missing <- setdiff(required_cols, names(blk_raw)) if (length(missing)

  1. stop(Missing required columns: , paste(missing, collapse = , ))
    Error: Missing required columns: period_end_date, cusip_number, asset_class, security_name, base_market_value, percent_of_fund

============================================================

3) AS-OF DATE

============================================================

blk_raw$period_end_date <- mdy(blk_raw$period_end_date)
Error in $<-.data.frame(*tmp*, period_end_date, value = numeric(0)) :
replacement has 0 rows, data has 19
if (all(is.na(blk_raw$period_end_date))) stop(Unable to parse Period End Date)
Error: Unable to parse Period End Date

asof <- as.character(blk_raw$period_end_date[1])
if (!nzchar(asof)) stop(As-of date could not be determined)
Error in if (!nzchar(asof)) stop(As-of date could not be determined) :
argument is of length zero

blk_raw$cusip_number <- gsub(^``, ``, blk_raw$cusip_number) Error in $<-.data.frame(tmp`, cusip_number, value = character(0)) :
replacement has 0 rows, data has 19

write.xlsx(

  • blk_raw,
  • file = file.path(out_dir, paste0(BLK TA - , asof, .xlsx)),
  • overwrite = TRUE
  • )

============================================================

4) WORKING DATA + CLASSIFICATION

============================================================

blk <- blk_raw |>
Error: unexpected > in blk <- blk_raw |>
transmute(

  • CUSIP = cusip_number,
    
  • AssetClass = asset_class,
    
  • SecurityName = security_name,
    
  • MarketValueUSD = as.numeric(base_market_value),
    
  • WeightPct = as.numeric(percent_of_fund)
    
  • )
    Error in transmute(CUSIP = cusip_number, AssetClass = asset_class, SecurityName = security_name, :
    object cusip_number not found

etf_override <- c(900934845, 900934852)

blk <- blk |>
Error: unexpected > in blk <- blk |>
mutate(

  • Type = case_when(
    
  •   CUSIP %in% etf_override ~ `ETF`,
    
  •   str_detect(AssetClass, `CASH`) ~ `CASH`,
    
  •   AssetClass == `FUTURE` ~ `FUTURE`,
    
  •   AssetClass == `EQUITY` &
    
  •     str_detect(SecurityName, `TRANSAMERICA|TA | VP`) &
    
  •     !str_detect(SecurityName, `\\bETF\\b`) ~ `FUND`,
    
  •   AssetClass == `EQUITY` ~ `ETF`,
    
  •   TRUE ~ `OTHER`
    
  • )
    
  • )
    Error in CUSIP %in% etf_override : object CUSIP not found

blkta <- blk |>
Error: unexpected > in blkta <- blk |>
select(

  • CUSIP, Type,
    
  • `Security Name` = SecurityName,
    
  • `Market Value - USD` = MarketValueUSD,
    
  • `Weight - %` = WeightPct
    
  • ) |>
    Error: unexpected > in:
    Weight - % = WeightPct ) |>

mutate(

  • `Market Value - USD` = round(`Market Value - USD`, 0),
    
  • `Weight - %` = round(`Weight - %`, 2)
    
  • )
    Error in mutate(Market Value - USD = round(Market Value - USD, 0), :
    object Market Value - USD not found

blklist <- split(blkta, blkta$Type)
Error in split(blkta, blkta$Type) : object blkta not found

add_total <- function(df) {

  • df2 <- df |> select(-Type)
    Error: unexpected > in:
    add_total <- function(df) { df2 <- df |>

bind_rows(

  • df2,
    
  • tibble(
    
  •   CUSIP = ``,
    
  •   `Security Name` = ``,
    
  •   `Market Value - USD` = sum(df2$`Market Value - USD`, na.rm = TRUE),
    
  •   `Weight - %` = sum(df2$`Weight - %`, na.rm = TRUE)
    
  • )
    
  • )
    Error in list2(...) : object df2 not found

}
Error: unexpected } in }
blklist <- lapply(blklist, add_total)
Error in h(simpleError(msg, call)) :
error in evaluating the argument X in selecting a method for function lapply: object blklist not found

============================================================

5) RENDER HTML

============================================================

html_file <- paste0(BLK TA - , asof, .html) html_out <-
file.path(out_dir, html_file)

render(

  • input = rmd_in,
  • output_file = html_file,
  • output_dir = out_dir,
  • envir = globalenv()
  • )

processing file: BLK_TA_Calc.Rmd
|....................... | 17%
ordinary text without R code

|.............................................. | 33%
label: unnamed-chunk-1 (with options)
List of 1
$ include: logi FALSE

|..................................................................... | 50%
inline R code fragments

|............................................................................................ | 67%
label: unnamed-chunk-2 (with options)
List of 2
echo : logi FALSE results: chr asis

Quitting from lines 16-38 (BLK_TA_Calc.Rmd) Error in nrow(blkta[blkta$Type == ETF, ]) : object blkta not found

if (!file.exists(html_out)) stop(HTML was not created)

============================================================

6) MICROSOFT GRAPH EMAIL (APP ONLY)

============================================================

token <- AzureAuth::get_azure_token(

  • resource = https://graph.microsoft.com/.default,
  • tenant = Sys.getenv(BLK_GRAPH_TENANT_ID),
  • app = Sys.getenv(BLK_GRAPH_CLIENT_ID),
  • password = Sys.getenv(BLK_GRAPH_CLIENT_SECRET),
  • auth_type = client_credentials,
  • version = 2
  • )
    Error in process_aad_response(res) :
    Unauthorized (HTTP 401). Failed to obtain Azure Active Directory token. Message:
    AADSTS7000216: client_assertion, client_secret or request is required for the client_credentials grant type. Trace ID: e7798ef2-89d0-4563-85d1-6c59cb193a00 Correlation ID: cbb1f8ea-76d5-4e03-8064-1a71da876325 Timestamp: 2026-05-07 20:04:43Z.

access_token <- token$credentials$access_token
Error: object token not found

send_graph_mail <- function(from_user, to, subject, body, attachment)
{

  • url <- sprintf(https://graph.microsoft.com/v1.0/users/%s/sendMail,
  • from_user)
  • recipients <- lapply(to, function(x) list(emailAddress =
  • list(address = x)))
  • raw <- readBin(attachment, raw, file.info(attachment)$size)
  • payload <- list(
  • message = list(
    
  •   subject = subject,
    
  •   body = list(contentType = `Text`, content = body),
    
  •   toRecipients = recipients,
    
  •   attachments = list(list(
    
  •     `@odata.type` = `#microsoft.graph.fileAttachment`,
    
  •     name = basename(attachment),
    
  •     contentBytes = base64enc::base64encode(raw),
    
  •     contentType = `text/html`
    
  •   ))
    
  • ),
    
  • saveToSentItems = TRUE
    
  • )
  • resp <- POST(
  • url,
    
  • add_headers(Authorization = paste(`Bearer`, access_token)),
    
  • body = toJSON(payload, auto_unbox = TRUE),
    
  • encode = `json`
    
  • )
  • if (status_code(resp) >= 300)
  • stop(`Graph sendMail failed: `, content(resp, `text`)) }
    

send_graph_mail(

  • from_user = kane.cotton@transamerica.com,
  • to = c(
  • `first.last@transamerica.com`,
    
  • ),
  • subject = Daily BlackRock Tactical Update,
  • body = paste(Please open the HTML in Chrome:, html_out),
  • attachment = html_out
  • )
    Error in paste(Bearer, access_token) : object access_token not found >

message(SUCCESS: Report generated and email sent → , html_out)
SUCCESS: Report generated and email sent → Y:/R/BLK/Outputs/BLK TA - .html