web
You’re offline. This is a read only version of the page.
close
Skip to main content

Announcements

No record found.

News and Announcements icon
Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Suggested Answer

How to email customer statement by code x++

(0) ShareShare
ReportReport
Posted on by 577

I can send email with customer statement pdf with no customer statement content. However, the content does exist by manually with the same parameters. The code is shown as below.

class AutoSendEmailInvoiceStatement extends RunBaseBatch
{
    public void run()
    {

        SysMailerMessageBuilder         mailer = new SysMailerMessageBuilder();
        SysMailerSMTP                   smtp = new SysMailerSMTP();
        str                             subject, contents, cc;
        SysEmailParameters              SysEmailParameters = SysEmailParameters::find();
        CustTable                       custTable = CustTable::find("US-001");
        str                             custEmail = custTable.InvoiceEmailAddress;
        CustAccountStatementExtContract contract = new CustAccountStatementExtContract();
        
        CustAccountStatementExtTmp      custAccountStatementExtTmp;
        
        try
        {
            if(custEmail)
            {
                mailer = new SysMailerMessageBuilder();
                mailer.setSubject("test d365 email");
                mailer.setFrom(SysEmailParameters.SMTPUserName);
                mailer.setBody(strReplace(CustParameters::find().ARStatementEmailBody, "\n", "
")); //mailer.addCc(UserInfo.networkAlias); mailer.addTo(custEmail); CustAccountStatementExtController controller = new CustAccountStatementExtController(); SRSPrintDestinationSettings settings; Filename fileName; SRSProxy srsProxy; SRSReportRunService srsReportRunService = new SrsReportRunService(); Microsoft.Dynamics.AX.Framework.Reporting.Shared.ReportingService.ParameterValue[] parameterValueArray; Map reportParametersMap; SRSReportExecutionInfo executionInfo = new SRSReportExecutionInfo(); System.Byte[] reportBytes = new System.Byte[0](); controller.parmReportName(ssrsReportStr(CustAccountStatementExt, Report)); fileName = "CustAccountStatementExt.pdf"; controller.parmShowDialog(false); controller.parmLoadFromSysLastValue(false); // Provide printer settings settings = controller.parmReportContract().parmPrintSettings(); settings.printMediumType(SRSPrintMediumType::File); settings.fileName(fileName); settings.fileFormat(SRSReportFileFormat::PDF); // Rendering the report controller.parmReportContract().parmReportServerConfig(SRSConfiguration::getDefaultServerConfiguration()); controller.parmReportContract().parmReportExecutionInfo(executionInfo); //set parameters contract.parmFromDate(mkdate(1, mthofyr(today()), year(today()))); contract.parmToDate(today()); contract.parmOnlyOpen(true); contract.parmIncludeReversed(false); contract.parmPrintNonZero(true); contract.parmPrintPaymentSchedule(false); contract.parmPrintCreditLimit(true); contract.parmShowDNCN(custTable.ARStatementPrintDNCN); contract.parmShowNegative(custTable.ARStatementPrintNegative); contract.parmPrintAging(true); contract.parmAgingPeriod(true); contract.parmAgingBucket(CustParameters::find().ARStatementStatRepInterval); contract.parmAgingBucketPrintDescription(true); contract.parmCustAccount("US-001"); contract.parmCustAccountStatementExtTmp(custAccountStatementExtTmp.getPhysicalTableName()); controller.parmReportContract().parmRdlContract().parmLanguageId("en-us"); controller.parmReportContract().parmRdlContract().parmLabelLanguageId("en-us"); controller.parmReportContract().parmRdpContract(Contract); srsReportRunService.getReportDataContract(controller.parmReportContract().parmReportName()); // TODO srsReportRunService.preRunReport(controller.parmReportContract()); reportParametersMap = srsReportRunService.createParamMapFromContract(controller.parmReportContract()); parameterValueArray = SrsReportRunUtil::getParameterValueArray(reportParametersMap); srsProxy = SRSProxy::constructWithConfiguration(controller.parmReportContract().parmReportServerConfig()); // Actual rendering to byte array reportBytes = srsproxy.renderReportToByteArray(controller.parmReportContract().parmReportPath(), parameterValueArray,settings.fileFormat(), settings.deviceinfo()); if (reportBytes) { System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(reportBytes); mailer.addAttachment(memoryStream, fileName, "application/pdf"); } smtp.sendNonInteractive(mailer.getMessage()); } else { warning("No customer email"); } } catch(Exception::CLRError) { SysUserInfo SysUserInfo; str warningMsd; System.Exception netExcepn; netExcepn = CLRInterop::getLastException(); warningMsd = strFmt("Fail to send email %1. ") netExcepn.ToString(); warning(warningMsd); } } public static void main(Args _args) { AutoSendEmailInvoiceStatement instance; ; instance = new AutoSendEmailInvoiceStatement(); if (instance.prompt()) instance.run(); } }

I have the same question (0)
  • huijij Profile Picture
    19,811 on at

    Hi Tony,

    Maybe you should turn the Bytes into a stream then call method of addAttachment():

        container binData;
            Binary binaryData;
            System.IO.MemoryStream mstream = new System.IO.MemoryStream(reportBytes);
            binaryData = Binary::constructFromMemoryStream(mstream);
            if(binaryData)
            {
                binData = binaryData.getContainer();
            }
        System.Byte[] binData1;
        System.IO.Stream stream1;
      // Turn the Bytes into a stream
            for(int i = 0; i < conLen(binData); i  )
            {
                binData1 = conPeek(binData,i 1);
                stream1 = new System.IO.MemoryStream(binData1);
            }
    
            mailer.addAttachment(stream1, fileName, "application/pdf");
    

    regards

  • Suggested answer
    greengrimms Profile Picture
    1,400 on at

    Hi Tony,

    Apart from what's suggested by Judy, check if the memoryStream object has any values when debugging. Also, is the pdf being attached to the email? Or are you just getting a blank pdf in your email?

    Depending on that, your issue could be on the report printing implementation or on the arguments you're sending to the addAttachment method.

  • Tony Mok Profile Picture
    577 on at

    Thank you Judy Jee, Danilo Bambi.

    The pdf is finally generated by Print archive. The code is shown as below for reference:

    class AutoSendEmailInvoiceStatementCopy extends RunBaseBatch
    {
        public void run()
        {
            #SRSFramework
            CustAccountStatementExtContract         contract;
            CustInvoiceJour                         custInvoiceJourLocal;
            SRSPrintDestinationSettings             SRSPrintDestinationSettings;
            CustTable                               custTable = CustTable::find("US-001");
            str                                     custEmail = custTable.InvoiceEmailAddress;
            SysEmailParameters                      SysEmailParameters = SysEmailParameters::find();
            CustAccountStatementExtTmp              custAccountStatementExtTmp;
        
            CustAccountStatementExtController   controller = new CustAccountStatementExtController();
            controller.parmReportName(PrintMgmtDocType::construct(PrintMgmtDocumentType::CustAccountStatement).getDefaultReportFormat());
            str fileName = "CustAccountStatementExt.pdf";
            controller.parmShowDialog(false);
            controller.parmLoadFromSysLastValue(false);
    
            Args _args = new Args();
            _args.record(custTable);
            controller.parmArgs(_args);
        
            contract = controller.parmReportContract().parmRdpContract();
            contract.parmRecordId(custTable.RecId);  // Record id must be passed otherwise the report will be empty
    
            contract.parmFromDate(mkdate(1, mthofyr(today()), year(today())));
            contract.parmToDate(today());
            contract.parmOnlyOpen(true);
            contract.parmIncludeReversed(false);
            contract.parmPrintNonZero(true);
            contract.parmPrintPaymentSchedule(false);
            contract.parmPrintCreditLimit(true);
            contract.parmPrintAging(true);
            contract.parmAgingPeriod(true);
            contract.parmAgingBucket(CustParameters::find().ARStatementStatRepInterval);
            contract.parmAgingBucketPrintDescription(true);
    
    
            contract.parmDayMonth(DayMonth::Day);
            contract.parmManualSetup(false);
            contract.parmPrintAmountGiro(false);
            contract.parmPrintGiro(PaymentStub::None);
            contract.parmPrintingDirection(ForwardBackwardPrinting::Forward);
            contract.parmPrintType("");
            contract.parmSpecifyDueToDate(dateNull());
    
            contract.parmCustAccount("US-001");
            Query query;
            MapEnumerator enumerator;
    
            enumerator = controller.parmReportContract().parmQueryContracts().getEnumerator();
            enumerator.moveNext();
            query = enumerator.currentValue();
            query.dataSourceTable(tableNum(CustTable)).addRange(fieldNum(CustTable, AccountNum)).value(queryValue(custTable.AccountNum));
    
            SrsReportDataContract srsReportDataContract = controller.parmReportContract();
            controller.parmReportContract(srsReportDataContract);
        
            SRSPrintDestinationSettings = new  SRSPrintDestinationSettings();
            SRSPrintDestinationSettings.overridePrintContractSettings(true);
            SRSPrintDestinationSettings.printMediumType(SRSPrintMediumType::Archive);
            SRSPrintDestinationSettings.parmOverwriteFileIsSet(true);
            SRSPrintDestinationSettings.fileFormat(SRSReportFileFormat::PDF);
    
            SRSPrintArchiveContract SRSPrintArchiveContract = new SRSPrintArchiveContract(SRSReportFileFormat::PDF);
            SRSPrintDestinationSettings.parmSRSPrintArchiveContract(SRSPrintArchiveContract);
            str archiveName = strFmt('%1-%2', curUserId(), timeNow());
            controller.parmReportContract().parmReportCaption(archiveName);//**This is the 'Description' field in the archive
        
            controller.parmReportContract().parmPrintSettings(SRSPrintDestinationSettings);
        
            controller.run();
    
            PrintJobHeader printJobHeader;
    
            select firstonly forupdate printJobHeader where printJobHeader.jobDescription == archiveName;
    
            info(strFmt("printJobHeader.RecId %1", printJobHeader.RecId));
    
            DocuRef docuRef;
    
            select firstonly forupdate docuRef where docuRef.RefRecId == PrintJobHeader.RecId;
    
            DocuValue docuValue;
            select firstonly forupdate docuValue where docuValue.RecId == docuRef.ValueRecId;
    
            info(strFmt("docuRef.RecId %1", docuRef.RecId));
            info(strFmt("docuValue.RecId %1", docuValue.RecId));
            
            System.IO.Stream stream = DocumentManagement::getAttachmentStream(docuRef);
    
            ttsbegin;
            printJobHeader.delete();
            docuRef.delete();
            docuValue.delete();
            ttscommit;
    
            
            infolog.clear();//Clear the message about archiving the report
    
            SysMailerMessageBuilder         mailer = new SysMailerMessageBuilder();
            mailer = new SysMailerMessageBuilder();
            mailer.setSubject("test d365 email..");
            mailer.setFrom(SysEmailParameters.SMTPUserName);
            mailer.setBody(strReplace(CustParameters::find().ARStatementEmailBody, "\n", "
    ")); //mailer.addCc(UserInfo.networkAlias); mailer.addTo(custEmail); if (stream != null) { mailer.addAttachment(stream, fileName, "application/pdf"); } SysMailerSMTP smtp = new SysMailerSMTP(); smtp.sendNonInteractive(mailer.getMessage()); } public static void main(Args _args) { AutoSendEmailInvoiceStatementCopy instance; ; instance = new AutoSendEmailInvoiceStatementCopy(); if (instance.prompt()) instance.run(); } }

  • Suggested answer
    Ludwig Reinhard Profile Picture
    Microsoft Employee on at

    Hi Tony,

    Why don't you use the standard ER customer account statement that you can send without making a code adjustment?

    Best regards,

    Ludwig

  • Tony Mok Profile Picture
    577 on at

    Hi Ludwig Reinhard,

    As the email is sent with not just customer statement, but also customer invoice, we need to code. By the way, what is standard ER customer account statement?

  • Sathish_Chinnappan Profile Picture
    1,318 on at
    Hi Tony Mok,
     
    Still I'm getting same issue mail sending with empty content. Can u send me full code.

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Introducing the 2026 Season 1 community Super Users

Congratulations to our 2026 Super Stars!

Congratulations to our 2025 Community Spotlights

Thanks to all of our 2025 Community Spotlight stars!

Leaderboard > Finance | Project Operations, Human Resources, AX, GP, SL

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 510 Super User 2026 Season 1

#2
Giorgio Bonacorsi Profile Picture

Giorgio Bonacorsi 399

#3
Adis Profile Picture

Adis 251 Super User 2026 Season 1

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans