How to send emails with delayed delivery in Outlook from R? - r

Using the RDCOMClient package in R, I am sending a series of automated emails from R. The emails need to be sent at a specific date and time, but I cannot figure out what elements in the outMail object to manipulate to send emails with delayed delivery.
Here's a simple example of what I am doing:
library(data.table)
library(RDCOMClient)
# table of emails, names and send times (stt)
test_emails = data.table( First.Name = c("Joe", "Brit", "Anton"),
email = c("Joe#fakeemail.com",
"Brit#fakeemail.com",
"Anton#fakeemail.com" ),
stt = structure(c(1602270000, 1603270000, 1602470000),
class = c("POSIXct", "POSIXt"), tzone = ""))
# access Outook
OutApp <- COMCreate("Outlook.Application")
# loop over table of names/emails
for(i in 1:test_emails[,.N]){
#standard setup:
outMail = OutApp$CreateItem(0)
outMail$GetInspector()
signature = outMail[["HTMLBody"]]
outMail[["To"]] = test_emails[i, email]
outMail[["subject"]] = "Subject line"
# example body that prints the time and date of when the email is sent
outMail[["HTMLBody"]] =
paste0("<p>Hi ", test_emails[i, First.Name], ",</p>",
"<p>As discussed please find attached the detailed test instructions (PDF) and data set (CSV file)",
"You received this email at ",
gsub('^0', '', format(econ_test[i, stt], '%I:%M %p')), ' on ',
format(econ_test[i, stt], '%A, %B %d'), "</p>",
'<p>', signature, '</p>')
# sends right now. How to delay this?
outMail$Send()
}
I've tried looking through the MailModule object list here, but I can't find anything to use - and I'm not sure how to inspect the outMail object created above (e.g., str() doesn't work on this kind of object).
Thanks.
*** Exact Solution Based on Accepted Answer ***
# Convert the POSIXct integers to MS's time units
gmt_diff <- 4 # EDT
defer_time <- as.numeric( as.Date( test_emails[i, stt]) ) + # convert to R's date values
(as.numeric(test_emails[i, stt]) - gmt_diff*3600) %% 86400/ 86400 - # convert the POSIXct time to fraction of a day
as.numeric(as.Date("1899-12-30")) # adjust for differences in origin
# Update the DeferredDeliveryTime MailItem
outMail[['DeferredDeliveryTime']] = defer_time

Set the MailItem.DeferredDeliveryTime property - https://learn.microsoft.com/en-us/office/vba/api/outlook.mailitem.deferreddeliverytime
You don't need the MailModule object. Take a look at the live Outlook objects with OutlookSpy (I am its author) - click the Item button on the OutlookSpy ribbon.

since afaik Outlook needs to be running (ie online and connected) for you to achieve delayed delivery so therefore your computer also being powered up and running - why not time your R script accordingly with eg taskscheduleR

Related

Wait for rgbif download to complete before proceeding

I am developing a small application in R Shiny. Part of the application will need to query GBIF to download species occurrence data. This is possible using rgbif. The function rgbif::occ_download() will download the data and rgbif::occ_download_meta() will check whether GBIF has fulfilled your request. For example:
geometry <- "POLYGON((30.1 10.1,40 40,20 40,10 20,30.1 10.1))"
res <- occ_download(paste0("geometry within ", geometry), type = "within", format = "SPECIES_LIST")
occ_download_meta(res)
<<gbif download metadata>>
Status: RUNNING
Format: SPECIES_LIST
Download key: 0004089-190415153152247
Created: 2019-04-25T09:18:20.952+0000
Modified: 2019-04-25T09:18:21.045+0000
Download link: http://api.gbif.org/v1/occurrence/download/request/0004089-190415153152247.zip
Total records: 0
So far, so good. However, the following function rgbif::occ_download_get() can't download the data for downstream analysis until occ_download_meta(res) has completed (when Status = SUCCEEDED).
How can I make the session wait until the download from GBIF has been completed? I cannot hard code a wait time into the script as different sized extents will take GBIF longer or shorter amounts of time to process. Also, the number of other active users querying the service could also alter wait times. I therefore need some sort of flag where Status == Succeeded before proceeding.
I have copied some skeleton code with comments below.
library(rgbif)
geometry <- "POLYGON((30.1 10.1,40 40,20 40,10 20,30.1 10.1))" # Define boundary
res <- occ_download(paste0("geometry within ", geometry), type = "within", format = "SPECIES_LIST")
# WAIT HERE UNTIL Status == SUCCEEDED
occ_download_meta(res)
x <- occ_download_get(res, overwrite = TRUE) # Download data
data<-occ_download_import(x) # Import into R
rgbif maintainer here. You could do something like we have within the occ_download_queue() function:
res <- occ_download(paste0("geometry within ", geometry), type = "within", format = "SPECIES_LIST")
still_running <- TRUE
status_ping <- 3
while (still_running) {
meta <- occ_download_meta(res)
status <- meta$status
still_running <- status %in% c("succeeded", "killed")
Sys.sleep(status_ping) # sleep between pings
}
you probably want to check for succeeded and killed, and do something different if killed

