How to retrieve Outlook inbox emails using R RDCOMClient?
Here is some sample code I got to work by trial and error:
library(RDCOMClient)
folderName = "AUX"
## create outlook object
OutApp <- COMCreate("Outlook.Application")
outlookNameSpace = OutApp$GetNameSpace("MAPI")
folder <- outlookNameSpace$Folders(1)$Folders(folderName)
# Check that we got the right folder
folder$Name(1)
emails <- folder$Items
# Just doing first 10, get total number with emails()$Count()
for (i in 1:10)
{
subject <- emails(i)$Subject(1)
# Replace "#78" with the text you are looking for in Email Subject line
if (grepl("#78", subject)[1]){
print(emails(i)$Body())
break
}
}
Sorry, but I don't know why some of these COM object require parameters (like Subject(1)), but others don't (like Body()). This worked for me on Outlook 2013, but it should also work on all versions of Outlook from 2007 on.
To get more info on the Outlook Object model I would suggest you either get Ken Slovak's Outlook 2007 book (still relevent for later versions of Outlook), or else check out my personal website, http://www.gregthatcher.com (check out the "Scripts" section -- I have been compiling these for many years.)
How to retrieve emails by date using RDCOMClient
Use Items.Find/FindNext
or Items.Restrict
with a query like [ReceivedTime] >= '02/20/2020 00:00am'
Using RDCOMClient to search Outlook inbox
I think something like this should work. It should search for any messages containing the specified phrase, and download each of their attachments.
library(RDCOMClient)
library(fs)
search.phrase <- 'test email executed at'
save.fldr <- tempdir() # Set a root folder to save attachments into
print(save.fldr)
outlook_app <- COMCreate("Outlook.Application")
search <- outlook_app$AdvancedSearch(
"Inbox",
paste0("http://schemas.microsoft.com/mapi/proptag/0x0037001E ci_phrasematch '", search.phrase, "'")
)
Sys.sleep(10) # Wait some time to allow search to complete
results <- search[['Results']]
for(i in c(1:results[['Count']])){ # Loop through search results
attachments.obj <- results[[i]][['attachments']] # Gets the attachment object
if(attachments.obj[['Count']] > 0){ # Check if there are attachments
attach.fldr <- file.path(save.fldr, path_sanitize(results[[i]][['Subject']])) # Set folder name for attachments based on email subject
if(!dir.exists(attach.fldr)){
dir.create(attach.fldr) # Create the folder for the attachments if it doesn't exist
}
for(a in c(1:attachments.obj[['Count']])){ # Loop through attachments
save.path <- file.path(attach.fldr, attachments.obj[[a]][['FileName']]) # Set the save path
print(save.path)
attachments.obj[[a]]$SaveAsFile(save.path) # Save the attachment
}
}
}
R, RDCOMClient and Outlook: Access inbox messages with shared addresses
Consider Outlook's Stores Object:
OutApp <- COMCreate("Outlook.Application")
OutStores <- OutApp$Session()$Stores()
# 1ST ACCOUNT
myfolder <- OutStores[[1]]$GetRootFolder()$folders(folderName)
# 2ND ACCOUNT
myfolder <- OutStores[[2]]$GetRootFolder()$folders(folderName)
...
Even loop through all stores:
OutApp <- COMCreate("Outlook.Application")
OutStores <- OutApp$Session()$Stores()
store_count <- OutStores$Count()
for (i in 1:store_count) {
myfolder <- OutStores[[i]]$GetRootFolder()$folders(folderName)
emails <- myfolder$Items
for (i in 1:10) {
subject <- emails(i)$Subject()
print(subject)
}
}
# QUIT APPLICATION
OutApp$Quit()
# RELEASE COM RESOURCES
subject <- NULL; emails <- NULL; myfolder <- NULL
OutStores <- NULL; OutApp <- NULL
gc()
Is there a way to find/read the Sender Email Address using R, RDCOMClient
The problem is that exchange stores the sender address as either the normal smtp version of the address for external users, but for Exchange users it uses the MS Exchange address. To get the normal smtp address, you have to look up the exchange user on and get their normal smtp email address.
You may want to look at the extrospectr
package on github. I haven't used it but it looks like it would give you a clean inbox like you're looking for.
If you look at the .lookup_exchange_sender
function in the file read_inbox.R
it shows how they handled looking up the address. First you have to look at what type of user the Sender
is (which you can do by retrieving the Sender
property of the MailItem, and then the AddressEntryUserType property, which has this enumeration). This ends up like emails(2)$Sender()$AddressEntryUserType()
.
Then then if it's an Exchange user, you would need to get the Sender
property of the MailItem (which is an AddressEntry) and then use the GetExchangeUser
method on the AddressEntry to return an ExchangeUser object. Once you have that you just need to access the PrimarrySMTPAddress property of the ExchangeUser.
When you put it all together, it looks like this: emails(2)$Sender()$GetExchangeUser()$PrimarySMTPAddress()
.
Link to extrospectr
on github:
https://github.com/aecoleman/extrospectr
This explains the Outlook methodology for what's stored in the sender email property:
SenderEmailAddress property does not contain a standard email address for internal contacts
RDCOMClient read email from a non-Outlook file path
Turned out there was a wrong object reference in my example above: I reference OutApp
rather than outlookNamespace
, when calling CreateItemFromTemplate
Maintaining the question as this might save somebody else the search and interpolating the VBA solution into R.
Working solution:
library(RDCOMClient)
OutApp <- COMCreate("Outlook.Application")
outlookNameSpace = OutApp$GetNameSpace("MAPI")
message_path <- "C:\\Users\\foo\\bar.msg"
message <- outlookNameSpace$OpenSharedItem(message_path)
Related Topics
In R Data.Table, How to Pass Variable Parameters to an Expression
Data.Table Join Then Add Columns to Existing Data.Frame Without Re-Copy
No Visible Binding For Global Variable Note in R Cmd Check
Suggestions for Speeding Up Random Forests
Create a Vector of All Days Between Two Dates
Test If an Argument of a Function Is Set or Not in R
Selecting Columns in R Data Frame Based on Those *Not* in a Vector
Display Exact Value of a Variable in R
Ggplot2 Does Not Appear to Work When Inside a Function R
Changing Million/Billion Abbreviations into Actual Numbers? Ie. 5.12M -> 5,120,000
Using R Statistics Add a Group Sum to Each Row
Merge Data.Frames Based on Year and Fill in Missing Values
How to Find Out Which Package Version Is Loaded in R
Advantages of Reactive VS. Observe VS. Observeevent
How to Get the Name of the Calling Function Inside the Called Routine