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.

ProvidersSetup

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).

SMTPSetup

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.setFrom("robot@contoso.com");
builder.addTo("primus@contoso.com");
builder.addTo("helena@contoso.com");
builder.setSubject("Test");
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()
    .setFrom("robot@contoso.com")
    .addTo("primus@contoso.com")
    .addTo("helena@contoso.com")
    .setSubject("Test")
    .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:

SysMailerFactory::getNonInteractiveMailer().sendNonInteractive(message);

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

smtp4dev

Now let’s try an interactive mailer.

SysMailerFactory::getInteractiveMailer().sendInteractive(message);

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:

InteractiveSelection

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

NativeEditor

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;
 
#define.SysMailerMyOwn_ID('MyOwn')
 
[ExportAttribute(identifierStr(Dynamics.AX.Application.SysIMailer)),
 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.

MyOwnProvider

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.

11 Comments

  1. Very well article. Helped a lot developing and learning functionality. Keep Rocking. 🙂

  2. Wondering if we can use SysOuthgoingEmailTable, SysOutgoingEmailData and than use Batch process to send email in D365 or not.

    • Yes, it should work. SysEmailDistributor reads records from SysOutgoingEmailTable and sends emails by a non-interactive mailer (explained in the blog post).

  3. HI Martin,
    I have configured smtp and Emails are sending in reports.now i need to send notification by code, but i have faced the following error.

    “ Exchange server could not be contacted. Security token could not be obtained. Ensure a valid Office 365 license is available for this tenant.”

    Thanks in advance
    Prabu

    • I know nothing about what you’re doing except of what I can read in the error message. It seems that you’re trying to send emails through Office 365 and you have some problem wuth authorization.
      Consider creating a thread in a discussion forum (such as https://community.dynamics.com/ax/f/33/) and explaining your situation in detail there.

  4. Martin,
    How can we render a report , generate pdf and attach it to the email?
    Can you pls help me out here.

    • Yes, it’s possible. The easiest way is simply setting the target for printing (printMediumType(SRSPrintMediumType::Email), emailAttachmentFileFormat(SRSReportFileFormat::PDF)).

  5. How can I attach multiple attachments while sending mail to the customer/Vendor?

Comments are closed.