I want to send mail within SSIS, preferably HTML formatted. What are the options?
Solutions
There are a couple of solutions to mail within SSIS:
- Send Mail Task
- Script Task with SmtpClient Class
- Execute SQL Task with sp_send_dbmail
- Custom Tasks like Send HTML Mail Task or COZYROC
To demonstrate the various solutions, I'm working with these four SSIS string variables. They contain the subject, body, from- and to address. Add these variables to your package and give them a suitable value. You could also use parameters instead if you're using 2012 project deployment.
Add these four variables to your package |
B) Script Task
The Script Task is a little harder to use than the Send Mail Task (if you don't have .Net knowledge), but it doesn't have the same drawbacks as the Send Mail Task. It uses the SmtpClient Class and it has an HTML formatted mail option and a configurable port number.
1) SMTP Connection Manager
This first step is optional. I like to use as much as possible standard connection managers. Right click in the Connection Managers window and add an SMTP Connect manager. Add the SMTP server and change other options if necessary (other options are not used in this example). The alternative is to use an extra SSIS string variable for storing the SMTP Server.
SMTP Connection manager |
2) Add Script Task
Add a Script Task to your Control Flow (or one of the event handlers). Give it a suitable name and add the SSIS variables as readonly variables to the Script Task.
Add all SSIS variables as ReadOnly |
3) The Script
In the Scipt I'm using the variables and the connection manager to fill the properties of the SMTP client. Copy the contents of the Main method to your method and add the extra import/using on top.
// C# Code using System; using System.Data; using Microsoft.SqlServer.Dts.Runtime; using System.Windows.Forms; using System.Net.Mail; // Added namespace ST_df6618207373422d961b80ca8b6a56e2 { [Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute] public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase { public void Main() { // Storing SSIS variables in .Net variables. You could skip this step and call the SSIS variables in the actual mail code // to reduce the number of code lines. Or you could fill these .Net variables with hardcoded values. String SendMailFrom = Dts.Variables["SendMailFrom"].Value.ToString(); String SendMailTo = Dts.Variables["SendMailTo"].Value.ToString(); String SendMailSubject = Dts.Variables["SendMailSubject"].Value.ToString(); String SendMailBody = Dts.Variables["SendMailBody"].Value.ToString(); // Get SMTP Server from SMTP Connection Manager. Alternative is to use extra variables or paramters instead: // String SmtpServer = Dts.Variables["SmtpServer"].Value.ToString(); String SmtpServer = Dts.Connections["My SMTP Connection Manager"].Properties["SmtpServer"].GetValue(Dts.Connections["My SMTP Connection Manager"]).ToString(); // Create an email and change the format to HTML MailMessage myHtmlFormattedMail = new MailMessage(SendMailFrom, SendMailTo, SendMailSubject, SendMailBody); myHtmlFormattedMail.IsBodyHtml = true; // Create a SMTP client to send the email SmtpClient mySmtpClient = new SmtpClient(SmtpServer); mySmtpClient.Port = 2525; // If you want to use a different portnumber instead of the default. Else remove this line. mySmtpClient.Send(myHtmlFormattedMail); // Close Script Task with success Dts.TaskResult = (int)ScriptResults.Success; } #region ScriptResults declaration enum ScriptResults { Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success, Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure }; #endregion } }
or use VB.Net code
' VB.Net Code Imports System Imports System.Data Imports System.Math Imports Microsoft.SqlServer.Dts.Runtime Imports System.Net.Mail ' Added <Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute()> _ <System.CLSCompliantAttribute(False)> _ Partial Public Class ScriptMain Inherits Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase Public Sub Main() ' Storing SSIS variables in .Net variables. You could skip this step and call the SSIS variables in the actual mail code ' to reduce the number of code lines. Or you could fill these .Net variables with hardcoded values. Dim SendMailFrom As String = Dts.Variables("SendMailFrom").Value.ToString() Dim SendMailTo As String = Dts.Variables("SendMailTo").Value.ToString() Dim SendMailSubject As String = Dts.Variables("SendMailSubject").Value.ToString() Dim SendMailBody As String = Dts.Variables("SendMailBody").Value.ToString() ' Get SMTP Server from SMTP Connection Manager. Alternative is to use extra variables or paramters instead: ' Dim SmtpServer as String = Dts.Variables("SmtpServer").Value.ToString(); Dim SmtpServer As String = Dts.Connections("My SMTP Connection Manager").Properties("SmtpServer").GetValue(Dts.Connections("My SMTP Connection Manager")).ToString() ' Create an email and change the format to HTML Dim myHtmlFormattedMail As New MailMessage(SendMailFrom, SendMailTo, SendMailSubject, SendMailBody) myHtmlFormattedMail.IsBodyHtml = True ' Create a SMTP client to send the email Dim mySmtpClient As New SmtpClient(SmtpServer) mySmtpClient.Port = 2525 ' If you want to use a different portnumber instead of the default. Else remove this line. mySmtpClient.Send(myHtmlFormattedMail) ' Close Script Task with success Dts.TaskResult = ScriptResults.Success End Sub #Region "ScriptResults declaration" 'This enum provides a convenient shorthand within the scope of this class for setting the 'result of the script. 'This code was generated automatically. Enum ScriptResults Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure End Enum #End Region End Class
4) The result
Close the Script Task and execute it: An email message with html formatting!
HTML formatted email |
If you're not into .Net, but really like TSQL then check out the next solution: Execute SQL Task with sp_send_dbmail
Hi if we want send message to multiple mails that time how to modify this code can any body help me .and i tried between two mails i used ; symbol but its not working .
ReplyDeleteString SendMailTo = Dts.Variables["SendMailTo"].Value.ToString();
See for example http://stackoverflow.com/questions/3209129/unable-to-send-an-email-to-multiple-addresses-recipients-using-c-sharp
DeleteWould it kill you to mention what version your developing this with. Seriously not everybody is up to 2012 and for those that aren't it might save them time in not bothering with the tutorial and looking for another solution with their earlier version.
ReplyDeleteHi 'Unknown',
DeleteWould it kill you to mention your name when you complain? If you read the instructions carefully you see that you must copy the content of my main method to your main method. Then it will just work fine in SSIS 2008 or even 2005. Hopefully you can now create your own blog to help all those that won’t understand mine.
Joost this article is very helpful! Ignore the haters. Thanks again!
DeleteDear Joost,
DeleteRe managing the above keyboard warrior: 10 out of 10
Also the "how to" was very informative also
Cheers
Tom
Dude... what a D bag... this a good article. Thanks for taking time out of you life to help me.
DeleteCharaka
Thanks Joost
ReplyDeleteThis worked like a charm, and saved me a lot of time and effort.
And for those who really want to know, I am using SQL Server 2008 R2. ;)
Regards,
Bhawesh
Hello,
ReplyDeleteI am working on a project that requires a Month (direct input in the package) to be passed into the Mail Subject line...I am struggling to make this happen as I have some knowledge of VB but I am new to SSIS.
I have used the script option to actually send the mail message (I needed html functionality), and that works perfectly! Now, I just need a variable value (which does already exist) to be passed in, for example "This is a Line", where subject is a replaced variable value.
Can you help?
Thank you! Your post has been extremely helpful!
See this blogpost about using variables in an SSIS Script Task.
DeleteThank you!
ReplyDeleteBut is there a way to pass a dynamic variable into a subject line of a Mail Task?
I am using the vbscript option, so I assume I could do a simple replace...thus far, nothing is working!
The email sends, but for formatting purposes, I need that dynamic variable passed into the subject line.
Thanks,
Bree
No dynamic is not possible. You always have to hardcode the variable name in the script. So either set all necessary variables as readonly variables and come up with an if/case-construction in the .net code where you choose the right variable...
DeleteOr create an expression on a variable that fills it with the right value and use that variable in your Script Task.
Okay, thank you - I am finding that it is not possible as well. That subject line is fairly static as set by SSIS/Script.
ReplyDeleteAs for the dynamic variable I need to include somewhere in the email, I suppose I will opt to try including it in the body of the message.
Thank you so much! I have bookmarked your blog site!
-Bree
It's hard to believe that no one had already submitted a Connect Feature Suggestion for this, so I just did. Please upvote https://connect.microsoft.com/SQLServer/feedback/details/1437047/ssis-send-mail-task-needs-additional-parameters.
ReplyDeleteGreat Article Thank you so much!
ReplyDeleteI m getting error like Error: Exception has been thrown by the target of an invocation.please help me on this
ReplyDeleteIt's a very generic error without any clues, but it's probably a typo in a variable name (or the scope of the variable). Otherwise you need to debug your script task to which line is causing the error.
DeleteWhat about the DeliveryMethod and Credentials ? Have you missed them ?
ReplyDeleteYou can extend this basic script to your own needs. The example uses the credentials of the user running the job. Just search for something like 'smtpClient c#'
Deletethank u very mutch, very helpful tuto, u are hero :-)
ReplyDeleteHi Joost,
ReplyDeleteSorry for late reply, I just came across and issue that my visual studio is installed in client domain , but i want to do an automation which sends mails to my company mail id. there is a server i.p and port for it as well as generic id and password is also provided to me. I tried doing this using send mail task ,but due to some port issue(means Send Mail Task by default it takes port no. 25, but i want to change so i m using the same in script task) Following the above approach i m able to send mail from C# but not able to received into my company mail id.
What went wrong , I am not able to catch it.
If it is possible please do reply !! THANK YOU IN ADVANCE..