I just saw the other response and guess I never wrote up the solution I actually implemented. It turns out that python imaplib is straightforward and I wrote a very quick script. Barring a few changes (e.g., anonymizing my various USERNAMEs, EMAILPASSWORD, WORKDOMAINNAME, MYGPGKEYID). I also don't just send encrypted it; but prepend the subject with the username of the sender and put some of the header stuff before the GPG (in case I'm reading it on my phone and can't decrypt).
#!/usr/bin/python
import imaplib
import email
from datetime import datetime,timedelta
import shelve
from subprocess import Popen, PIPE
def piped_call(command1, arg1_list, command2, arg2_list):
"""
if arg1_tuple = (a10, a11, a12); arg2_tuple is (a20, a21)
This executes "command1 a10 a11 a12 | command2 a20 a21 a22"
"""
if type(arg1_list) not in (list, tuple):
arg1_list = [arg1_list,]
if type(arg2_list) not in (list, tuple):
arg2_list = [arg2_list,]
p1 = Popen([command1,]+list(arg1_list), stdout=PIPE)
p2 = Popen([command2,]+list(arg2_list), stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()
return p2.communicate()[0]
shlf = shelve.open('/home/USERNAME/mail/mail.shlf')
# This shelf (a persistent python dictionary written to file) has as its key
# the IMAP message ids of all emails that have been processed by this script.
# Every time the script runs, I fetch all emails from the current day
# (except from midnight to 1am, where I fetch all emails since yesterday)
# and then send all emails that haven't been sent previously
# by checking message ids against the python shelf.
M = imaplib.IMAP4_SSL(host='imap.WORKDOMAINNAME.com', port=993)
M.login('EMAILUSERNAME', 'EMAILPASSWORD')
M.select()
dt = datetime.now() - timedelta(0,5*60*60)
# Only search for messages since the day of an hour earlier.
# This way messages from yesterday don't get lost at midnight; as well as limiting the number of messages to process through to just todays.
typ, uid_data = M.uid('search', None, '(SINCE %s)' % dt.strftime('%d-%b-%Y'))
for num in uid_data[0].split():
typ, data = M.uid('fetch', num, '(RFC822)')
e = email.message_from_string(data[0][1])
print 'Message %s\n%s\n' % (num, e['subject'])
if num not in shlf:
sender_email = e['return-path']
for s in ('<', '>', '@WORKDOMAINNAME.com'):
sender_email = sender_email.replace(s,'')
subject = "%s: %s" % (sender_email, e['Subject'])
body = ("From: %s\n"
"To: %s\n"
"Cc: %s\n"
"Subject: %s\n\n" % (e['From'], e['To'], e['Cc'], e['subject']))
payload = e.get_payload()
if type(payload) in (list, tuple):
payload = str(payload[0])
else:
payload = str(payload)
encrypted_payload = piped_call('echo', (payload,),
'gpg', ('-e', '-a', '-r', 'MYGPGKEYID'))
body += encrypted_payload
piped_call('echo', (body,),
'mail', ['USERNAME@gmail.com', '-s', subject])
shlf[num] = datetime.now()
M.close()
M.logout()
I then added the following lines to my crontab (the script above is named mail.py inside a directory called mail), so it will run every 5 minutes during the normal hours on weekdays (M-F 8-7pm) and less frequently at other hours. (crontab -e)
# Every 5 minutes, M-F from 8am - 7pm.
*/5 8-19 * * 1-5 cd /home/USERNAME/mail && ./mail.py >> /home/USERNAME/mail/mail.log 2>&1
# Every 30 minutes, Sat&Sun from 8am-7pm
0,30 8-19 * * 6,7 cd /home/USERNAME/mail && ./mail.py >> /home/USERNAME/mail/mail.log 2>&1
# Every 30 minutes, M-F 8pm-2am; (no emails 2am-8am)
0,30 0-2,20-23 * * 1-5 cd /home/USERNAME/mail && ./mail.py >> /home/USERNAME/mail/mail.log 2>&1
# Every 60 minutes, Sat&Sun hours 8pm-2am; (no emails 2am-8am)
0 0-2,20-23 * * 6-7 cd /home/USERNAME/mail && ./mail.py >> /home/USERNAME/mail/mail.log 2>&1
In Keepass2, "Add Entry," and set "Title" to "GPG." Move from "Entry" tab to "Auto-Type" tab. Select "Override default sequence" and set to "{PASSWORD}".
Before you send email, open Keepass2 with Keepass2 password. Ask IceDove with Enigmail to "Send" and pinentry should appear (locking keyboard, preventing "Ctrl+V" (or any other keyboard shortcut you normally use to perform auto-type), preventing switch windows "Alt+Tab", etc.).
Use mouse to highlight "GPG" entry in Keepass2 and click "Perform Auto-Type" icon in Keepass2 (left of "Find" icon and underneath "Help" menu). As the keyboard "focus" was last on the pinentry text input box, Keepass2 will now start typing your long password for you.
Use mouse to click "OK" on pinentry. Done!
For more details on "Auto-Type" (http://keepass.info/help/base/autotype.html).
Best Answer
You can use GPG to symmetrically encrypt a file with a passphrase (
gpg -c
). If the passphrase has enough entropy, you don't need an extra step of generating a secret key. What does “enough entropy” mean? Your encryption needs to withstand offline attacks, where the attacker can make cracking attempts as fast as his hardware allows it. With a small PC farm, the attacker might be able to make a couple hundred billion attempts per second, which is roughly 2^69 per decade. So with an entropy of 2^70 you'll be safe. That means if your passphrase consists of completely random letters (lower or upper case) and digits, it should be 12 characters long.Now to store that passphrase, you can use GPG with its usual key pairs. Use
gpg --gen-key
to generate a key pair, andgpg -e
to encrypt the passphrase used to encrypt the large file for one or more key pairs.Here's a sketch on how to do the encryption (note that I avoid putting the passphrase on the command line or in the environment, so as to make sure another user can't find it by looking at the
ps
output while the command is running):and how to decrypt:
The reason to use a passphrase (a shared secret) rather than directly encrypt is that it allows the file to be shared between several people. Only the small passphrase needs to be reencrypted if you want to add a recipient (removing a recipient only makes sense if you know the recipient hasn't had access to the plaintext and requires reencoding the ciphertext anyway).