def encrypt_message(self, message): to_encrypt = self.get_base_message(message) backend = self.get_backend() control_msg = backend.get_control_message() encrypted_msg = backend.get_octet_stream( to_encrypt, recipients=self.gpg_recipients, signer=self.gpg_signer) if isinstance(message, SafeMIMEMultipart): message.set_payload([control_msg, encrypted_msg]) message.set_param('protocol', self.protocol) message.set_type('multipart/encrypted') return message gpg_msg = SafeMIMEMultipart(_subtype='encrypted', encoding=message.encoding) gpg_msg.attach(control_msg) gpg_msg.attach(encrypted_msg) # copy headers for key, value in message.items(): if key.lower() in ['Content-Type', 'Content-Transfer-Encoding']: continue gpg_msg[key] = value gpg_msg.set_param('protocol', self.protocol) return gpg_msg
def message(self): # If neither encryption nor signing was request, we just return the normal message orig_msg = super(GPGEmailMessage, self).message() if not self.encrypted and not self.signed: return orig_msg encoding = self.encoding or settings.DEFAULT_CHARSET signers = self.gpg_signers recipients = self.gpg_recipients context = self.gpg_context if isinstance(orig_msg, MIMEMultipart): to_encrypt = MIMEMultipart(_subtype='alternative', _subparts=orig_msg.get_payload()) else: # No attachments were added to_encrypt = orig_msg.get_payload() msg = rfc3156(to_encrypt, recipients=recipients, signers=signers, context=context, always_trust=self.gpg_always_trust) # if this is already a Multipart message, we can just set the payload and return it if isinstance(orig_msg, MIMEMultipart): orig_msg.policy = orig_msg.policy.clone(max_line_length=0) orig_msg.set_payload(msg.get_payload()) orig_msg.set_param('protocol', self.protocol) # Set the micalg Content-Type parameter. Only present in messages that are only signed # TODO:We don't yet know how to get the correct value, we just return GPGs default if self.encrypted is False: orig_msg.set_param('micalg', 'pgp-sha256') return orig_msg # This message was not a multipart message, so we create a new multipart message and attach # the payload of the signed and/or encrypted payload. body, sig = msg.get_payload() gpg_msg = SafeMIMEMultipart(_subtype=self.alternative_subtype, encoding=encoding) gpg_msg.attach(body) gpg_msg.attach(sig) for key, value in orig_msg.items(): if key.lower() in ['Content-Type', 'Content-Transfer-Encoding']: continue gpg_msg[key] = value # TODO: We don't yet know how to get the correct value if self.encrypted is False: gpg_msg.set_param('micalg', 'pgp-sha256') gpg_msg.set_param('protocol', self.protocol) return gpg_msg
def sign_message(self, message, **kwargs): to_sign = self.get_base_message(message) backend = self.get_backend() if isinstance(message, SafeMIMEMultipart): # We have to adjust the policy because Django SOMEHOW adjusts the line-length of # multipart messages. This means a line-break in the Content-Type header of to_sign # gets removed, and this breaks the signature. to_sign.policy = to_sign.policy.clone(max_line_length=0) # get the gpg signature signature = backend.sign(to_sign.as_bytes(linesep='\r\n'), self.gpg_signer) signature_msg = backend.get_mime_signature(signature) if isinstance(message, SafeMIMEMultipart): message.set_payload([to_sign, signature_msg]) message.set_param('protocol', self.protocol) message.set_param('micalg', 'pgp-sha256') message.set_type('multipart/signed') return message gpg_msg = SafeMIMEMultipart(_subtype='signed', encoding=message.encoding) gpg_msg.attach(to_sign) gpg_msg.attach(signature_msg) # copy headers for key, value in message.items(): if key.lower() in ['Content-Type', 'Content-Transfer-Encoding']: continue gpg_msg[key] = value gpg_msg.set_param('protocol', self.protocol) gpg_msg.set_param('micalg', 'pgp-sha256') return gpg_msg