{"id":63,"date":"2019-09-24T15:26:57","date_gmt":"2019-09-24T18:26:57","guid":{"rendered":"https:\/\/pedrotornich.com\/a\/?p=63"},"modified":"2019-09-25T13:36:28","modified_gmt":"2019-09-25T16:36:28","slug":"additional-attachments-when-sending-reports-through-email","status":"publish","type":"post","link":"https:\/\/pedrotornich.com\/a\/2019\/09\/24\/additional-attachments-when-sending-reports-through-email\/","title":{"rendered":"Additional attachments when sending reports through email"},"content":{"rendered":"\n<p>Hi folks,<\/p>\n\n\n\n<p>I&#8217;ve been posed with the following task: When the user posts a purchase invoice we would need to get other files attached to the purchase order and send them as attachments alongside with the invoice report itself, in a single email.<\/p>\n\n\n\n<p>After digging the print management framework I found the class that actually sends the email.<\/p>\n\n\n\n<p>The method <strong>toEmail()<\/strong> from the <strong>SrsReportRunPrinter<\/strong> class&nbsp;sends the email, but inside this method, right before sending the email, it calls the&nbsp; <strong>onToEmail()<\/strong> method from the <strong>SRSPrintDestinationSettingsDelegates<\/strong> class, which in return will call the <strong>toEmail() delegate<\/strong> and when this delegate returns false it terminates the sending process without errors.<\/p>\n\n\n\n<p>Check the line 11 of the following method:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp line-numbers\">private void toEmail()\n{\n    guid printId = newGuid();\n    SSRSReportRuntimeEventSource::EventWriteRenderReportToEmailDetailTaskStart(\n        \"Printing report to email started.\",\n         reportContract.parmReportExecutionInfo().parmReportRunId(),\n         printId);\n\n    try\n    {\n        if(!delegatesHelper.onToEmail(this, reportContract, reportParamArray))\n        {\n            SSRSReportRuntimeEventSource::EventWriteRenderReportToEmailDetailTaskStop(\n            \"Printing report to email ended.\",\n             reportContract.parmReportExecutionInfo().parmReportRunId(),\n             printId);\n            return;\n        }\n\n        if(!printSettings)\n        {\n            throw error(strfmt(\"@SYS318601\", 'printSettings'));\n        }\n\n        SrsReportEMailDataContract emailContract = printSettings.parmEMailContract();\n\n        if(emailContract)\n        {\n            SRSReportFileFormat fileFormat = emailContract.parmAttachmentFileFormat();\n            SRSImageFileFormat imageFormat = emailContract.parmAttachmentImageFileFormat();\n            str attachmentFileName;\n            System.Byte[] reportBytes;\n\n            attachmentFileName = this.getAttachmentName(fileFormat, imageFormat);\n\n            reportBytes = this.renderReportToFile(attachmentFileName, fileFormat);\n\n            if (!delegatesHelper.onToSendEmail(reportBytes, this, reportContract, reportParamArray))\n            {\n                return;\n            }\n\n            if (reportBytes &amp;&amp; reportBytes.Length > 0)\n            {\n                if (this.parmReportRunMailer().emailReportWithRetry(emailContract, reportBytes, attachmentFileName))\n                {\n                    \/\/ The report has been successfully sent as attachment to email.\n                    str message = delegatesHelper.onToEmailSucceed(this, reportContract);\n                    if(message == '')\n                    {\n                        message = \"@SYS344685\";\n                    }\n                    info(message);\n                }\n                else\n                {\n                    str message  = delegatesHelper.onToEmailFailed(this, reportContract);\n                    if(message)\n                    {\n                        info(message);\n                    }\n                }\n            }\n        }\n    }\n    finally\n    {\n        SSRSReportRuntimeEventSource::EventWriteRenderReportToEmailDetailTaskStop(\n        \"Printing report to email ended.\",\n         reportContract.parmReportExecutionInfo().parmReportRunId(),\n         printId);\n    }\n}<\/code><\/pre>\n\n\n\n<p>So, to solve the issue we can subscribe to this delegate and write our own logic to send the email. This way we would be able to add all additional attachments before sending it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp line-numbers\">[SubscribesTo(classStr(SRSPrintDestinationSettingsDelegates), delegateStr(SRSPrintDestinationSettingsDelegates, toEmail))]\npublic static void SRSPrintDestinationSettingsDelegates_toEmail(SrsReportRunPrinter printer, SrsReportDataContract dataContract, Microsoft.Dynamics.AX.Framework.Reporting.Shared.ReportingService.ParameterValue[] paramArray, EventHandlerResult result)\n{\n    \/\/ Add a new parameter in SystemParameters to enable\/disable the multiple attachments feature\n    if(SystemParameters::find().EnablePrintMgmtMultipleAttachments)\n    {\n        \/\/ Call a static method that will perform the send email logic\n        MyMailerClass::sendEmail(...)\n       \n        \/\/ Set result to false\n        result.result(false);\n    }\n}<\/code><\/pre>\n\n\n\n<p>The custom method that will add the attachments and send the email could be based on&nbsp;the method&nbsp;<strong>emailReport()<\/strong> from the <strong>SrsReportRunMailer<\/strong> class, as you can see in the following piece of code, this is the out-of-the-box method to add attachments and send emails:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp line-numbers\">public boolean emailReport(SrsReportEMailDataContract emailContract, System.Byte[] reportBytes, str fileName)\n{\n    SRSReportFileFormat fileFormat;\n    boolean result = false;\n\n    \/\/ Check args and validate contract\n    if(!emailContract)\n    {\n        throw error(strfmt(\"@SYS318601\", 'emailContract'));\n    }\n\n    if(reportBytes.Length == 0)\n    {\n        throw error(strfmt(\"@SYS318601\", 'reportBytes'));\n    }\n\n    if(!fileName)\n    {\n        throw error(strfmt(\"@SYS318601\", 'fileName'));\n    }\n\n    emailContract.validate();\n\n    \/\/ Using mailer to send out report non interactively.\n    if(mailer == null)\n    {\n        this.initMailer();\n    }\n\n    if (mailer)\n    {\n        \/\/ Construct mailer message builder and pass all the values from the contract.\n        var messageBuilder = new SysMailerMessageBuilder();\n        messageBuilder.setFrom(fromAddress)\n                      .addTo(emailContract.parmTo())\n                      .addCc(emailContract.parmCc())\n                      .setSubject(emailContract.parmSubject())\n                      .setBody(emailContract.parmBody())\n                      .addAttachment(new System.IO.MemoryStream(reportBytes), fileName);\n        result = mailer.sendNonInteractive(messageBuilder.getMessage());\n    }\n\n    return result;\n}<\/code><\/pre>\n\n\n\n<p>To leverage some of the out-of-the-box code, the new mailer class should extend the&nbsp;<strong>SrsReportRunMailer<\/strong>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hi folks, I&#8217;ve been posed with the following task: When the user posts a purchase invoice we would need to get other files attached to the purchase order and send them as attachments alongside with the invoice report itself, in a single email. After digging the print management framework I [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,6],"tags":[],"class_list":["post-63","post","type-post","status-publish","format-standard","hentry","category-d365fo","category-ssrs"],"_links":{"self":[{"href":"https:\/\/pedrotornich.com\/a\/wp-json\/wp\/v2\/posts\/63"}],"collection":[{"href":"https:\/\/pedrotornich.com\/a\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pedrotornich.com\/a\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pedrotornich.com\/a\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pedrotornich.com\/a\/wp-json\/wp\/v2\/comments?post=63"}],"version-history":[{"count":5,"href":"https:\/\/pedrotornich.com\/a\/wp-json\/wp\/v2\/posts\/63\/revisions"}],"predecessor-version":[{"id":103,"href":"https:\/\/pedrotornich.com\/a\/wp-json\/wp\/v2\/posts\/63\/revisions\/103"}],"wp:attachment":[{"href":"https:\/\/pedrotornich.com\/a\/wp-json\/wp\/v2\/media?parent=63"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pedrotornich.com\/a\/wp-json\/wp\/v2\/categories?post=63"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pedrotornich.com\/a\/wp-json\/wp\/v2\/tags?post=63"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}