Skip to main content

How to send email messages with Microsoft Dynamics AX

There are more than one way to send emails through Microsoft Dynamics AX system, using X++ code.

The most recommended way is to use the standard mail mechanism built in the system.
That way copies of any email you send will be save in the Email sending status form (based on table SysOutgoingEmailTable) and you will be able to monitor and see status of sent emails:
(Administration -> Periodic -> E-mail processing -> Email sending status; Form: SysOutgoingEmailTable)
This mechanism based on a system table that contain the emails, and a batch job that scan that table and send the emails, one by one (with retries and status controlling).
This technique is very simple to use and therefore it has some disadvantages; you cannot add attachments or use advanced email properties (cc, bcc, priority flag, etc).
To use this mechanism, first you have to make sure you a SMTP server configured and running.
Go to Administration -> Setup -> E-mail parameters and fill the required settings:
(Form: SysEmailParameters)
Next step is to make sure the E-mail distributor batch is up and running.
Go to Basic -> Inquiries -> Batch Job and check if the batch job exists with status Executing or Waiting.
(Form: BatchJob)
If it doesn’t, you can activate it from Administration -> Periodic -> E-mail processing -> Batch.
Now we are ready to implement our X++ code:
void SendMail()
{
SysMailer mail;
SysOutgoingEmailTable outgoingEmailTable;
SysEmailItemId nextEmailItemId;
Map map;
str SenderName, SenderEmail, To, Subject, Body;
;

SenderName = "X++.info";
SenderEmail = "Sender@xplusplus.info";
To = "recipient@xplusplus.info";
Subject = "Subject line for the email";
Body = "Body of the email";

nextEmailItemId = EventInbox::nextEventId();
outgoingEmailTable.EmailItemId = nextEmailItemId;
outgoingEmailTable.IsSystemEmail = NoYes::No;
outgoingEmailTable.Sender = SenderEmail;
outgoingEmailTable.SenderName = SenderName;
outgoingEmailTable.Recipient = To;
outgoingEmailTable.Subject = SysEmailMessage::stringExpand(Subject, map);
outgoingEmailTable.Priority = eMailPriority::Normal ;
outgoingEmailTable.WithRetries = false;
outgoingEmailTable.RetryNum = 0;
outgoingEmailTable.UserId = curUserId();
outgoingEmailTable.Status = SysEmailStatus::Unsent;
outgoingEmailTable.Message = Body;
outgoingEmailTable.LatestStatusChangeDateTime = DateTimeUtil::getSystemDateTime();
outgoingEmailTable.insert();
}
The result of the example above will shown in the Email sending status form as mentioned above.
(Administration -> Periodic -> E-mail processing -> Email sending status; Form: SysOutgoingEmailTable)

Popular posts from this blog

Dynamics Axapta: Sales Orders & Business Connector

Well, again folllowing my same idea of writting close to nothing and pasting code, I'll paste in some code to create a sales order from some basic data and the invoice it. I'll try to explain more in the future. AxaptaObject axSalesTable = ax.CreateAxaptaObject("AxSalesTable"); AxaptaRecord rcInventDim = ax.CreateAxaptaRecord("InventDim"); AxaptaRecord rcCustTable = ax.CreateAxaptaRecord("CustTable"); rcCustTable.ExecuteStmt("select * from %1 where %1.AccountNum == '" + MySalesOrderObject.CustAccount + "'"); if (MySalesOrderObject.CurrencyCode.Trim().Length == 0) MySalesOrderObject.CurrencyCode = rcCustTable.get_Field("Currency").ToString().Trim(); string sTaxGroup = rcCustTable.get_Field("taxgroup").ToString().Trim(); //set header level fields axSalesTable.Call("parmSalesName", MySalesOrderObject.SalesName.Trim()); axSalesTable.Call("parmCustAccount", M

Passing values between form and class

Class name is EmplDuplication and Form is EmplTable . void clicked() {    MenuFunction mf;    args args = new Args();    ;     args.record(EmplTable);     mf = new menufunction(identifierstr(EmplDuplication), MenuItemType::Action); mf.run(args); } Meanwhile, in the main() method of the EmplDuplication class, we need to put this Axapta x++ code to get the datasource: static void main(Args args) {     EmplDuplication EmplDuplication; EmplTable localEmplTable; ;     if(args.record().TableId == tablenum(EmplTable)) localEmplTable = args.record();     ... }