In this brief documentation for myself, I go over the process of sending GPG Encrypted emails in web2py. At the server level, there is a few things you need to do to install gnupgp and generate a public/private key with the email used for sending with web2py.
First you will need a few things via apt
sudo apt-get install gnupg rng-tools sudo rngd -r /dev/urandom
Then proceeding to create the public/private key pair.
su www-data export GNUPGHOME="/home/www-data/.gnupg" gpg --gen-key
You can now generate a public key for your users to import for decrypting your email messages.
gpg --output desiredFileName.gpg --export emailusedwithweb2py@thisSite.com
I had done this as root initially and it didn’t work properly. I think the www-data user did not have the necessary permissions because the export variable was left unset. In order to be able to use this I changed to the web2py server user
su www-data and set my environment variable properly
As a side note be sure that the user/group managing this gpg setup is the www-data user or whatever user is managing your web2py server.
chown -R www-data:www-data /home/www-data/.gnupg
However there is a few things necessary still and that is. In order for you to be able to send a message to someone with this functionality from your website, you need to have there public key in your key ring. As the www-data user you can see the keys in your key ring like this:
So the question is how do I get this to happen? I chose to have my users generate and upload their own public key file. Then in web2py I ran an os command to have my users public key file entered in to my key chain.
I did this by creating an onvalidation function that verifies that the files mimetype is set to a valid type for me to want to run an os.system call with. (This is accomplished by using the python magic library). Then on success of validation executing the gpg –import command from an os.system() call which imports my users public key in to my keychain.
def verify_upload_gpg(form): tmppath = os.path.join(request.folder, 'uploads', 'tmpupf%f.gpg' % random.random()) filename = form.vars.upload_gpg.file filepath = open(tmppath, 'wb') shutil.copyfileobj(filename, filepath) filepath.close() in_filename = str(tmppath) validate_type = magic.from_file(in_filename, mime=True) if validate_type != 'application/x-gnupg-keyring': form.errors.upload_gpg = T("Not a valid mimetype") else: os.system("gpg --import %s" % (in_filename)) def upload_gpg(form): form = SQLFORM(db.gpg_messages, formstyle='bootstrap') if form.process(onvalidation=verify_upload_gpg).accepted: session.flash = "Succesfully Installed Public GPG Email Key" return dict(form=form) elif form.errors: response.flash = 'Please correct the highlighted fields' return dict(form=form) else: return dict(form=form)
Then just to be sure in your server.
In my case I wanted to send a verification email prior so I ran the gpg settings in my controller for the emails I wished to send that are encrypted.
if form.accepts(request.vars, session): mail.settings.gpg_home = '/home/www-data/.gnupg' mail.settings.cipher_type = 'gpg' mail.settings.sign = True mail.settings.sign_passphrase = GPG_PASSPHRASE mail.settings.encrypt = True mail.send(to=EMAIL, subject='Access for file %s' % FILENAME, message='The key to decrypt this file %s is provided here: %s. We have also attached a python script to make the decryption for this file go that much easier.' % (FILENAME, form.vars.key), attachments = mail.Attachment(os.path.join(request.folder, 'static/emails/', 'script.py'))) if mail.error != None: session.flash = "Errors: %s" % (mail.error) else: session.flash = "An email with the AES Encryption Key has been sent to %s " % (EMAIL) return redirect(URL('default', 'index')) elif form.errors: response.flash = 'Please correct the highlighted fields' return dict(form=form) else: return dict(form=form)
And that is my setup with GNUPGP and web2py.