An email message is a great way to send a notification when a SAS job completes, or to distribute a result from SAS as an attached report or spreadsheet. The SAS programming language allows you to send email as an output via the FILENAME EMAIL method.
In this article:
The FILENAME EMAIL statement allows you to specify all of the component parts of an email message, including Subject, recipients (To, CC, BCC), From, Importance and more. Here's an example of a small SAS program that produces some data and generates an email message with data-driven values and a small message body.
options emailsys=smtp;
/* Small SAS job to produce some data */
%let origin = Europe;
proc sql;
create table subset as
select * from sashelp.cars
where origin = "&origin.";
%let count=&sqlobs.;
quit;
/* Email message with dynamic content based on data */
filename msg email
to="chuck.sasuser@company.com"
from="replies-disabled@company.com"
subject = "Created: Cars from &origin.";
data _null_;
file msg;
put "%trim(&count.) cars selected, subset from &origin.";
run;
In the SAS log, you'll see the action taken:
NOTE: The file MSG is:
E-Mail Access Device
Message sent
To: "chuck.sasuser@company.com"
Cc:
Bcc:
Subject: Created: Cars from Europe
Attachments:
And the recipient sees something like this in their inbox:
When sending email, SAS is acting as an email client. SAS requires an email service to send the messages, and this is typically accessed via SMTP (Simple Mail Transfer Protocol). In your SAS environment this might already be configured for you, or you might need to specify SMTP settings using SAS options. These options include EMAILSYS, EMAILHOST, EMAILPORT and more.
To check the current value of your email options, run PROC OPTIONS with group=email:
proc options group=email; run;
If the current values are not set by an administrator, you can set them within your program by using an OPTIONS statement. You might need to work with a system administrator to learn the proper values for your environment.
options
emailsys=smtp
emailhost=your.smtpemail.server.com
emailport=25;
This paper (PDF) by SAS' Chuck Hunley contains a helpful guide to configuring your email options.
FILENAME EMAIL supports most of the standard email flags that you can set in full email clients. Flags such as Importance, Read Receipts, Expiration time, and Sensitivity are set with named options, documented with the FILENAME EMAIL statement.
filename mail email
from="watcher@creep.com"
to="victim@school.edu"
importance='high'
readreceipt
ct="text/html"
subject="I know what you did last summer"
sensitivity='private';
data _null_;
file mail;
put '<html><body>';
put '<h2>Uh oh</h2>';
put "<p>...and I'll keep quiet";
put "<br>for a price</p>";
put '</body></html>';
run;
Most email clients support rich content using HTML. By using one of the ODS HTML or HTML-like tagsets, you can create customized formatted messages that include SAS output. Remember that not every email client supports a full range of HTML structure, formatting, and behavior -- so it's wise to keep the HTML simple. However, you can easily use ODS to create the body of your message in HTML, and include tabular output such as from PROC REPORT or PROC PRINT. Use ODS TEXT statements to create additional annotations within the message.
This code example shows how to use ODS templates to adjust the structure of the simple msoffice2k tagset to create an email message that renders well in any client, including Microsoft Outlook.
ods path(prepend) work.template(update);
proc template;
define style styles.myemail;
parent=styles.seaside;
class body /
htmlstyle="border:none";
class systitleandfootercontainer /
htmlstyle="border:none";
class page /
htmlstyle="border:none";
end;run;
FILENAME OUTPUT EMAIL
SUBJECT = "blogs.sas.com: &postCount posts,
&commentCount comments"
FROM = "Chris Hemedinger <chris.blogger@sas.com>"
TO = (&toList)
CT ='text/html';
ods tagsets.msoffice2k(id=email)
file=OUTPUT(title="7-day blog report")
style=myemail;
proc report nowd data=pastweek;
title "&postCount blogs.sas.com posts";
title2 color=red "NOTE: " color=blue "View counts are sourced from Google Analytics";
columns post_date post_author blog_ID post_link ga_views comment_count ;
define post_date / group order=data 'Date posted' style(column)=[just=l];
define post_author / order 'Author' style(column)=[just=l];
...
run;
ods tagsets.msoffice2k(id=email) close;
You can attach one or more files to your email message with the ATTACH= option on the FILENAME EMAIL statement. The file(s) to attach must be located in a folder that the SAS session can access so that they can be added to the message.
filename outbox EMAIL;
data _null_;
FILE outbox
to=("recipient@company.com" )
importance="HIGH"
sensitivity="CONFIDENTIAL"
subject="Monthly sales: Your report for June"
attach=("/home/user/sales/june_sales.xlsx"
content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
file outbox;
put "Attached is the report for June sales.";
put "Thank you,";
put "Sales Data Team";
run;
Email systems rely on file extensions and MIME types to determine the type of the file that's attached. To explicitly set the type, you can specify the MIME type in your program via the CONTENT_TYPE= suboption on the ATTACH option.
This video tutorial shows how to automate a set of emails to multiple recipients, including the attachment of a spreadsheet to each message:
An embedded image is a special type of attachment that appears in the body of the email message. Instead of an attached file, the image data is included in the message body and rendered inline by the email client (such as Microsoft Outlook or Gmail).
The ODS HTML5 destination can include images in the HTML body. When using this for email you should use JPEG or PNG images. (Scalable vector graphics or SVG is supported by HTML, but not by all email clients.)
ods graphics / imagefmt=png height=400 width=400;
filename outbox EMAIL
to="chris.h@epa.gov"
from="go.green@environment.com"
subject="Gas guzzlers"
ct="text/html";
ods html5 (id=mail) file=outbox style=pearlj
options(bitmap_mode="inline") gtitle;
title "CARS data: mpg vs HP";
proc sgplot data=sashelp.cars;
scatter x=mpg_city y=horsepower;
run;
ods html5 (id=mail) close;
If you have a standalone image file you want to include (such as a logo or banner), it's possible to reference this directly by building your own HTML. Code snippet:
filename myemail email
to="Jim@acme.com"
from="Wiley <wcoyote@acme.com>"
sender="Wiley <wcoyote@sas.com>"
attach=('C:\Public\Pictures\Sample Pictures\sasLogo.gif' NAME="sasLogo" INLINED="logo"
'C:\temp\reportToEmail.html' NAME='myreport')
subject="Embedded Image Example"
content_type="text/html";
Use the INLINE= suboption on the ATTACH option to assign a reference name to the image you want to include inline. Assuming that your email is HTML content, use this convention to reference your image:
<img src="cid:myimage"/>
where "myimage" is the reference name you specified in the INLINE option.
The SAS documentation for FILENAME EMAIL includes an example for inlined images. See this article for more information and examples: Using SAS to send a graph in the body of an email.
We'll cover two use cases for sending email to multiple recipients:
It's common to read the email distribution list from an external source, such as Excel or CSV. In this example we have two possible lists: one for daily distribution and one for just Mondays (a wider distribution). We use the PROC SQL SELECT INTO feature to read the addresses into a macro variable, which we can reference in the FILENAME EMAIL statement:
%let cutoff = %sysfunc(today()) - 7;
/* two lists: one for Monday and one for all other days */
%let dist = %sysfunc(ifc(%sysfunc(today(),weekday1.)=2,weekly,daily));
filename dl "/u/userid/reports/distlist_&dist..csv";
data distlist;
infile dl dsd;
length email $ 50;
input email;
run;
/* create space-delimited list like: "email1" "email2" "email3" */
proc sql noprint;
select cat('"',trim(email),'"') into :toList separated by ' ' from distlist;
quit;
FILENAME OUTPUT EMAIL
SUBJECT = "Report for (%TRIM(%QSYSFUNC(putn(&cutoff., NLDATE20.))) - %TRIM(%QSYSFUNC(today(), NLDATE20.)))"
FROM = "Chris Hemedinger <myaddress@sas.com>"
TO = (&toList)
CT ='text/html';
Here's a sample message produced by this process:
You can use SAS macro language to create a reusable macro routine to send a personalized email message. The CALL EXECUTE statement can run that routine for each value in a data set, creating a data-driven process to generate custom emails. This example code segment was adapted from the sample provide by Daniel Rodda in his tutorial video.
%macro sendreports(Email, Make, Model_Count);
filename outbox EMAIL;
data _null_;
FILE outbox
to=("&email" )
importance="HIGH"
sensitivity="CONFIDENTIAL"
subject="NHTSA: &make Recall"
file outbox;
put "Dear &make.,";
put;
put "National Highway Traffic Safety Administration (NHTSA) has identified ";
put "&Model_count of your models as having potentially faulty airbags.";
put "Thank you,";
put "NHTSA Data Team";
run;
%mend sendreports;
/* In this example, car_data contains records for email, make name, and count */
/* Example:
safety@ford.com Ford 36
safety@honda.com Honda 27
...
*/
data _null_;
set car_data;
/* will send one email message per record */
call execute(cats('%sendreports(',Email,',',Make,',',Model_Count,')'));
run;
Read more about data driven processes using SAS macro and CALL EXECUTE: CALL EXECUTE made easy for SAS data-driven programming.
This feels a bit like cheating, but there isn't any magic function in SAS that sends SMS messages. Instead, we're going to rely on a mobile phone service trick. Most phone service providers allow you to send text messages via e-mail by using a special address scheme for the text message recipient. Each carrier is a little different, but you can find the details with a simple internet search: "sms via email".
My current carrier is AT&T, and so to receive a text message as e-mail I would send it to the address my_number@txt.att.net. With the FILENAME EMAIL method, it's easy to send an e-mail using SAS.
options emailhost='mailserver.company.com' emailsys=smtp;
/* NOT my real phone number */
filename msg email to="9198675309@txt.att.net"
FROM = "Cafe Bot <youremail@company.com>"
subject="Breakfast goodie: &Goodie.";
data _null_;
file msg;
put 'Bon appetit!';
run;
Here's an example of the text message from my phone:
Learn more in this blog article: How to send a text message from SAS.
You can use SAS to communicate directly with providers such as Gmail and Outlook.com, but these require additional configuration and the method has security considerations. For example, to use SAS as a client for Gmail you must first enable Less secure apps from your Google account. If you use two-factor authentication (a good practice), then you must also use an "App password" instead of your selected account credentials. Note: protect your Google credentials and/or App password! It's best practice to not code these into your programs, but secure them in a place that only you can access.
options emailhost=
(
"smtp.gmail.com"
/* alternate: port=487 SSL */
port=587 STARTTLS
auth=plain
/* your Gmail address */
id="your_address@gmail.com"
/* optional: encode PW with PROC PWENCODE */
pw="your_password"
)
;
filename myemail EMAIL
to="lucky_recipient@gmail.com"
subject="Read SAS blogs";
data _null_;
file myemail;
put "Dear Friend,";
put "I recommend that you read https://blogs.sas.com ";
put "for lots of SAS news and tips.";
run;
filename myemail clear;
For more details see this article: How to use Gmail to send a message from a SAS program.
Hi Chris, this is great article. Thanks for posting. Is there an option to also add voting buttons to your email? Tina
Hi @mtrobins,
Voting buttons are a Microsoft Outlook feature and not supported natively in SMTP. There isn't a SAS method to trigger this feature in Outlook.
You could create an email body in HTML that features yes and no links, each of which linked to a website to record the "vote"... but that's not a built-in feature of the email function.
I think you meant "style=pearl", not "style=pearj".
In the msoffice2k example, I had to reverse the order of the filename and output statements to avoid getting an error.
A problem I haven't solved: If I put in two pieces of output - two sgplots, or an sgplot followed by a proc report, for example - I get a horizontal line line between them. The number of people who want that must be vanishingly small, so there's probably a simple fix that I'm overlooking. Any ideas?
Thanks @JackHamilton - I fixed the msoffice2k example. PearlJ is a real style -- example here.
PearlJ may be a real style, but Pearj does not appear to be. It's a typo.
ods html5 (id=mail) file=outbox style=pearj
options(bitmap_mode="inline") gtitle;
70 ods html5 (id=mail) file=outbox style=pearj
71 options(bitmap_mode="inline") gtitle;
WARNING: Style PEARJ not found; HTMLBlue style will be used instead.
NOTE: Writing HTML5(MAIL) Body file: OUTBOX
Whoops! Thanks @JackHamilton -- fixed it.
Hi Chris! Love this article.
If I am attaching a graph as a part of the email, using the image:
ODS graphics/imagemap imagefmt=png;
proc sgplot data=reassign;
title 'Gexa Expirations';
vbar yy_mm / response=count group=Top_Category
dataskin=crisp
grouporder=ascending
xaxis display=(nolabel);
yaxis grid label='Expirations';
run;
title;
Is there a way to attached TIP's the display the graphical information within the email?
When I use the option:
tip=(Top_Category count);
The tips will only display in SAS, and not in the email.
Hi @Keegan - not all email clients support the "hover tips" that you're building in your content, so I'd say the approach is limiting as part of an email. If the goal is to provide actual data values along with the image, I'd suggest including a table in the email with perhaps some of the values you want to highlight. Or use SGPLOT and axis table to add values into the chart.
Sending email with images is so much easier than it used to be!
Thank you SO MUCH!!!
How to limit the size of attached excel say "50mb" ?
@Shwethav You must do that while creating the Excel file. You cannot reduce the file size while attaching it to an email.
Maximum sizes of files are usually controlled by the mail handling agents, and then the whole mail (or the whole attachment) is rejected there.
Hey Chris,
Just an FYI. Running SAS 9.4M7 EBI here. I had to modify the attachment line to get the excel readable. I needed to specify the content type in the attachment.
Loved the "%sysfunc(getoption(WORK))/roster.xlsx" and %sysfunc(pathname(out)) code. This will allow my customers to keep their attachments in temp space!
Thanks
filename out "%sysfunc(getoption(WORK))/roster.xlsx";
proc export data=sashelp.class outfile=out dbms=xlsx replace;
run;
proc sql noprint;
select count(name)
into: size TRIMMED from sashelp.class;
quit;
filename outbox EMAIL
to="email@address"
from="email@address"
subject="Your new class list: &size members"
attach="%sysfunc(pathname(out))" /*Did NOT work*/
attach=("%sysfunc(pathname(out))" content_type="application/xlsx") /* Worked !!!*/
;
data _null_;
file outbox;
put "Here's your roster!";
run;
Hey Chris is it possible to attach a file from the SAS Studio explorer folders if so how do I refer to that in the attach option? Tried this:
filename myemail EMAIL;
FILENAME REFFILE FILESRVC FOLDERPATH='/Users/jwalker' FILENAME='BSA_FEDWIRE.csv';
data _null_;
FILE myemail
to=("jwalker@coastalbank.com")
subject="testing with attachment"
attach=(REFFILE);
file myemail;
put "Attached is sample";
put "Thank you,";
put "it worked";
run;
ERROR 24-2: Invalid value for the ATTACH option. Also just tried the path, but I think its looking for a path on the OS:
data _null_;
FILE myemail
to=("jwalker@coastalbank.com")
subject="testing with attachment"
attach=('/Users/jwalker/BSA_FEDWIRE.csv');
file myemail;
put "Attached is sample";
put "Thank you,";
put "it worked";
run;
Hi Chris,
I was able to generate nice html report via "How to format your email with ODS in SAS". How can I add addition descriptive text to it?
If I use data _null_; seperate e-Mail are generated.
Chris - This is super helpful!
Anyone having issues with hyphenated emails? When we send to a hyphenated email it bounces. As far as I can tell our macro creating the to email list is parsing the hyphens correctly, but when the emails are sent it appears that spaces are addded. For example, when sending to AAAA.BBBB-CCCC@somewhere.com I receive a Mailer Daemon error and the error indicates that the email was sending "AAAA.BBBB - CCCC@ somewhere.com". Notice the additional spaces added before and after the hyphen and after the @ symbol.
Non hyphenated emails send fine, it's just the hyphenated emails that are bouncing on us.
Cheers,
Jonathon
@jstewar9 - This type of problem is best progressed with SAS Tech Support by opening a track.
@jstewar9 I don't think there's anything inherent in FILENAME EMAIL that would cause this. Are you sure the email address isn't being altered as part of the data prep? Or is it a concatenation of elements that doesn't have whitespace trimmed from the original pieces?
I followed your example, but i found in OutLook, the email body will be in a attachment named "ATT00001.bin" automaticly. I am not sure whether it is due to some IT policy or firewall issue from mail server side.
@NovGetRight Using SMTP or MAPI? If MAPI, there are a number of security policies that could interfere with email being sent in the way that you want.
@ChrisHemedinger I use SMTP.
Hi @ChrisHemedinger, Thanks a stack for this!! You're a Rockstar!! I am using the below code to send an email (copy & pasted from a SAS community :D), only if the data table is populated. I want to receive a notification if the data table is empty tho, but it does not work. Please help!!
%macro email;
data _null_;
call symputx('nobs',nobs);
stop;
set Exceptions nobs=nobs;
run;
%if (&nobs.) %then
%do;
filename outfile email from= "Department@company.com" to="User@company.com" subject="EXCEPTIONS as at &date." attach=("/SAS/Department/Process/Exceptions.xlsx" content_type="application/xlsx");
data _null_;
file outfile;
PUT 'Email body';
run;
%end;
%else
%do;
filename outfile email from= "Department@company.com" to="MyEmail@company.com" subject="EXCEPTIONS data as at &date. is empty";
%end;
%MEND EMAIL;
%EMAIL;
@Mar1ene in your %ELSE %DO block, you need to add the DATA _NULL_ step to send the email, like you have in the first %DO block.:
data _null_;
file outfile;
PUT 'No exceptions';
run;
That assumes the work.exceptions dataset exists when there are no exceptions and has 0 obs. If the work.exceptions dataset does not exist when there are no exceptions, then the code should be throwing an error. In that case, you could change from you %IF statement to check for the existence of work.exceptions, instead of checking the number of obs in work.exceptions. HTH.
Thank you @Quentin , you are an absolute legend!!
Thank you, @ChrisHemedinger, a lot for this article!
Is there a way to make emails sent by SAS to appear in the sent items folder of your email program. (I'm currently using Outlook 2016 on Windows 10.)
@Multipla99 Not by using SMTP, no. If you used MAPI (which is hard to get working reliably, as I mentioned), then Outlook would be the sender and it should appear in your Sent folders. But that is difficult to automate, works only on your local laptop, and isn't viable when you have a remote SAS session that is driving the email.
I recommend that you include yourself as a CC or BCC on the email so you know you'll have a copy.
how to connect?!
ERROR: Email: The connection was refused.
NOTE: The SAS System stopped processing this step because of errors.
NOTE: DATA statement used (Total process time):
real time 2.33 seconds
cpu time 0.15 seconds
@hellohere post this as a question in Programming; post the complete log.
Get in contact with your mail admins for how to connect to the SMTP server.
Hello,
I am trying to send e-mails with SAS using the cloud-based service SendGrid to no avail.
I can successfully send e-mails without SAS by following these steps from SendGrid documentation :
https://docs.sendgrid.com/for-developers/sending-email/getting-started-smtp
For SAS, I tried using these two different options, but they both give me errors.
options emailhost= ( "smtp.sendgrid.net" port=25 auth=plain id="apikey" pw="my_plain_api_key" ) ;
options emailhost= ( "smtp.sendgrid.net" port=25 auth=login id="YXBpa2V5" pw="my_base64_api_key" ) ;
Any idea on what I am doing wrong? Any help would be appreciated. Thank you in advance 🙂
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning and boost your career prospects.