Custom e-mail process in Microsoft Dynamics AX 2012 R3

Custom e-mail process in Microsoft Dynamics AX 2012 R3

One of the common requirements I’ve seen being requested by the client in recent implementations is to have the ability to send out e-mails to customers on a custom trigger. For example, the client may want to send out e-mails to a customer when a shipment has been made from the warehouse. There might even be a scenario where the e-mail needs to be sent out when a custom field has been set to a specific state.

To be able to implement this, there are some necessary configurations we would need to complete first.

SMTP setup

Navigate to System Administration > Setup > System > E-mail parameters and provide the relevant setup information for sending out e-mails from AX.

E-mail template

Navigate to Organization administration > Setup > E-mail templates. In the form, perform the following steps:

  1. Create a new e-mail template and provide the necessary values.
  2. Provide the template subject and layout type.
  3. Click E-mail message button and a form will open.
  4. This form has 3 tabs at the bottom namely Normal, HTML and Preview. In the HTML tab, the template for the e-mail can be provided. Note that only the contents of the <body> tag are to be placed here as AX appends the <html>, <head> and <body> tags automatically during E-mail processing. This also means that any CSS which is required has to be placed in-line in the HTML tags.

Configure e-mail template for use

The e-mail template created previously should be configurable from the front-end as the client might need to replace it with a new one, let’s say a template designed specifically for sales during the holiday season. So instead of hard-coding the template ID within the code, it would be preferable to add this as a configurable option in parameters form or any other form as per the requirement.

Customization overview

To enable the custom e-mail process from a technical perspective, we might have one of the following 2 scenarios depending on the requirement:

  1. A process that executes when a specific action is performed in the system
  2. A process that executes on pre-defined intervals and executes on the basis of a condition

In this post, we’ll be discussing the second scenario. Let’s say we have a requirement where we would like to send an e-mail to the customer once their order has been ‘Delivered’. For this, we can create a batch job which periodically checks the orders’ status and sends out e-mails for the ones which have been delivered recently and no e-mail has been sent out for these yet.

An important point to note here is that there should be a means to check whether the e-mail has already been sent out for a particular record or not. One way of doing this is to set a flag on the record in the table which will be updated during our process once its e-mail has been generated and added to the queue.

Solution implementation

The first step here would be to create a class which extends from RunBaseBatch. This would allow us to create a batch job for our custom code and let it execute on set intervals without user intervention.

Now there are a few basic methods which we would need to override for our solution. Following is the list of methods and a description of what needs to be done in the same respectively:

  • new()
    As a best practice the new() method should be declared as protected and should only be accessible from within the class.
  • construct()
    This method should be declared as public static and only this method should be used whenever we want to generate and return a new instance of our class from external code.
  • description()
    This method is simply used to return a default description string. This string is automatically displayed to the user whenever they proceed to execute the job. This description can be changed by the user before execution if required.
  • main(Args _args)
    This method is the starting point of execution for the process. A new instance of our class is created here and the call to run() method is generated.
  • run()
    This is the method where the actual logic and solution for our process needs to be implemented. Once we’ve gathered the required data here, the next step is to simply call a default method which will generate the e-mail and add it to the distribution queue.

Details of e-mail generation method

For the generation of our order’s e-mail, we have an Out-Of-The-Box (OOTB) method which serves the purpose. The method is SysEmailTable::sendmail(). This method can be called from within the run() method by providing the required parameters for execution.

The parameters have been summarized below:

  • SysEmailId _emailId:
    This is the e-mail template ID we created earlier in the configuration.
  • LanguageId _language:
    This is the default language ID for the e-mail template. If passed as empty, it will retrieve the language ID configured against the e-mail template.
  • str _emailAddr:
    This is the recipient e-mail address where we want the e-mail to be sent.
  • Map _mappings (Optional):
    AX allows us to set values dynamically in the template during e-mail generation. For this purpose we can put placeholders in the HTML code like %Placeholder Name%. To replace the placeholder during process execution, we need to provide value mappings in this object. For example, let’s say we have the customer name to be replaced. In this case, we’ll add the customer name placeholder from the HTML against target value in the map. During process execution, AX will replace all placeholders with the provided values.
  • FilenameOpen _attachmentFilename (Optional):
    This parameter can be used to attach files in the outgoing e-mail. The complete path of the target file needs to be provided here.
  • str _xmlData (Optional):
    This parameter can be used to pass the XML template in case we’re not using HTML design. The complete XML would be passed in string format here.
  • boolean _isTraceable (Optional):
    AX allows to keep a copy of the e-mail being sent if this parameter is set to true. The copy can be reviewed from System administration > Periodic > E-mail processing > E-mail sending status. Once this form is opened, there is a check-box near the top-left corner Also show sent e-mails. Once checked, it shows all the e-mails which have been sent to date and had traceability set to true.
  • UserId _userId (Optional):
    The parameter can be used to set the user ID which is being used to add the generated e-mail to outgoing e-mail queue.
  • boolean _isWithRetries (Optional):
    This parameter can be used to specify whether the sending the e-mail should be retried in case it fails to be sent out the first time.

Batch scheduling

Now that our code has been completed, we would need to queue the following batch jobs for process automation:

  1. Our custom class created for e-mail processing. To schedule this in batch, we need to create an Action menu item and place a link in the relevant AX area page as per requirement. Once the link is clicked, the standard AX batch job execution dialog will pop-up. Set the necessary values, Batch processing to true and Recurrence as required and click OK.
  2. The e-mail processing batch job. This is the job which sends out all e-mails currently in the distribution queue. To schedule this in batch, go to System administration > Periodic > E-mail processing > Batch. Once the link is clicked, the standard AX batch job execution dialog will pop-up. Perform the necessary steps as described in the previous step and click OK.


After having performed the steps as described in this post, we will have successfully implemented the solution and scheduled e-mail processing for the required scenario. The process will be run automatically as per the recurrence set and will not require further intervention from front-end users.

Ubaid Ullah's picture
Ubaid Ullah is currently working as a Senior Software Engineer in ERP Implementation Services. He has been with Systems Limited from past 3 years. He works in the role of Microsoft Dynamics AX Technical Consultant and has experience in AX 2012 development.

Disclaimer: The views expressed here are solely those of the author in his private capacity and do not in any way represent the views of Systems Limited, or any other entity related to Systems Limited.

Add new comment