Stop Rfacebook for loop outputting while still running code

The point in the code is to gather posts from a Facebook page and store them in my_page however i am unfamiliar with the code as it is for a Uni project. The problem i have is that it has to be used in a .rpres format created using Rstudio and as such i don't want the output but still need to run the code.
This is the output i don't want to be displayed:
```{r, echo = FALSE}
#install.packages("Rfacebook")
include(Rfacebook)
token <- "Facebook dev auth token goes here"
page_name <- "BuzzFeed"
my_page <- getPage(page_name, token, n = 2,reactions = TRUE,api = "v2.10")
number_required <- 50
dates <- seq(as.Date("2017/07/14"), Sys.Date(), by = "day")
#
n <- length(dates) - 1
df_daily <- list()
for (i in 1:n){
cat(as.character(dates[i]), " ")
try(df_daily[[i]] <- getPage(page_name, token,
n = number_required,reactions = TRUE,api = "v2.10",
since = dates[i],
until = dates[i+1]))
cat("\n")
}
```
Your problem is simply that Rfacebook::getPage prints to the console when it runs. That's because it calls cat(), which is the same thing as print(). Fortunately the package provides a switch to turn that off - all you need to do is add the verbose = FALSE argument to your call and it will stop printing:
getPage(...)
getPage(..., verbose = FALSE)
It's pretty bad practice for a package to call cat or print - they should use message and warning instead - so I have raised an issue with the package maintainer to ask for this to be changed, which you can watch here if you like:
https://github.com/pablobarbera/Rfacebook/issues/145

"download.file" Incomplete and inconsistent downloads

