Example #1
0
 def moderate(self, msg):
     # For some reason, this import doesn't work at the file level.
     from control import sign
     message_id = msg['message-id']
     if not message_id:
         print(
             'Unable to moderate incoming message due to lack of Message-ID: header.'
         )
         raise ValueError('Messages must contain a Message-ID: header.')
     message_id = message_id.replace(
         ':', '_')  # Make it safe for subject-command.
     # Put the email message into the list's moderation holding space on S3.
     response = s3.put_object(
         Bucket=config.s3_bucket,
         Key=self._s3_moderation_prefix + message_id,
         Body=msg.as_string(),
     )
     # Get the moderation auto-deletion/auto-rejection interval from the S3 bucket lifecycle configuration.
     lifecycle = s3.get_bucket_lifecycle_configuration(
         Bucket=config.s3_bucket)
     from datetime import timedelta
     mod_interval = timedelta(
         days=next((r['Expiration']['Days']
                    for r in lifecycle.get('Rules', [])
                    if r['Prefix'] == config.s3_moderation_prefix), 3))
     # Wrap the moderated message for inclusion in the notification to mods.
     forward_mime = MIMEMessage(msg)
     control_address = 'lambda@{}'.format(self.host)
     for moderator in self.moderator_addresses:
         # Build up the notification email per-moderator so that we can include
         # pre-signed moderation commands specific to that moderator.
         approve_cmd = sign(
             'list {} mod approve "{}"'.format(self.address, message_id),
             moderator, mod_interval)
         reject_cmd = sign(
             'list {} mod reject "{}"'.format(self.address, message_id),
             moderator, mod_interval)
         message = MIMEMultipart()
         message['Subject'] = 'Message to {} needs approval: {}'.format(
             self.address, approve_cmd)
         message['From'] = control_address
         message['To'] = moderator
         message.attach(
             MIMEText(
                 templates.render('notify_moderators.jinja2',
                                  list_name=self.address,
                                  control_address=control_address,
                                  approve_command=approve_cmd,
                                  reject_command=reject_cmd,
                                  moderation_days=mod_interval.days)))
         message.attach(forward_mime)
         ses.send_raw_email(
             Source=control_address,
             Destinations=[
                 moderator,
             ],
             RawMessage={
                 'Data': message.as_string(),
             },
         )
Example #2
0
 def invite(self, target_address, command, verb):
     command_address = '{}@{}'.format(config.command_user, self.host)
     from datetime import timedelta
     validity_duration = timedelta(
         days=3)  # TODO: make this duration configurable
     token = control.sign(target_address,
                          self.address,
                          validity_duration=validity_duration)
     cmd = 'list {} {} "{}"'.format(self.address, command, token)
     list_name = self.name
     if not list_name:
         list_name = self.address
     control.send_response(
         source=command_address,
         destination=target_address,
         subject='Invitation to {} {} - Fwd: {}'.format(
             verb,
             list_name,
             control.sign(cmd,
                          target_address,
                          validity_duration=validity_duration),
         ),
         body=
         'To accept the invitation, reply to this email.  You can leave the body of the reply blank.',
     )
Example #3
0
    def moderate(self, msg):
        # For some reason, this import doesn't work at the file level.
        from control import sign

        message_id = msg["message-id"]
        if not message_id:
            print("Unable to moderate incoming message due to lack of Message-ID: header.")
            raise ValueError("Messages must contain a Message-ID: header.")
        message_id = message_id.replace(":", "_")  # Make it safe for subject-command.
        # Put the email message into the list's moderation holding space on S3.
        response = s3.put_object(
            Bucket=config.s3_bucket, Key=self._s3_moderation_prefix + message_id, Body=msg.as_string()
        )
        # Get the moderation auto-deletion/auto-rejection interval from the S3 bucket lifecycle configuration.
        lifecycle = s3.get_bucket_lifecycle_configuration(Bucket=config.s3_bucket)
        from datetime import timedelta

        mod_interval = timedelta(
            days=next(
                (
                    r["Expiration"]["Days"]
                    for r in lifecycle.get("Rules", [])
                    if r["Prefix"] == config.s3_moderation_prefix
                ),
                3,
            )
        )
        # Wrap the moderated message for inclusion in the notification to mods.
        forward_mime = MIMEMessage(msg)
        control_address = "lambda@{}".format(self.host)
        for moderator in self.moderator_addresses:
            # Build up the notification email per-moderator so that we can include
            # pre-signed moderation commands specific to that moderator.
            approve_cmd = sign('list {} mod approve "{}"'.format(self.address, message_id), moderator, mod_interval)
            reject_cmd = sign('list {} mod reject "{}"'.format(self.address, message_id), moderator, mod_interval)
            message = MIMEMultipart()
            message["Subject"] = "Message to {} needs approval: {}".format(self.address, approve_cmd)
            message["From"] = control_address
            message["To"] = moderator
            message.attach(
                MIMEText(
                    templates.render(
                        "notify_moderators.jinja2",
                        list_name=self.address,
                        control_address=control_address,
                        approve_command=approve_cmd,
                        reject_command=reject_cmd,
                        moderation_days=mod_interval.days,
                    )
                )
            )
            message.attach(forward_mime)
            ses.send_raw_email(
                Source=control_address, Destinations=[moderator], RawMessage={"Data": message.as_string()}
            )
Example #4
0
    def invite(self, target_address, command, verb):
        command_address = "{}@{}".format(config.command_user, self.host)
        from datetime import timedelta

        validity_duration = timedelta(days=3)  # TODO: make this duration configurable
        token = control.sign(target_address, self.address, validity_duration=validity_duration)
        cmd = 'list {} {} "{}"'.format(self.address, command, token)
        list_name = self.name
        if not list_name:
            list_name = self.address
        control.send_response(
            source=command_address,
            destination=target_address,
            subject="Invitation to {} {} - Fwd: {}".format(
                verb, list_name, control.sign(cmd, target_address, validity_duration=validity_duration)
            ),
            body="To accept the invitation, reply to this email.  You can leave the body of the reply blank.",
        )