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(), }, )
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.', )
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()} )
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.", )