注意:

在 OCI 监视中为 Oracle Cloud Infrastructure Events 设置电子邮件通知

简介

Oracle Cloud Infrastructure (OCI) 服务发出事件,这些事件是指示资源更改的结构化消息。需要创建规则才能处理事件,并指定在找到匹配事件时要触发的操作。

电子邮件通知操作是您为事件匹配定义的响应。OCI 电子邮件传送服务提供了快速可靠的托管解决方案,用于发送安全、大量和事务性电子邮件通知。

目标

先决条件

Oracle Cloud Infrastructure Identity and Access Management (OCI IAM) 管理员应创建:

有关已订阅和首选电子邮件传送区域的更多信息,请参见 Configuring SMTP Connection Endpoint

任务 1:在电子邮件传送中配置批准的发件人

必须为通过 OCI 发送邮件的所有“发件人:”地址设置批准的发件人。它与区间关联,并且仅存在于配置了批准发件人的区域中。

如下所述,您可以对批准的发件人使用域名或默认 oracle 通知。

  1. 打开 OCI 控制台的导航菜单,然后单击开发人员服务

  2. 在 "Application Integration" 下,单击 Email Delivery

  3. 在“电子邮件传送”下,单击批准的发件人

  4. 单击创建批准的发件人,然后输入要作为批准的发件人列出的电子邮件地址

    :如果 OCI 电子邮件传送 SMTP 连接端点是 smtp.email.ap-mumbai-1.oci.oraclecloud.com,则将 noreply@notification 添加到区域,然后输入批准的发件人电子邮件地址。例如,noreply@notification.ap-mumbai-1.oci.oraclecloud.com

  5. 单击添加可将电子邮件地址添加到“批准的发件人”列表中。

任务 2:创建标记名称空间和密钥定义

  1. 打开导航菜单,然后单击监管和管理

  2. 在“租户管理”下,单击标记名称空间

  3. 在“标记名称空间”页上,单击创建标记名称空间

  4. 在“创建标记名称空间”面板中,选择相应的区间并在名称空间名称中键入 custom 并提供说明

  5. custom 名称空间上,单击创建标记键定义,然后在标记键中键入 recipient 并创建它。

    :可以在需要通知的每个 OCI 资源中将收件人电子邮件地址添加到定义的标记。该解决方案将使用 recipient addresses 通知(如果在云事件中可用),否则将在函数配置中使用 defaultrecepient 地址。例如,demouser1@abc.com、demouser2@abc.com

任务 3:在 OCI Vault 中创建密钥

  1. 打开 navigation(导航)菜单,单击 Identity & Security(身份和安全性),然后单击 Vault(Vault)

  2. 在列表范围下,选择包含 Vault 的区间

    :如果需要创建新的 Vault 和主加密密钥,请按照创建 Vault主加密密钥中的说明操作。

  3. 在“资源”下,单击创建密钥并选择相应的主加密密钥。

    • 在名称字段中输入 smptppass 和说明 SMTP password for OCI email delivery Authentication

    • 为密钥类型模板选择 plain-text 格式,然后输入 smtp password 以获取密钥的内容。

      :使用 OCI IAM 管理员共享的 SMTP 密码。

任务 4:创建和部署 OCI 函数

  1. 在 OCI 控制台上,单击顶部导航中的 Cloud Shell

  2. 使用云 shell 中的 Fn 项目 CLI 创建函数

    fn init --runtime python <function-name>
    
    Example: fn init --runtime python emaildelivery-func
    
  3. 将目录更改为新创建的目录。

  4. 创建应用程序以部署函数。

    # 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....."]'
    
  5. 通过覆盖现有内容,在 func.py 文件中复制并粘贴以下脚本。

    # 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"})
    
  6. 您可以在脚本中将 companylogo.png 替换为公司徽标,并将 HTML 文本更新为电子邮件正文。默认值为 Oracle 徽标。

  7. 运行以下命令以部署函数。

    fn -v deploy --app <app-name>
    
    Example: fn -v deploy --app emaildeliveryapp
    
  8. 在下面执行,为每个配置键和值添加函数配置。

    • 发件人:使用在任务 1 中配置的已批准发件人。

    • smtpuser:OCI IAM 管理员共享的 SMTP 用户。

    • smtppass:使用 SMTP 密码 Vault 密钥的 OCID 并更新 smtppass 配置值。

    • host:根据先决条件使用 SMTP 连接端点。

    • defaultrecipient:提供电子邮件地址作为默认收件人。该解决方案将使用 _recipient addresses_ 通知(如果在云事件中可用),否则将在功能配置中使用 _defaultrecepient_ 地址。

    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
    

任务 5:创建事件规则

  1. 打开导航菜单,然后单击可观察性和管理

  2. 在“事件服务”下,单击规则

  3. 单击创建规则,然后在“创建规则”面板中,提供规则的友好名称和规则的说明

  4. 规则条件区域中,指定事件类型和触发函数的操作。您可以基于事件类型、属性和标记定义筛选器,以限制触发操作的事件。下面是触发计算实例启动或停止事件的示例。

    计算实例事件规则

任务 6:验证电子邮件通知

  1. 在创建了事件规则以触发 OCI 事件的区间中启动或停止计算实例。

  2. 您将收到电子邮件友好通知,并附加了原始 JSON。

    电子邮件通知

确认

作者 - Dipesh Kumar Rathod(基础设施首席云架构师)

更多学习资源

探索 docs.oracle.com/learn 上的其他实验室,或者访问 Oracle Learning YouTube 频道上的更多免费学习内容。此外,请访问 education.oracle.com/learning-explorer 成为 Oracle Learning Explorer。

有关产品文档,请访问 Oracle 帮助中心