How to send emails from code in AX 7

There are many situations when you may want to send an e-mail from Dynamics AX. Let’s see what options we have.

First of all, you have to configure the environment. Go to System administration > Setup > Email > Email parameters (or simply search for email parameters in navigation search).

The first tab shows email providers. Simply put, email providers are classes that knows how to send emails. If you want to construct a message in code and send it to an SMTP server, you don’t need many different providers, but that’s not the only option. Maybe you want to use an Exchange server instead of SMTP. Or maybe you want to allow users to modify messages before sending.

There are two categories of providers: interactive and non-interactive. You have to choose one non-interactive provider to be used for sending directly from code – that’s done in Batch email provider field. Then you can enable and disable interactive providers. As you’ll see later, if more than one is enabled, the user can choose which to use.


You may need extra configuration for providers, such as connection details to your Exchange server. To keep it simple, configure just the SMTP server on the SMTP settings tab. If you don’t have / don’t want to use any real SMTP server, you can use development tools such as smtp4dev (as I did).


With the setup ready, let’s look at some code. You can create a runnable class to test it.

First of all, you have to build a message. It’s an object containing the subject, the body, recipients and so on. We have the message builder class to help:

var builder = new SysMailerMessageBuilder();
builder.setBody("Test email");

If you prefer, you can use a more succinct syntax, because the builder offers a fluent interface:

var builder = new SysMailerMessageBuilder()
    .setBody("Test email");

You can combine these two approaches at will – it’s no magic, just a few methods returning objects.

When you’ve configured the builder, let it actually build the message:

var message = builder.getMessage();

What it returns is an instance of System.Net.Mail.MailMessage class, but it isn’t really necessary to know. The var keyword helps us to hide such a detail.

The last step is getting a mailer and sending the message out. Try the non-interactive mailer first:


If I run the code, my smtp4dev successfully receives the mail.


Now let’s try an interactive mailer.


Notice that the syntax is very similar to what we did with the non-interactive mailer, and that the message is still constructed in exactly the same way, therefore you don’t have to learn almost anything new.

If you run the code, AX realizes that there are several enabled providers, therefore it let you choose:


What happens next obviously depends on the provider. If you pick the AX email client, you’ll get this form:


When you click Send, it will send the email via SMTP (and you can see it in your inbox, in smtp4dev or so).

You can also build your own providers, if needed. You just have to create a class and implement SysIMailerInteractive interface, SysIMailerNonInteractive interface or both.

I don’t want to go to details here, nevertheless you can look at my dummy interactive provider to see that you don’t really need much boilerplate code.

