6

I have an ASP.NET MVC application that has to send an email to a list of recipients with an attachment detailing a specific "Project". I get the details for this from a report by making use of SQL Server Reporting Services (SSRS).

I've never really used SSRS before, but I received some code from a colleague where he used it. What he does with the report is he downloads it in the browser to the client's machine. So, if I don't do that I sit with a byte array containing the report data.

Is there a way I can send this as an attachment without first physically writing the file to the filesystem of the server? The report will either be in excel format or a pdf.

Edit: I am using SmtpClient to send the email's.

Carel
  • 2,063
  • 8
  • 39
  • 65
  • You have ASP.NET MVC (version?) web server with file upload and you want to email (SMTP?) your uploaded file to a list of email addresses? – Jossef Harush Kadouri Apr 22 '14 at 08:09
  • @JossefHarush: No, I do not have a file upload control. The file I want to attach comes from an SSRS report that is retrieved from a SQL reporting server. I can configure in the code to retrieve the report in various formats, but I'll use either xsl or pdf. – Carel Apr 22 '14 at 08:32
  • Who saves the file to the filesystem? You or the 'blackbox' solution you got from your colleague? – Jossef Harush Kadouri Apr 22 '14 at 08:41
  • @JossefHarush: That sounds suspiciously like an unfriendly remark. And who says I save the file to the filesystem? I figured out I can create a stream from the `byte[]` and create a `Net.Mail.Attachment` using the stream and the appropriate content type. I will post this as my solution as soon as I am able. – Carel Apr 22 '14 at 08:53

2 Answers2

8

Get the file data in a byte[]

byte[] binaryFile = //  get your file data from the SSRS ...
string filename = "SSRS.pdf";

Prepare a list or array of the destination addresses:

string[] addresses = // get addresses somehow (db/hardcoded/config/...)

sending smtp message through SmtpClient:

MailMessage mailMessage= new MailMessage();

mailMessage.From = new MailAddress("sender email address goes here");

// Loop all your clients addresses
foreach (string address in addresses)
{
    mailMessage.To.Add(address);    
}

mailMessage.Subject = "your message subject goes here";
mailMessage.Body = "your message body goes here";

MemoryStream memoryStream = new MemoryStream(binaryFile);
mailMessage.Attachments.Add( new Attachment( memoryStream, filename , MediaTypeNames.Application.Pdf ));

SmtpClient smtpClient = new SmtpClient();
smtpClient.Send(mailMessage);
Jossef Harush Kadouri
  • 32,361
  • 10
  • 130
  • 129
4

to do this you would need to leverage off the SSRS ReportManager API as follows.

  1. First read in the report from the Web Service with SSRS
  2. Read the file into memory rather than saving to the server or client
  3. Send the MemoryStream object straight to the email server.

Reporting services: Get the PDF of a generated report How to send an email with attachments using SmtpClient.SendAsync?

string strReportUser = "RSUserName";
string strReportUserPW = "MySecretPassword";
string strReportUserDomain = "DomainName";

string sTargetURL = "http://SqlServer/ReportServer?" +
   "/MyReportFolder/Report1&rs:Command=Render&rs:format=PDF&ReportParam=" +
   ParamValue;

HttpWebRequest req =
      (HttpWebRequest)WebRequest.Create( sTargetURL );
req.PreAuthenticate = true;
req.Credentials = new System.Net.NetworkCredential(
    strReportUser,
    strReportUserPW,
    strReportUserDomain );

HttpWebResponse HttpWResp = (HttpWebResponse)req.GetResponse();

Stream fStream = HttpWResp.GetResponseStream();

HttpWResp.Close();



//Now turn around and send this as the response..
ReadFullyAndSend( fStream );

ReadFullyAnd send method. NB: the SendAsync call so your not waiting for the server to send the email completely before you are brining the user back out of the land of nod.

public static void ReadFullyAndSend( Stream input )
{
   using ( MemoryStream ms = new MemoryStream() )
   {
      input.CopyTo( ms );

        MailMessage message = new MailMessage("from@foo.com", "too@foo.com");
            Attachment attachment = new Attachment(ms, "my attachment",, "application/vnd.ms-excel");
            message.Attachments.Add(attachment);
            message.Body = "This is an async test.";

            SmtpClient smtp = new SmtpClient("localhost");
            smtp.Credentials = new NetworkCredential("foo", "bar");
            smtp.SendAsync(message, null);
   }
}  
Community
  • 1
  • 1
Robbie Tapping
  • 2,516
  • 1
  • 17
  • 18
  • Thanks. This is very similar to the solution I found. I did note when working on it that I had to set the content type of the attachement, eg if its an xls: `mail.Attachments.Add(new Attachment(stream, "Research - " + projectId + ".xls" , "application/vnd.ms-excel"));` – Carel Apr 22 '14 at 08:59
  • Ah yes the mime-type, ill add it in above so that incase anyone sees and uses the code above it is solid. – Robbie Tapping Apr 22 '14 at 09:10