Monday, August 26, 2013

Sending E-mails from an Automation Object - Part 2

In Part 1 I discussed a script that allows your Galaxy to send e-mails through an SMTP server. The e-mail, while short and simple, was all contained within a single Execute script. This means that every single class used by the script is instantiated and initialized every time the script runs. Also, all the information that the script uses was hardcoded within the script itself.

Let's take advantage of the different execution types, UDAs, and the Declarations section to reshape the script into a better, optimized, and well-structured object. Details after the break.

While most of the original script will remain intact, we'll have to change a couple of lines and add more UDAs to optimize the execution of the object and make it more flexible by allowing you to change some of the information at runtime. BTW, I do love dot notation for attributes, so that's what I'll use here.

Just as the original script, we'll need a trigger for the script. You might want to change the subject and body of the e-mail message on runtime; a couple of string UDAs will do the trick. The way I see it, the sender account and e-mail address should always be the same, so it makes sense to have these hardcoded in the script. But the recipient might be different depending on the e-mail you are sending. Based on this, let's create the following UDAs:

Name Data Type Category
Email.Trigger Boolean User writeable
Email.To String User writeable
Email.Subject String User writeable
Email.Body String User writeable

Looking at the script in Part 1 , you might see that part of the data will not change from execution to execution. The SMTP server and port, the user credentials, and the sender's address will be the same all the time. Besides, creating and instantiating the corresponding objects every time the script runs takes time, time that the engine might not have. Also, we only need one e-mail message object; we can simply update its content each time we send an e-mail. So why don’t we move the corresponding code to the Startup section of the script? If we do this (and we will), then the declaration of the objects will need to be placed in the Declarations of the script so it can be shared between the Startup and the Execute sections.

Declarations section:
dim smtp as System.Net.Mail.SmtpClient;
dim emailMsg as System.Net.Mail.MailMessage;
OnStartup script:
' Initialize SMTP client.
smtp = new System.Net.Mail.SmtpClient("smtp.gmail.com", 587);
smtp.EnableSsl = true;
smtp.Credentials = new System.Net.NetworkCredential("username", "password");

' Initialize e-mail MESSAGE.
emailMsg = new System.Net.Mail.MailMessage();
emailMsg.From = new System.Net.Mail.MailAddress("username@gmail.com", Me.Tagname);
Notice that in this version of the script I omitted declaring a sender object and directly assigned the new MailAddress instance to the From property of the MailMessage object. We could have done this in the previous version of the script, but I thought it was easier to read and explain by declaring every component individually. But now that we know how the script works, we can start optimizing the code a little bit here and there. Also, in the last line of code, instead of hardcoding a display name for the sender, I use the automation object's instance name in case you have several instances in your Galaxy sending e-mails.

The rest of the script stays in the Execute section with the same trigger as before:
  • Expression: Me.Email.Trigger
  • Trigger type: On True

' TO address.
dim recipient as System.Net.Mail.MailAddress;
recipient = new System.Net.Mail.MailAddress(Me.Email.To);

' Email MESSAGE.
emailMsg.To.Clear();
emailMsg.To.Add(recipient);
emailMsg.Subject = Me.Email.Subject;
emailMsg.Body = Me.Email.Body;

' Send e-mail.
smtp.SendMailAsync(emailMsg);

' Reset flag.
Me.Email.Trigger = false;
Adding the recipient's e-mail address is a bit different because the To property of the MailMessage class is a collection of MailAddress objects (in case you want to send the e-mail to multiple addresses). We need to clear the collection before adding the new e-mail address, otherwise the e-mail message will also be send to all previous recipients.

As in Part 1 , the SMTP account, user name and password information is hardcoded within the script. Anybody with access to the script will have access to the SMTP credentials. I wouldn't add these credentials as UDAs because then anybody with access to the runtime, like using Object Viewer, will be able to see the account information.

No comments:

Post a Comment