using System.ComponentModel.Composition;
 ExportMetadataAttribute(extendedTypeStr(SysMailerId), #SysMailerMyOwn_ID)]
public class MyOwnEmailProvider implements SysIMailerInteractive
    public SysMailerDescription getDescription()
        return "My Own Email Provider";
    public SysMailerId getId()
        return #SysMailerMyOwn_ID;
    public boolean sendInteractive(System.Net.Mail.MailMessage _message)
        info("Forget it. They wouldn't read it anyway.");   
        return true;

You don’t have to register the provider in any way – the pluggable architecture in AX and the Managed Extensibility Framework will handle that. Just build your project, start AX and use your new provider.


If you want to review implementation of standard providers, the classes are called SysMailerSMTP, SysMailerExchange and SysMailerEML.

Several people already asked about sending emails from code in AX 7. I hope this blog post will answer the most common questions.

File upload and download in AX 7

New Dynamics AX is a web application running in cloud, so how can users work with files in such an environment? The answer is: in the same way as with other web applications. If you know how to add and download attachments in your webmail client, you can do it in AX 7 as well.

And it’s not too difficult for developers either.

Let me demonstrate it on a simple form I’ve built.


When you click the Upload button, a dialog opens where you can pick a file on your computer and upload it. It even shows progress of uploading.


The whole upload is triggered by a single statement: File::GetFileFromUser(). You don’t have to deal with any details.

By default, the file is uploaded to a temporary blob storage and can be accessed through some ugly URL such as this:


If you click the download button, it will navigate to the URL and your browser will do the rest:


Code of Download button is again a one-liner: new Browser().navigate(fileUrl).

This is the complete code of the form, showing also how to get the URL of the uploaded file:

public class UploadDownloadForm extends FormRun
    str fileUrl;
    class UploadButton
        public void clicked()
            FileUploadTemporaryStorageResult result = File::GetFileFromUser() as FileUploadTemporaryStorageResult;
            if (result && result.getUploadStatus())
                fileUrl = result.getDownloadUrl();
    class DownloadButton
        public void clicked()
            new Browser().navigate(fileUrl);

Your files typically aren’t accessible by URL, because they’re in database or in a secured storage. But that’s not a problem. Just load the content of your file to a stream and pass it to File::SendFileToUser(). It will put the file to the temporary blob storage and navigate to the URL, therefore users can download the file in the same way as above.

New X++ features in AX 7

X++ didn’t change much since I started to work with it eleven years ago, with a few exceptions such as event handlers in AX 2012.

That’s not true anymore in AX 7, because it comes with many new language constructs (and more are expected). If you’re familiar with modern object-oriented languages, and especially C#, you’ll find them very familiar, but some concepts will be completely new for many AX developers.

In general, X++ now utilizes many features supported by CIL and the syntax of new features closely follow C#, which is helpful for everyone who knows or is going to learn C#. To use the language correctly, you also have to be aware of some details of the runtime environment (CLR), such as how it handles garbage collection. You’ll find much more information written for C# developers than for X++ developers, therefore consider learning about common features from sources originally intended for C#.

Some new features help with implementation hiding and splitting the application to logical packages, which is really missing in AX these days (and AX7 isn’t the solution either, it’s just one more step in the right direction).

I’m not going to talk about every new feature, because you can already find that in AX7 wiki (Using X++ and debugger features) and mfp’s blog: (What is new in X++ in AX7?). Let me just mention a few things that I consider especially important or tricky.

Private member variables

This feature may not look very exciting, but is solves an important problem. Having all member variables protected (as in previous AX versions) means that any child class can access and change any variable defined in its parents. Classes often have member variables that they need for their own internal logic and that shouldn’t be exposed to anybody else.

Making variables private protects them from unexpected changes and it also make it easier for developers extending the class. For example, if a parent class has eight private fields and two protected, developers adding child classes have to about just two variables and not all ten. It’s obvious that the private ones aren’t intended for them.

Const and readonly

Const represents values that never change. It’s a simple concept, but it’s nice to have it in X++, instead of using variables (which doesn’t prevent changes) and macros (which don’t have type and are really ugly).

Readonly member variables are more interesting, because you can set their value when creating an object and they can’t change afterwards. It’s a common scenario but there was no way to enforce it in previous versions. It also allows you to create immutable objects.

Static member variables

Static fields (member variables) share certain values across all instances of a class. It’s useful in some cases, but it’s also very dangerous for several reasons. Please try to avoid them, especially if you don’t understand what these two points mean:

  • Static fields are often responsible for problems with memory allocation, when a static field refers to an object tree with a lot of data and the reference makes all these objects ineligible for garbage collection. If you have to make such a reference, weak references may help you in same cases.
  • If the field is used in more than a single thread, its value may change at any point (unless you introduce some type of locking). If you set a value to a static field a second ago, you still can’t be sure that some other thread didn’t already change it to something else. This may lead to bugs that are very difficult to reproduce. Multi-threading issues aren’t limited to static fields, but they’re common with them, because the same value is automatically shared by all threads.


Finally block can be used after try in a similar way as catch. Code inside finally executes regardless of whether code in try finished normally or it threw an exception. It’s usually used to clean up resources allocated in try block.

Note that it’s completely valid to use try/finally without any catch clause (because you have exception handling at some higher level or you simply can’t handle it in any way).

    throw error("It's broken!");
    info("Let's clean up everything");


This statement is in fact a shortcut for try/finally statement used for classes implementing IDisposable interface. It’s intended for releasing certain resources that CLR can’t manage automatically and that should be released as soon as possible (such as file handles). You want to be sure that regardless of happens (e.g. exception is thrown), you won’t leave a resource locked, memory allocated and so on. If the resource is wrapped in a class correctly implementing IDisposable and you instantiate the class with using, you’re safe.

You will meet the dispose pattern very often if you start using .NET types for streams, database queries and network communication, among others. Make sure that you correctly dispose all disposable objects, otherwise you can run out of database connections, for example. The using statement is here to make it easier for you.

Maybe you never needed anything like that before, but I think we’ll mix X++ and other .NET code much more often in AX 7, because it’s now so much easier, and therefore more developers will need this kind of knowledge.

Note that you technically can utilize using blocks for other purposes – all you need to implement IDisposable. The following example shows a custom class TimeMeasure used to measure how long does it take to execute code inside the using statement.

using (TimeMeasure m = new TimeMeasure())
    // Do something here

This is the implementation, which coincidentally shows several other new features in AX 7:

using System.Diagnostics;
class TimeMeasure implements System.IDisposable
    private Stopwatch stopwatch = Stopwatch::StartNew();
    public void Dispose()

The using block starts with creating an instance of the class, which initializes the member variable. And when the block ends, Dispose method is executed.

Please take it as a demonstration of how the statement works, not as an encouragement to misuse IDisposable on regular bases. This technique is useful in some cases, but they aren’t very common.

Notice that my code above uses using in another context: using System.Diagnostics. That’s a completely unrelated thing, they merely use the same keyword.

Extension methods

Extensions methods provide a way to pretend that you added an instance method to a class, table, view or map without actually changing it.

For example, let’s say that I want a method to convert a list to a set. I can’t change the List class (because it’s defined in AX kernel), but I can easily write a static method doing the conversion for me.

Set set = List_Extension::toSet(list);

It works, but it’s not easy to read and you have to know about the existence of List_Extension class. I would prefer to do this instead:

Set set = list.toSet();

And this is exactly what extension methods make possible.

To be considered an extension method, the method (and the class in which it’s defined) must meet certain criteria, which you can find on AX7 wiki. I’ll rather show you the actual implementation of toSet():

public static class List_Extension
    public static Set toSet(List _list)
        //TODO: throw error if _list is null
        Set set = new Set(_list.typeId());
        ListEnumerator enumerator = _list.getEnumerator();
        while (enumerator.moveNext())
        return set;

Notice that it’s really just a static method that gets a list as its argument. It can’t access any non-public members as it could if it was an actual instance method added to the class.

Even if you have a class that you technically can change (unlike List in the example above), you still may want to use an extension method to avoid overlayering.

You don’t necessary have to create any extension method by yourself, but you must be at least aware of their existence. Otherwise you would wonder where certain methods come from.


These are really great additions to X++, aren’t they? And don’t forget that this is not an exhaustive list.