Note:
- This tutorial requires access to Oracle Cloud. To sign up for a free account, see Get started with Oracle Cloud Infrastructure Free Tier.
- It uses example values for Oracle Cloud Infrastructure credentials, tenancy, and compartments. When completing your lab, substitute these values with ones specific to your cloud environment.
Set Up Email Notifications for Oracle Cloud Infrastructure Events in OCI Monitoring
Introduction
Oracle Cloud Infrastructure (OCI) services emit events, which are structured messages that indicate changes in resources. It is required to create rules to work with events and also specify an action to trigger when it finds a matching event.
Email notification actions is a response which you define for event matches. OCI email delivery service provides a fast and reliable managed solution for sending secured, high-volume and transactional email notifications.
Objectives
- Send email friendly OCI event notification using OCI Email Delivery.
Prerequisites
Oracle Cloud Infrastructure Identity and Access Management (OCI IAM) administrator should create:
-
Dynamic group and policies for OCI function to invoke and send email notification.
-
Dynamic Group
Create dynamic group for function compartment.
# Replace OCID for function compartment All {resource.type = 'fnfunc', resource.compartment.id = '<function-compartment>'} Example: All {resource.type = 'fnfunc', resource.compartment.id = 'ocid1.compartment.oc1..aaaaaaaanovmfmmnonjjyxeq4jyghszj2eczlrkgj5svnxrt...'}
-
Policies
Create policies to assign dynamic group for function.
# Replace dynamic-group-name, function-compartment and OCID of vault secret for OCI function Allow dynamic-group <dynamic-group-name> to read secret-family in compartment <function-compartment> where target.secret.id='<ocid of smtp password vaultsecret>' Allow dynamic-group <dynamic-group-name> to inspect compartments in tenancy Allow dynamic-group <dynamic-group-name> to read repos in compartment <function-compartment>
-
-
Simple Mail Transfer Protocol (SMTP) Service Account with limited user capability to
SMTP credentials
only. Generate and share the SMTP credential with the developer. -
Compartment, group and policies for developer to create secrets and deploy the function.
# Replace group-name as per your tenancy Allow group <group-name> to manage repos in compartment <function-compartment> Allow group <group-name> to manage vaults in compartment <function-compartment> Allow group <group-name> to manage keys in compartment <function-compartment> Allow group <group-name> to manage secret-family in compartment <function-compartment> Allow group <group-name> to manage approved-senders in compartment <function-compartment> allow group <group-name> to use cloud-shell in tenancy allow group <group-name> to manage functions-family in compartment <function-compartment> allow group <group-name> to use virtual-network-family in compartment <network-compartment> Allow group <group-name> to read objectstorage-namespaces in tenancy
For more information about subscribed and preferred email delivery region, see Configuring SMTP Connection Endpoint.
Task 1: Configure approved sender in email delivery
An approved sender must be set up for all “From:” addresses sending mail through OCI. It is associated with a compartment and only exists in the region where the approved sender was configured.
You can use your domain name or default oracle notification for approved sender as mentioned below.
-
Open the navigation menu of OCI Console and click Developer Services.
-
Under Application Integration, click Email Delivery.
-
Under Email Delivery, click Approved Senders.
-
Click Create Approved Sender and enter the email address that you want to list as an approved sender.
Note: If your OCI email delivery SMTP connection endpoint is
smtp.email.ap-mumbai-1.oci.oraclecloud.com
then addnoreply@notification
to region and enter in approved sender email address. For example,noreply@notification.ap-mumbai-1.oci.oraclecloud.com
. -
Click Add to add email address to your Approved Senders list.
Task 2: Create Tag namespace and key definition
-
Open the navigation menu and click Governance & Administration.
-
Under Tenancy Management, click Tag Namespaces.
-
On the Tag Namespaces page, click Create Tag Namespaces.
-
In the Create Tag Namespace panel, select the appropriate compartment and type custom in namespace name and provide description.
-
On custom namespace, click Create Tag Key Definitions and type recipient in Tag key and create it.
Note: You can add the recipient email addresses to the defined tag in each OCI resource, where notification required. The solution will use
recipient addresses
to notify, if available in Cloud event, elsedefaultrecepient
address will be used specified in function configuration. For example, demouser1@abc.com,demouser2@abc.com
Task 3: Create secret in OCI vault
-
Open the navigation menu, click Identity & Security, and then click Vault.
-
Under List scope, select a compartment that contains the vault.
Note: If you need to create a new vault and master encryption key, follow the instructions in Create Vault and Master Encryption Key.
-
Under Resources, click Create Secret and select appropriate master encryption key.
-
Enter smptppass in name field and description SMTP password for OCI email delivery authentication.
-
Select the format plain-text for Secret Type Template and enter smtp password, for contents of the secret.
Note: Use SMTP password shared by OCI IAM admin.
-
Task 4: Create and deploy OCI function
-
On OCI console, click Cloud Shell in the top navigation.
-
Create function using Fn project CLI from cloud shell.
fn init --runtime python <function-name> Example: fn init --runtime python emaildelivery-func
-
Change directory to the newly created directory.
-
Create app to deploy the function.
# Specify the OCID of subnet fn create app emaildeliveryapp --annotation oracle.com/oci/subnetIds='["<subnet OCID>"]' Example: fn create app emaildeliveryapp --annotation oracle.com/oci/subnetIds='["ocid1.subnet.oc1.ap-mumbai-1.aaaaaaaabitp32dkyox37qa3tk3evl2nxivwb....."]'
-
Copy and paste below script in the
func.py
file by overwriting the existing content.# python script for sending SMTP configuration with Oracle Cloud Infrastructure Email Delivery import io import json import logging import oci from fdk import response import smtplib import email.utils import ssl import base64 from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase # Get Resource Principal Credentials signer = oci.auth.signers.get_resource_principals_signer() # Get instance principal context secret_client = oci.secrets.SecretsClient(config={}, signer=signer) identity_client = oci.identity.IdentityClient(config={}, signer=signer) tenancy_data = identity_client.get_tenancy(tenancy_id=signer.tenancy_id).data t_name = str(tenancy_data.name) t_id = signer.tenancy_id # Retrieve secret def read_secret_value(secret_client, secret_id): response = secret_client.get_secret_bundle(secret_id) base64_Secret_content = response.data.secret_bundle_content.content base64_secret_bytes = base64_Secret_content.encode('ascii') base64_message_bytes = base64.b64decode(base64_secret_bytes) secret_content = base64_message_bytes.decode('ascii') return secret_content # Sender name sendername = 'noreply' # If you're using Email Delivery in a different region, replace the HOST value with an appropriate SMTP endpoint. # Use port 25 or 587 to connect to the SMTP endpoint. port = 587 # Reading company logo information in base64 encoded with open("companylogo.png", "rb") as image_file: image_data = base64.b64encode(image_file.read()) image_data = '<img src="data:image/png;base64,'+str(image_data)[2:]+'" alt="company logo" />' def handler(ctx, data: io.BytesIO=None): try: # Extracting function config values cfg = ctx.Config() smtp_user = cfg["smtpuser"] host = cfg["host"] sender = cfg["sender"] smtp_defrec = cfg["defaultrecipient"] smtp_pass = cfg["smtppass"] # Secrets from vault smtp_pass = read_secret_value(secret_client, secret_id=smtp_pass ) # Extracting values from triggered OCI event body = json.loads(data.getvalue()) e_Type = body.get("eventType") e_time = body.get("eventTime") r_name = body["data"]["resourceName"] c_id = body["data"]["compartmentId"] c_name = body["data"]["compartmentName"] r_id = body["data"]["resourceId"] add_detail = "" try: # Extracting additional details from OCI event details = body["data"]["additionalDetails"] for key, value in details.items(): add_detail = add_detail+str(key)+' : '+str(value)+'<br>' except (Exception, ValueError) as ex: add_detail = "Additional details not available for this OCI event" try: # Extracting recepient details if available in OCI event recipient = body["data"]["definedTags"]["custom"]["recipient"] except Exception as e: recipient = smtp_defrec # Extract event type e_Type = e_Type.split('com.oraclecloud.')[1] # Extract region name r_id = r_id.split('.')[3] # The subject line of the email. SUBJECT = 'Event | '+ r_name + ' | ' + e_Type + ' | ' + e_time BODY_HTML = """\ <html> <head></head> <body> """ +str(image_data)+ """ <h2>Oracle Cloud Notification</h2> <hr> <b>Event Time : </b>""" +str(e_time)+ """ <br> <b>Event Type : </b>""" +str(e_Type)+ """ <br> <b>Tenancy Name : </b>""" +str(t_name)+ """ <br> <b>Tenancy ID : </b>""" +str(t_id)+ """ <hr> <b>Resource Name : </b>""" +str(r_name)+ """ <br> <b>Region Name : </b>""" +str(r_id)+ """ <br> <b>Compartment ID : </b>""" +str(c_id)+ """ <br> <b>Compartment Name : </b>""" +str(c_name)+ """ <hr> <b>Details : </b><br>""" +str(add_detail)+ """ <hr> <br> <p> Thank you, <br> The OCI team <br><br><br> Please do not reply directly to this email. This mailbox is not monitored. If you have any questions regarding this notification, contact your account administrator. <br> </p> </body> </html> """ # create message container msg = MIMEMultipart() msg['Subject'] = SUBJECT msg['From'] = email.utils.formataddr((sendername, sender)) msg['To'] = recipient # Attach HTML body for email msg.attach(MIMEText(BODY_HTML, 'html')) # Attach JSON payload as attachement attach_file = json.dumps(body,indent=2) payload = MIMEBase('application', 'octate-stream') payload.set_payload(attach_file) payload.add_header('Content-Disposition', 'attachment', filename='event_output.json') msg.attach(payload) # Try to send the message. server = smtplib.SMTP(host, port) server.ehlo() # most python runtimes default to a set of trusted public CAs that will include the CA used by OCI Email Delivery. # However, on platforms lacking that default (or with an outdated set of CAs), customers may need to provide a capath that includes our public CA. server.starttls(context=ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH, cafile=None, capath=None)) # smtplib docs recommend calling ehlo() before & after starttls() server.ehlo() server.login(smtp_user, smtp_pass) # our requirement is that SENDER is the same as From address set previously server.sendmail(sender, recipient, msg.as_string()) server.close() # Display an error message if something goes wrong. except (Exception, ValueError) as ex: logging.getLogger().info('error parsing json payload: ' + str(ex)) return response.Response(ctx, response_data=json.dumps({"message": "success"}),headers={"Content-Type": "application/json"})
-
You could replace companylogo.png with your company logo and update HTML text as email body in script. Default is Oracle logo.
-
Run below command to deploy the function.
fn -v deploy --app <app-name> Example: fn -v deploy --app emaildeliveryapp
-
Execute below to add function configuration for each config key and value.
-
sender: Use approved sender configured in Task 1.
-
smtpuser: SMTP user shared by OCI IAM admin.
-
smtppass: Use OCID of SMTP password vault secret and update in smtppass config value.
-
host: Use SMTP connection endpoint as per prerequisite.
-
defaultrecipient: Provide email address as default recipient. The solution will use
_recipient addresses_
to notify, if available in Cloud event, else_defaultrecepient_
address will be used in function configuration.
fn config function <app-name> <function-name> <config-key> <config-value> Example: fn config function emaildeliveryapp emaildelivery-func sender noreply@notification.ap-mumbai-1.oci.oraclecloud.com
-
Task 5: Create event rule
-
Open the navigation menu and click Observability & Management.
-
Under Events Service, click Rules.
-
Click Create Rule and in the Create Rule panel, provide a friendly name for the rule and a description of what the rule does.
-
In the Rule Conditions area, specify event type and action to trigger function. You can define filters based on event types, attributes, and tags to limit the events that trigger actions. Below is example to trigger compute instance start or stop event.
Task 6: Validate email notification
-
Start or stop the compute instance in compartment where event rule was created to trigger the OCI event.
-
You will receive email friendly notification, along with raw JSON attached to it.
Related Links
Acknowledgments
Author - Dipesh Kumar Rathod (Master Principal Cloud Architect, Infrastructure)
More Learning Resources
Explore other labs on docs.oracle.com/learn or access more free learning content on the Oracle Learning YouTube channel. Additionally, visit education.oracle.com/learning-explorer to become an Oracle Learning Explorer.
For product documentation, visit Oracle Help Center.
Set Up Email Notifications for Oracle Cloud Infrastructure Events in OCI Monitoring
F87596-01
October 2023
Copyright © 2023, Oracle and/or its affiliates.