If you have reviewed some of my other posts here on automationpro.co.uk, you will know that I’m a fan of the ABX functionality in vRA8. Something that I have been wanting to accomplish for a while is sending an email from an ABX. There are some awesome posts out there on how to do this with public providers, such as Gmail or using Amazons Simple Email Service (SES) as documented in this great post. The problem I have with these methods is the reliance on using an external email provider service. I really wanted to send an email using an internal MS Exchange Server that I have in my lab environment. I won’t lie, this took quite a few late nights to get right and I attempted to use multiple python libraries, but in the end this is what worked for me.
What do you need?
- An internal MS Exchange server – I used MS Exchange 2019
- Credentials to login to the MS Exchange server with
- The code below, ensuring that the required action constants are configured correctly.
# Email via MS exchangelib # Tested using MS Exchange 2019 server # Provided by Paul E Davey # Learn more at https://automationpro.co.uk # # Required Dependencies # exchangelib==4.6.0 # python-dateutil # # Default inputs # Type Name Value # Action Constant smtpServer The FQDN to the exchange server # Action Constant smtpSender Email address of the sender (who we are sending an email from) # Action Constant smtpLoginUsername The username to use to connect to the SMTP / Exchange server with # Action Constant smtpLoginPassword Password for the smtpLoginUsername account def handler(context, inputs): from exchangelib import DELEGATE, Configuration, Message, Mailbox, Credentials, Account, EWSTimeZone, UTC_NOW from dateutil.tz import gettz from exchangelib.protocol import BaseProtocol, NoVerifyHTTPAdapter # Tell exchangelib to use this adapter class instead of the default # In my lab environment I do not have a valid HTTPS certificate installed on my MS Exchange 2019 server # The following line works around this issue by ignoring the certification validation BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter # Credentials to connect to the SMTP server with credentials = Credentials( username = inputs["smtpLoginUsername"], password = context.getSecret(inputs["smtpLoginPassword"]) ) # Configuration for the SMTP connection config = Configuration( server=inputs["smtpServer"], credentials=credentials ) # Account settings for the SMTP connection acc = Account( primary_smtp_address = inputs["smtpSender"], config = config, autodiscover = False, access_type = DELEGATE, default_timezone = EWSTimeZone.timezone('/'.join(gettz('Europe/London')._filename.split('/')[-2:])) ) # Construct the email message (sibject and body) that you wish to send msg = Message( account=acc, folder=acc.sent, subject='E-mail from vRA ABX Action', body='This email was produced by an ABX action and sent to you via the specified MS Exchange Server', to_recipients=[Mailbox(email@example.com')] ) # Send the message msg.send_and_save()
Create 4 action constants to hold sensitive information. Example values are shown in the table below (password redacted!)
The action requires the Action Constants to be added as inputs. Add each of the action constants as an input for the ABX action. You will need to select Action constant in the Type dropdown to be able to find them.
Two dependencies are required as shown below. It is important to specify the version of exchangelib as later versions have a conflict within the ABX execution environment.
You can setup an event subscription to trigger the action to execute. Obviously, other inputs can be added to allow you to send useful information such as on completion of a deployment. And yes, you could do this in vRO, but where would the fun be in that!