Am trying to understand why I am having inconsistent results downloading CSV files from a website archive. Don't know if the problem is at my end, the other side or just failed communications in between. Any suggestions are welcomed.
Using a R script to automate the downloading of CSV files by month and year from the HYCOM archives for analysis. The script generated the following URL trying URL 'http://ncss.hycom.org/thredds/ncss/GLBu0.08/reanalysis/3hrly?var=salinity&var=water_temp&var=water_u&var=water_v&latitude=13.875&longitude=-72.25&time_start=2012-05-01T00:00:00Z&time_end=2012-05-31T21:00:00Z&vertCoord=&accept=csv'
Running download.file successfully obtains the file about half the time, otherwise fails. Any suggestions are welcomed. The images below shows the failed run. Successful run is below.
Successful Log
#download one month of data
MM = '05'
LastDay = ndays(paste(year,MM,'01',sep="-"))
H1 = paste( as shown in image)
H2 = '-01T00:00:00Z&time_end='
#H3 = 'T21:00:00Z&timeStride=1&vertCoord=&accept=csv'
H3 = 'T21:00:00Z&vertCoord=&accept=csv'
HtmlLink <- paste(H1,year,"-",MM,H2,year,"-",MM,"-",LastDay,H3,sep="")
dest = paste("../data/",year,MM,".csv",sep="")
download.file(url =HtmlLink ,destfile=dest,cacheOK=FALSE, method="auto")
trying URL 'as shown in image'
Content type 'text/plain;charset=UTF-8' length unknown
..................................................
................downloaded 666 KB
user system elapsed
28.278 6.605 5201.421
LOG OF FAILED RUN
You can/should turn the following into a function accepting parameters and replace the hardcoded values with said params (I used httr:::parse_query() to make the list):
library(httr)
URL <- "http://ncss.hycom.org/thredds/ncss/GLBu0.08/reanalysis/3hrly"
params <- list(var = "salinity",
var = "water_temp",
var = "water_u",
var = "water_v",
latitude = "13.875",
longitude = "-72.25",
time_start = "2012-05-01T00:00:00Z",
time_end = "2012-05-31T21:00:00Z",
vertCoord = "",
accept = "csv")
dest_file <- "filename"
res <- GET(url=URL,
query=params,
timeout(360),
write_disk(dest_file, overwrite=TRUE),
verbose())
warn_for_status(res)
You can (eventually) remove the verbose() from that GET call, but it's helpful during debugging.
The main issue is that this server is s l o w and times out before the transfer is complete. Even the value of 360 might not be enough (you'll need to experiment).
Many thanks to all for the help. The suggestion by hrbrmstr appears to be an elegant answer and I look forwards to testing it. However, I was unable to install a working copy using the program manager. Installation from a local download also failed since R complained that the OS X version that I downloaded from CRAN was a windows version, not OS X. Yes, I repeated the download several times to make sure I had the right package.
As suggested by Cyrus Mohammadian, I tried the procedures in the curl library.
Running the same URL, download.file transfers failed about 50% of the time. Using curl reduced the transfer times from 2000 seconds to 1000 seconds with no failures in 12 tries.
## calculate number of days in month
ndays <- function(d) {
last_days <- 28:31
rev(last_days[which(!is.na(
as.Date( paste( substr(d, 1, 8),
last_days, sep = ''),
'%Y-%m-%d')))])[1] }
nlat = 13.875
elon = -72.25
#download one month of data
year = 2008
MM = '01'
LastDay = ndays(paste(year,MM,'01',sep="-"))
H1 = paste('http://ncss.hycom.org/thredds/ncss/GLBu0.08/reanalysis/3hrly?
var=salinity&var=water_temp&var=water_u&var=water_v&latitude=',
nlat,'&longitude=', elon,'&time_start=',sep="")
H2 = '-01T00:00:00Z&time_end='
H3 = 'T21:00:00Z&timeStride=1&vertCoord=&accept=csv'
HtmlLink <- paste(H1,year,"-",MM,H2,year,"-",MM,"-",LastDay,H3,sep="")
dest = paste("../data/",year,MM,".csv",sep="")
curl_download(url =HtmlLink ,destfile=dest,quiet=FALSE, mode="wb")

Using R to make Amazon MWS API calls

I'm using R to make a call to the Amazon MWS API and get the following error:
The request signature we calculated does not match the signature you
provided. Check your AWS Secret Access Key and signing method. Consult
the service documentation for details.
This post helped me a lot with the Product Advertising API. However, I cannot seem to make it work on the MWS side.
Here is my code:
library(digest)
library(RCurl)
base.html.string <- "https://mws.amazonservices.com/Products/2011-10-01?"
SellerID <- 'A2UZXXXXXXXXXX'
MWSAuthToken <- 'ATVPXXXXXXXXX'
MarketplaceID <- 'ATVPXXXXXXXXX'
AWSAccessKeyId <- 'AKIAXXXXXXXXXXXXXXXX'
AWSsecretkey <- 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
ActionType <- 'GetMyPriceForASIN'
version.request = '2011-10-01'
ASINList.ASIN.1 <- 'B00XXXXXXX'
pb.txt <- Sys.time()
pb.date <- as.POSIXct(pb.txt, tz = Sys.timezone)
Timestamp = strtrim(format(pb.date, tz = "GMT", usetz = FALSE, "%Y-%m-%dT%H:%M:%SZ"), 24)
str = paste('POST\nmws.amazonservices.com\n/Products/2011-10-01\n',
'ASINList.ASIN.1=', ASINList.ASIN.1,
'&AWSAccessKeyId=', AWSAccessKeyId,
'&Action=', ActionType,
'&MWSAuthToken=', MWSAuthToken,
'&MarketplaceId=', MarketplaceID,
'&SellerId=', SellerID,
'&SignatureMethod=HmacSHA256',
'&SignatureVersion=2',
'&Timestamp=', gsub('%2E','.',gsub('%2D', '-', curlEscape(Timestamp))),
'&Version=', version.request,
sep = '')
## signature test
Signature = curlEscape(base64(hmac(enc2utf8(AWSsecretkey), enc2utf8(str), algo = 'sha256', serialize = FALSE, raw = TRUE)))
AmazonURL <- paste(base.html.string,
'ASINList.ASIN.1=', ASINList.ASIN.1,
'&AWSAccessKeyId=', AWSAccessKeyId,
'&Action=', ActionType,
'&MWSAuthToken=', MWSAuthToken,
'&MarketplaceId=', MarketplaceID,
'&SellerId=', SellerID,
'&SignatureMethod=HmacSHA256',
'&SignatureVersion=2',
'&Timestamp=', Timestamp,
'&Version=', version.request,
'&Signature=', Signature,
sep = '')
AmazonResult <- getURL(AmazonURL)
I'm using the Amazon MWS Scratchpad and made sure my string to sign matches.
My secret key does contain +'s, but I thought encoding would fix that.
Any help would be appreciated!
I figured out my problem after reading this post. I took Amazon's examples literally and used a POST instead of GET. I also had tweaked unnecessarily with my time stamp calculation, which I fixed as well. Hope this helps someone down the road.

Handling internet connection R

I`m trying to download several stocks from google, but every time the connection stops, R stops the loop. How can I handle this problem?
stocks <- c(
'MSFT',
'GOOG',
...
)
for (symbol in stocks)
{
stock_price <- getSymbols(symbol,src='google', from=startDate,to=endDate,auto.assign = FALSE)
prices[,j] <- stock_price[,1]
j <- j + 1
}
From the R manual "quantmod.pdf:
If auto.assign=FALSE or env=NULL (as of 0.4-0) the data will be returnedfrom the call, and will require the user to assign the results himself.Note that only one symbol at a time may be requested when auto assignment is disabled.
You are trying to request more than one ticket symbol at a time with the auto.assign parameter set to false and this is not allowed. However, you should be able to obtain all your symbols at once by adapting the following code:
data <- new.env()
getSymbols.extra(stocks, src = 'google', from = startDate, to = endDate, env = data, auto.assign = T)
plot(data$MSFT)
Pay careful attention to the R manual for getSymbols
"Data is fetched through one of the available getSymbols methods and saved in the env specified - the .GloblEnv by default.

Resources