class_docstr: S3Output handles all alert dispatching for AWS S3
class_docstr_tok: ["S3Output","handles","all","alert","dispatching","for","AWS","S3"]
docstr: Send alert to an S3 bucket
  
  Organizes alert into the following folder structure:
      service/entity/rule_name/datetime.json
  The alert gets dumped to a JSON string
  
  Publishing:
      By default this output sends the current publication in JSON to S3.
      There is no "magic" field to "override" it: Simply publish what you want to send!
  
  Args:
      alert (Alert): Alert instance which triggered a rule
      descriptor (str): Output descriptor
  
  Returns:
      bool: True if alert was sent successfully, False otherwise
code: def _dispatch(self, alert, descriptor):
      """Send alert to an S3 bucket
  
      Organizes alert into the following folder structure:
          service/entity/rule_name/datetime.json
      The alert gets dumped to a JSON string
  
      Publishing:
          By default this output sends the current publication in JSON to S3.
          There is no "magic" field to "override" it: Simply publish what you want to send!
  
      Args:
          alert (Alert): Alert instance which triggered a rule
          descriptor (str): Output descriptor
  
      Returns:
          bool: True if alert was sent successfully, False otherwise
      """
      bucket = self.config[self.__service__][descriptor]
  
      # Prefix with alerts to account for generic non-streamalert buckets
      # Produces the following key format:
      #   alerts/dt=2017-01-25-00/kinesis_my-stream_my-rule_uuid.json
      # Keys need to be unique to avoid object overwriting
      key = "alerts/dt={}/{}_{}_{}_{}.json".format(
          datetime.now().strftime("%Y-%m-%d-%H"),
          alert.source_service,
          alert.source_entity,
          alert.rule_name,
          uuid.uuid4(),
      )
  
      LOGGER.debug(
          "Sending %s to S3 bucket %s with key %s", alert, bucket, key
      )
  
      publication = compose_alert(alert, self, descriptor)
  
      client = boto3.client("s3", region_name=self.region)
      client.put_object(
          Body=json.dumps(publication), Bucket=bucket, Key=key
      )
  
      return True
  
imports: from abc import abstractmethod
  from collections import OrderedDict
  from email.mime.application import MIMEApplication
  from email.mime.multipart import MIMEMultipart
  from email.mime.text import MIMEText
  from datetime import datetime
  import json
  import uuid
  import backoff
  from botocore.exceptions import ClientError
  import boto3
  from streamalert.alert_processor.helpers import compose_alert, elide_string_middle
  from streamalert.alert_processor.outputs.output_base import OutputDispatcher, OutputProperty, StreamAlertOutput
  from streamalert.shared.backoff_handlers import backoff_handler, success_handler, giveup_handler
  from streamalert.shared.logger import get_logger
label_desc: Use image node_id 2 for calling the S3Output obj's underlying member method code with example usage: obj._dispatch(alert, descriptor) and returns: True