96 lines
3.2 KiB
Python
96 lines
3.2 KiB
Python
from email.mime.multipart import MIMEMultipart
|
|
from email.mime.text import MIMEText
|
|
from email.mime.image import MIMEImage
|
|
from email.mime.application import MIMEApplication
|
|
from email.utils import formatdate
|
|
|
|
import smtplib
|
|
from pretty_bad_protocol import gnupg
|
|
|
|
import flask
|
|
#import poobrains
|
|
from poobrains import app
|
|
|
|
def getgpg():
|
|
return gnupg.GPG(binary=app.config['GPG_BINARY'], homedir=app.config['GPG_HOME'])
|
|
|
|
|
|
class MailError(Exception):
|
|
pass
|
|
|
|
|
|
class Mail(MIMEMultipart):
|
|
|
|
fingerprint = None
|
|
crypto = None
|
|
|
|
def __init__(self, fingerprint=None, **kwargs):
|
|
|
|
MIMEMultipart.__init__(self, **kwargs)
|
|
self.fingerprint = fingerprint
|
|
self.crypto = getgpg()
|
|
self['From'] = app.config['SMTP_FROM']
|
|
self['Date'] = formatdate()
|
|
|
|
|
|
def as_string(self, unixfrom=False):
|
|
|
|
fingerprint = str(self.fingerprint) # TODO: enforce str by implementing __setattr__?
|
|
|
|
wrapper_msg = MIMEMultipart(_subtype='encrypted', protocol='application/pgp-encrypted')
|
|
wrapper_msg['From'] = self['From']
|
|
wrapper_msg['To'] = self['To']
|
|
wrapper_msg['Subject'] = self['Subject']
|
|
wrapper_msg['Date'] = self['Date']
|
|
|
|
pgp_info = MIMEApplication(b"Version: 1\n", _subtype='pgp-encrypted', _encoder=lambda x: str(x))
|
|
pgp_info['Content-Disposition'] = 'attachment'
|
|
wrapper_msg.attach(pgp_info)
|
|
|
|
self_string = MIMEMultipart.as_string(self, unixfrom=unixfrom)
|
|
|
|
crypto_kw = {
|
|
'symmetric': False # IIUC symmetric=True makes us at risk for leaking private keys
|
|
}
|
|
|
|
if app.config['GPG_PASSPHRASE'] is not None and \
|
|
app.config['GPG_SIGNKEY'] is not None:
|
|
crypto_kw['passphrase'] = app.config['GPG_PASSPHRASE']
|
|
crypto_kw['default_key'] = app.config['GPG_SIGNKEY']
|
|
|
|
ciphertext = str(self.crypto.encrypt(self_string, str(self.fingerprint), **crypto_kw))
|
|
if ciphertext != '':
|
|
pgp_attachment = MIMEApplication(ciphertext, _encoder=lambda x: str(x))#, _subtype='octet-stream')
|
|
wrapper_msg.attach(pgp_attachment)
|
|
|
|
return wrapper_msg.as_string(unixfrom=unixfrom)
|
|
|
|
|
|
if hasattr(cryptinfo.stderr):
|
|
app.logger.error("Problem encrypting mail. stderr follows.")
|
|
app.logger.error(cryptinfo.stderr)
|
|
else:
|
|
app.logger.error("Problem encrypting mail. No further information.")
|
|
|
|
raise MailError("Problem encrypting mail.")
|
|
|
|
|
|
def send(self):
|
|
|
|
if not isinstance(self.fingerprint, str):
|
|
raise MailError('Trying to send mail without selecting public key fingerprint.')
|
|
|
|
if self['To'] is None:
|
|
raise MailError('Recipient for mail not set!')
|
|
|
|
if app.config['SMTP_STARTTLS']:
|
|
smtp = smtplib.SMTP(app.config['SMTP_HOST'], port=app.config['SMTP_PORT'])
|
|
smtp.starttls() # FIXME: We'll want to check if this actually worked
|
|
|
|
else:
|
|
smtp = smtplib.SMTP_SSL(app.config['SMTP_HOST'], port=app.config['SMTP_PORT'])
|
|
|
|
smtp.ehlo()
|
|
smtp.login(app.config['SMTP_ACCOUNT'], app.config['SMTP_PASSWORD'])
|
|
smtp.sendmail(self['From'], self['To'], self.as_string())
|