imapfwd: forward mail to a main box

I have several email addresses but I want all messages to arrive in a single mailbox. imapfwd connects to an imap server and forward all unread mails to an other address through SMTP. Here are the recognized options:

$ ./imapfwd --help
Usage: imapfwd [options] USERNAME IMAPHOST SMTPHOST DESTINATION

Options:
  -h, --help       show this help message and exit
  --pass=PASSWORD  imap password
  -p PORT          imap port
  --ssl            use SSL for imap
  --prefix=PREFIX  append a string to subject. ex: [box1]

I use the script in a cronjob. To set up the job, type crontab -e and add a line like this (I’ve saved the script in /home/pierre/bin/):

# m    h  dom mon dow   command
 */10  *   *   *   *    /home/pierre/bin/imapfwd --pass or4nge mylogin imap.hmail.com smtp.isp.com mainbox@fmail.com

Here is the script:

[download imapfwd]

#!/usr/bin/env python
 
# Copyright 2009 (C) Pierre Duquesne <stackp@online.fr>
# Licensed under the BSD Revised License.
 
import imaplib
import smtplib
import sys
import optparse
import getpass
import email.parser
 
USAGE="imapfwd [options] USERNAME IMAPHOST SMTPHOST DESTINATION" 
 
def parse_args():
    "Parse command-line arguments."
    parser = optparse.OptionParser(usage=USAGE)
    parser.add_option('--pass', dest='password', default=None,
                      help="imap password")
    parser.add_option('-p', dest='port', type='int', default=None,
                      help="imap port")
    parser.add_option('--ssl', dest='ssl', default=False, 
                      action='store_true',
                      help="use SSL for imap")
    parser.add_option('--prefix', dest='prefix', default=None, 
                      action='store',
                      help="append a string to subject. ex: [box1]")
    options, remainder = parser.parse_args(sys.argv[1:])
    return options, remainder
 
options, args = parse_args()
try:
    username = args[0]
    imaphost = args[1]
    smtphost = args[2]
    destination = args[3]
except:
    print "Error: some arguments are missing. Try --help."
    print USAGE
    sys.exit(1)
 
# connect to imap
print 'Connecting to %s as user %s ...' % (imaphost, username)
if options.ssl: 
    IMAP = imaplib.IMAP4_SSL
else:
    IMAP = imaplib.IMAP4
try:
    if options.port:  
        imap_server = IMAP(imaphost, options.port)
    else:     
        imap_server = IMAP(imaphost)
    if not options.password: 
        options.password = getpass.getpass()
    imap_server.login(username, options.password)
except Exception,e:
        print 'Error:', e;  sys.exit(1)
 
# connect to smtp
try:
    smtp_server = smtplib.SMTP(smtphost)
except Exception, e:
    print 'Could not connect to', smtphost, e.__class__, e
    sys.exit(2)
 
# filter unseen messages
imap_server.select("INBOX")
resp, items = imap_server.search(None, "UNSEEN")
numbers = items[0].split()
 
# forward each message
sender = "%s@%s" % (username, imaphost)
for num in numbers:
    resp, data = imap_server.fetch(num, "(RFC822)")
    text = data[0][1]
    if options.prefix:
        parser = email.parser.HeaderParser()
        msg = parser.parsestr(text)
        msg['Subject'] = options.prefix + msg['Subject']
        text = msg.as_string()
    smtp_server.sendmail(sender, destination, text)
    # Flag message as Seen (may have already been done by the server anyway)
    imap_server.store(num, '+FLAGS', '\\Seen')
 
imap_server.close()
smtp_server.quit()

file transfer with netcat

netcat lets you stream bytes over the network. When used with tar, you can transfer files and directories.

Say you have two computers — bam and boom — and you want to copy the ~/pictures/ directory from bam to boom.

First, on host boom:

netcat -l -q 0 -p 3000 | tar xzv

Second, on host bam:

tar czv ~/pictures/ | nc -q 0 boom 3000

Done.

Find big files

[download big]

#!/bin/sh
# find the biggest files under the current directory.

find . -type f -printf "%k %p\n" | sort -rn | head

Find recent files

[download recent]

#!/bin/sh
# Find files created or modified less than 1 day ago

find . -mtime -1 -print

wifiscan

On linux, display the wireless networks around with a bit of shell magic:

[download wifiscan]

#!/bin/sh

# 20101123: Update to match the new iwlist output format.
# 20080304: Initial release.

IWLIST=/sbin/iwlist

# List wireless interfaces
ifaces=`LANG=C $IWLIST  scan 2>/dev/null | grep "Scan completed" | awk '{print $1}' | tr '\n' ' '`

# Choose only the first one
iface=`echo $ifaces | awk '{print $1}'`

# Extract informations and format output
(echo ESSID~~~Channel~~~Quality~~~Encryption && \
 echo "---~~~---~~~---~~~---" && \
 $IWLIST $iface scan | \
 sed -n -e 's/.*ESSID:\(.*\)/\1/p' \
        -e 's/.*Channel:\([^ ]*\)/~~~\1/p' \
        -e 's/Encryption key:\(.*\)/~~~\1/p' \
        -e 's/.*Quality:\([^ ]*\)\/100.*/~~~\1/p' | \
 xargs -n4 echo) | \
\
awk -F~~~ '{print $1 "~~~" $4 "~~~" $3 "~~~" $2}' | \
column -ntx -s ~~~

Here’s the result:

pierre@abricot:~$ wifiscan
ESSID              Encryption      Quality      Channel
---                ---             ---          ---
kameha             on              88           1
freephonie         on              88           1
                   on              90           1
NEUF_2714          on              75           6
Neuf WiFi          off             75           6
                   on              88           1
Livebox-074c       on              38           10
whiterabbit        on              38           11
                   on              38           11