Skip to main content

Notifications

Finance | Project Operations, Human Resources, ...
Answered

Save invoice and send it as eamil

Posted on by 25

Hi, 

I have a code issue that are troubling me and I would like to see if any of you have an idea.

Currently we’re integrating to a new website.

One of the functions we need is to generate an invoice to the customer.

We’ve added a button on the website, once pushed it will send through an email and invoice number to a method in AX that will generate the invoice and email it back.

 

The headache comes as it works for some invoices but not others and I cannot seem to figure out why.

The error we get is that when sending the email there is no file to attach.

So somewhere when I’m generating the invoice in AX it doesn’t work and then when I call the send email code there is no file to attach.

 

When I preview the invoices in AX they all shows to screen with no issues.

I can also save them as PDF’s no issue.

 

But when running the code some invoice fails to save other work fine, the is error:

Method 'addAttachment' in COM object of class 'CDO.Message' returned error code 0x80070002 (<unknown>) which means: The system cannot find the file specified.

I haven’t been able to google anything useful regarding this error.

 

I have a job I’m using to call the method

static void SSS_EmailInvoice(Args _args)

{

 

    //str xmlDoc  = "<InvoicePrint><FromAddress>sales@sssaustralia.com.au</FromAddress><ToAddress>soren.rasmussen@sssaustralia.com.au</ToAddress><Subject>SSS Invoice</Subject><Body>This is your invoice</Body><InvoiceId>SI0483794</InvoiceId><SalesId></SalesId> </InvoicePrint>"; //works

    str xmlDoc  = "<InvoicePrint><FromAddress>sales@sssaustralia.com.au</FromAddress><ToAddress>soren.rasmussen@sssaustralia.com.au</ToAddress><Subject>SSS Invoice</Subject><Body>This is your invoice</Body><InvoiceId>SI0486086</InvoiceId><SalesId></SalesId> </InvoicePrint>"; //fails  

    

    //SI0497671,SI0483794,SI0483794,SI0486086,SI0497599,SI0497600

   

    CV_SSSCustom::printInvoice(xmlDoc);

 

}

 

 

The method is a static method on a functions class

 

public static str printInvoice(str xmlPayload)

{

    XmlDocument doc;

    XmlElement element;

    XmlElement item;

    XMLNodeListIterator iterator;

    //

    SysEmailParameters          parameters = SysEmailParameters::find();

    SMTPRelayServerName         relayServer;

    SMTPPortNumber              portNumber;

    SMTPUserName                userName;

    SMTPPassword                password;

    InteropPermission           interopPermission = new InteropPermission(InteropKind::ComInterop);

    FileIOPermission            fioPermission;

    System.Exception            e;

    SysMailer                   mailer = new SysMailer();

   

    //report variables

    SrsReportRunController      ssrsController = new SrsReportRunController();

    SalesInvoiceContract        salesInvoiceContract = new SalesInvoiceContract();

    SRSPrintDestinationSettings printerSettings;

    CustInvoiceJour             custInvoiceJour;

    smmParametersTable          smmParametersTable = smmParametersTable::find();

    Filename                    fileName;

 

    str                         fromAddress;

    str                         toAddress; //inbound parameter

    str                         subject;

    str                         body;

    SalesId                     salesId;

    InvoiceId                   invoiceId; //inbound parameter

 

    doc = new XmlDocument();

    doc.loadXml(xmlPayload);

    element = doc.documentElement().selectSingleNode("//InvoicePrint");

    fromAddress = element.getNamedElement("FromAddress").text();

    toAddress = element.getNamedElement("ToAddress").text();

    subject = element.getNamedElement("Subject").text();

    body = element.getNamedElement("Body").text();

    invoiceId = element.getNamedElement("InvoiceId").text();

    SalesId = element.getNamedElement("SalesId").text();

   

    // Add record

    if (invoiceId)

    {

        select firstOnly custInvoiceJour

            where custInvoiceJour.InvoiceId == invoiceId;

            //where custInvoiceJour.InvoiceId == invoiceId || custInvoiceJour.SalesId == SalesId;

 

        fileName = strFmt("%1\\%2.pdf", smmParametersTable.SSSCVArchivePath, invoiceId);

 

    /*    fioPermission = new FileIOPermission(fileName ,"RW");

        fioPermission.assert();

        interopPermission = new InteropPermission(InteropKind::ComInterop);*/

        interopPermission.assert();         

        

        

        // Define which report design to print

        ssrsController.parmReportName("SalesInvoice.ReportTFS"); //ssrsReportStr(SalesInvoice, ReportTFS));       

        ssrsController.parmReportName(ssrsReportStr(SalesInvoice, ReportTFS));

        // Ddefine how we want to execute the report (right now or batch style)

        ssrsController.parmExecutionMode(SysOperationExecutionMode::ReliableAsynchronous);

        // Hide the report dialog

        ssrsController.parmShowDialog(false);

 

        // Need to populate the required parms for the current sales order controller

        salesInvoiceContract.parmRecordId(custInvoiceJour.RecId);

        salesInvoiceContract.parmCountryRegionISOCode(SysCountryRegionCode::countryInfo());

        salesInvoiceContract.parmDocumentTitle('Invoice');

        // Link the contract to the controller so we know how to run the dp

        ssrsController.parmReportContract().parmRdpContract(salesInvoiceContract);

 

        // Link the printer settings to the controller

        printerSettings = ssrsController.parmReportContract().parmPrintSettings();

        // Print to HTML and always overwrite if the file exists

        printerSettings.printMediumType(SRSPrintMediumType::File);

        printerSettings.fileFormat(SRSReportFileFormat::PDF);

        printerSettings.overwriteFile(true);

        printerSettings.fileName(fileName);

 

        // Run & save the report

        ssrsController.startOperation();

 

        if (printerSettings.fileName())

        {

 

            if (parameters.SMTPRelayServerName)

                relayServer = parameters.SMTPRelayServerName;

            else

                relayServer = parameters.SMTPServerIPAddress;

 

            portNumber  = parameters.SMTPPortNumber;

            userName    = parameters.SMTPUserName;

            password    = SysEmailParameters::password();

            subject     = subject;

            body        = body;

 

            try

            {

               // interopPermission = new InteropPermission(InteropKind::ComInterop);

                //interopPermission.assert();

 

                mailer = new SysMailer();

                mailer.SMTPRelayServer(relayServer,portNumber,userName,password, parameters.NTLM);

                mailer.fromAddress(fromAddress);

                mailer.tos().appendAddress(toAddress);

 

                mailer.subject(subject);

                mailer.htmlBody(body);

                mailer.attachments().add(printerSettings.fileName());

                mailer.sendMail();

                //CodeAccessPermission::revertAssert();

                //info("Email has been send!");

            }

            catch (Exception::CLRError)

            {

                e = ClrInterop::getLastException();

 

                while (e)

                {

                    info(e.get_Message());

                    e = e.get_InnerException();

                    info(strFmt("%1", e));

                }

            }

          

        }

        CodeAccessPermission::revertAssert();

    }

    else

        info("No invoiceId selected");

   

    return "OK";

}

  • Verified answer
    Tigerrasmussen Profile Picture
    Tigerrasmussen 25 on at
    RE: Save invoice and send it as eamil

    Hi Janna,

    no unfortunately I haven't been able to figure out the solution.

    I believe it could be caused by the System account not having enough access.

    But again I don't want to play around to much with those settings.

    I've decided to follow another path and create a batch that will export all invoice to a directory.

    Once exported the website can access the files and email them.

    So there is definitely read access for the system account.

    Thanks

    Soren

  • RE: Save invoice and send it as eamil

    Hi Soren,

    Is he issue resolved on your side already?

  • Sergei Minozhenko Profile Picture
    Sergei Minozhenko 23,089 on at
    RE: Save invoice and send it as eamil

    Hi Soren Rasmussen,

    Have you tried to debug it to find the exact place where the error is coming? Are you running the process in batch or it's user session? Have you already tried to make a full x++ compile + full CIL build?

  • Tigerrasmussen Profile Picture
    Tigerrasmussen 25 on at
    RE: Save invoice and send it as eamil

    Hi Sergei,

    thanks for your reply. There is definitely an issue saving the file with this code.

    For some reason the invoice generation cannot save the file.

    I did restart the SQL and AOS and now it doesn't work at all.

    The webservice are getting an the following error, have you seen this before?

    Unable to cast object of type 'System.Object[]' to type 'Microsoft.Dynamics.Ax.Xpp.Common

    I did alter the code as per below but gets the same error, it seems like the webservice cannot access the method or fails during the invoice generation. Can you see any issues?

    public static str printInvoice(str xmlPayload)

    {

       #File

       XmlDocument doc;

       XmlElement element;

       XmlElement item;

       XMLNodeListIterator iterator;

       //

       SysEmailParameters          parameters = SysEmailParameters::find();

       SMTPRelayServerName         relayServer;

       SMTPPortNumber              portNumber;

       SMTPUserName                userName;

       SMTPPassword                password;

       InteropPermission           interopPermission;

       System.Exception            e;

       SysMailer                   mailer = new SysMailer();

       //

       //report variables

       SalesInvoiceController               salesInvoiceController;

       SalesInvoiceContract                 salesInvoiceContract;

       SrsReportDataContract                contract;

       SrsReportRunInterface                reportRun;

       SRSReportExecutionInfo               executionInfo;

       FilePath                             filePath;

       SrsReportRunController      ssrsController = new SrsReportRunController();

       //SalesInvoiceContract        salesInvoiceContract = new SalesInvoiceContract();

       SRSPrintDestinationSettings printerSettings;

       CustInvoiceJour             custInvoiceJour;

       smmParametersTable          smmParametersTable = smmParametersTable::find();

       Filename                    fileName;

       Args                        args;

       str                         fromAddress;

       str                         toAddress; //inbound parameter

       str                         subject;

       str                         body;

       SalesId                     salesId;

       InvoiceId                   invoiceId; //inbound parameter

       doc = new XmlDocument();

       doc.loadXml(xmlPayload);

       element = doc.documentElement().selectSingleNode("//InvoicePrint");

       fromAddress = element.getNamedElement("FromAddress").text();

       toAddress = element.getNamedElement("ToAddress").text();

       subject = element.getNamedElement("Subject").text();

       body = element.getNamedElement("Body").text();

       invoiceId = element.getNamedElement("InvoiceId").text();

       SalesId = element.getNamedElement("SalesId").text();

       args = new Args();

       args.parmEnumType(enumNum(PrintCopyOriginal));

       args.parmEnum(PrintCopyOriginal::OriginalPrint);

       // Add record

       if (invoiceId)

       {

           select firstOnly custInvoiceJour

               where custInvoiceJour.InvoiceId == invoiceId;

               //where custInvoiceJour.InvoiceId == invoiceId || custInvoiceJour.SalesId == SalesId;

           fileName = strFmt("%1\\%2.pdf", smmParametersTable.SSSCVArchivePath, invoiceId);

           new FileIOPermission(filePath, "RW").assert();

           salesInvoiceController = new salesInvoiceController();

           salesInvoiceController.parmReportName(ssrsReportStr(SalesInvoice, ReportTFS));

           salesInvoiceController.parmExecutionMode(SysOperationExecutionMode::ScheduledBatch);

           salesInvoiceController.parmShowDialog(false);

           args.record(custInvoiceJour);

           salesInvoiceContract = salesInvoiceController.parmReportContract().parmRdpContract();

           salesInvoiceContract.parmRecordId(custInvoiceJour.RecId);

           salesInvoiceContract.parmCountryRegionISOCode(SysCountryRegionCode::countryInfo());

           salesInvoiceContract.parmDocumentTitle("Invoice");

           contract = salesInvoiceController.parmReportContract();

           if(args.record() && contract != null)

           {

               reportRun = new SrsReportRunImpl(contract.parmReportName());

               reportRun.parmReportContract(contract);

               if (reportRun.parmReportContract().parmReportExecutionInfo() == null)

               {

                   executionInfo = new SRSReportExecutionInfo();

                   reportRun.parmReportContract().parmReportExecutionInfo(executionInfo);

               }

               printerSettings = reportRun.parmReportContract().parmPrintSettings();

               printerSettings.printMediumType(SRSPrintMediumType::File);

               printerSettings.fileFormat(SRSReportFileFormat::PDF);

               filePath = printerSettings.fileName(@fileName);

               printerSettings.overwriteFile(true);

               reportRun.runReport();

           }

           if (filePath)

           {

               if (parameters.SMTPRelayServerName)

                   relayServer = parameters.SMTPRelayServerName;

               else

                   relayServer = parameters.SMTPServerIPAddress;

               portNumber  = parameters.SMTPPortNumber;

               userName    = parameters.SMTPUserName;

               password    = SysEmailParameters::password();

               subject     = subject;

               body        = body;

               try

               {

    //                interopPermission = new InteropPermission(InteropKind::ComInterop);

    //                interopPermission.assert();

                   mailer = new SysMailer();

                   mailer.SMTPRelayServer(relayServer,portNumber,userName,password, parameters.NTLM);

                   mailer.fromAddress(fromAddress);

                   mailer.tos().appendAddress(toAddress);

                   mailer.subject(subject);

                   mailer.htmlBody(body);

                   mailer.attachments().add(printerSettings.fileName());

                   mailer.sendMail();

     //              CodeAccessPermission::revertAssert();

                   //info("Email has been send!");

               }

               catch (Exception::CLRError)

               {

                   e = ClrInterop::getLastException();

                   while (e)

                   {

                       info(e.get_Message());

                       e = e.get_InnerException();

                       info(strFmt("%1", e));

                   }

               }

           }//filepath

           CodeAccessPermission::revertAssert();

       }//invoice

       else

           info("No invoiceId selected");

       return "OK";

    }

  • Sergei Minozhenko Profile Picture
    Sergei Minozhenko 23,089 on at
    RE: Save invoice and send it as eamil

    Hi Tigerrasmussen,

    I would add check if the file exists before adding the attachment to the e-mail. Maybe it's not ready or locked by another process and can't be attached because of that.

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

December Spotlight Star - Muhammad Affan

Congratulations to a top community star!

Top 10 leaders for November!

Congratulations to our November super stars!

Community AMA December 12th

Join us as we continue to demystify the Dynamics 365 Contact Center

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 291,253 Super User 2024 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 230,188 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Product updates

Dynamics 365 release plans