Category Archives: code

sending email in python with gmail

A Python nugget from Programming Your Home (review) I wanted to share from p97:

import smtplib
def send_email(subject, message)
    recipient = 'your_email_recipient@domain.tld'
    gmail_sender = 'your_gmail_account@gmail.com'
    gmail_password = 'your_gmail_password'

    #use tls
    gmail_smtp = smtplib.SMTP('smtp.gmail.com', 587)
    gmail_smtp.ehlo()
    gmail_smtp.starttls()
    gmail_smtp.ehlo()

    #login
    gmail_smtp.login(gmail_send, gmail_password)

    #message formatting
    mail_header = 'To: ' + recipient + '\n' + 'From: ' + gmail_sender + '\n' + 'Subject: ' + subject + '\n'
    message_body = message
    mail message = mail_header + '\n ' + message_body + '\n\n'

    #send
    gmail_smtp.sendmail(gmail_sender, recipient, mail_message)

    #close
    gmail_smtp.close()

setting up an unreal irc server on centos 6

Ever want to run an IRC server? I recently set one up at irc.datente.com using a Digital Ocean VM running CentOS 6.5 x64.

Here’s what I did, if you want to replicate the process for yourself (full documentation available from Unreal’s website):

  • acquire CentOS 6.5 x64 server (as I mentioned, I used Digital Ocean)
  • `yum -y install screen wget gcc`
  • `yum -y upgrade`
  • `adduser unreal`
  • `su – unreal`
  • download Unreal to your server (http://www.unrealircd.com/downloads/unreal/source – `wget http://www.unrealircd.com/downloads/Unreal3.2.10.2.tar.gz`)
  • `tar zxf Unreal*.gz`
  • `cd Unreal*`
  • `make clean`
  • `./Config`
    • answer prompts – most can be left default
  • `make`
  • `cp doc/example.conf unrealircd.conf`
  • edit unrealircd.conf (use your editor of choice)
    • see sample config file below for what I did (minus passwords / emails)
  • if all has gone well, start Unreal
    • `screen ./unreal start`
  • create a startup script to ensure Unreal launches on reboot as user `unreal`

That’s it. Thankfully, while the config file isn’t pleasant to play with, it’s a lot better than it used to be.

loadmodule "src/modules/commands.so";
loadmodule "src/modules/cloak.so";

include "help.conf";
include "badwords.channel.conf";
include "badwords.message.conf";
include "badwords.quit.conf";
include "spamfilter.conf";

me
{
        name "your.irc.server.tld";
        info "Your IRC Server";
        numeric 1;
};

admin {
        "Your Name";
        "yournick";
        "your@email.tld";
};

class           clients
{
        pingfreq 90;
        maxclients 500;
        sendq 100000;
        recvq 8000;
};

class           servers
{
        pingfreq 90;
        maxclients 10;          /* Max servers we can have linked at a time */
        sendq 1000000;
        connfreq 100; /* How many seconds between each connection attempt */
};

allow {
        ip             *@*;
        hostname       *@*;
        class           clients;
        maxperip 25;
};

/* Passworded allow line */
allow {
        ip             *@255.255.255.255;
        hostname       *@*.passworded.ugly.people;
        class           clients;
        password "f00Ness";
        maxperip 1;
};

allow channel {
        channel "#WarezSucks";
        class "clients";
};

oper youroperatornick {
        class           clients;
        from {
                userhost bob@smithco.com;
        };
        password "yourpassword";
        flags
        {
                netadmin;
                can_zline;
                can_gzline;
                can_gkline;
                global;
        };
};

listen         *:6697
{
        options
        {
// uncomment this line if you chose to compile Unreal with SSL support
//              ssl;
                clientsonly;
        };
};

listen         *:8067;
listen         *:6667;

/* not linking to any other servers right now
link            hub.mynet.com
{
        username        *;
        hostname        1.2.3.4;
        bind-ip         *;
        port            7029;
        hub             *;
        password-connect "LiNk";
        password-receive "LiNk";
        class           servers;
                options {
                        /* Note: You should not use autoconnect when linking services */
                        autoconnect;
                        ssl;
                        zip;
                };
};
*/

ulines {
        services.roxnet.org;
        stats.roxnet.org;
};

drpass {
        restart "I-love-to-restart";
        die "die-you-stupid";
};

log "ircd.log" {
        /* Delete the log file and start a new one when it reaches 20MB, leave this out to always use the 
           same log */
        maxsize 20971520;
        flags {
                oper;
                connects;
                server-connects;
                kills;
                errors;
                sadmin-commands;
                chg-commands;
                oper-override;
                spamfilter;
        };
};

alias NickServ { type services; };
alias ChanServ { type services; };
alias OperServ { type services; };
alias HelpServ { type services; };
alias StatServ { type stats; };

alias "identify" {
        format "^#" {
                target "chanserv";
                type services;
                parameters "IDENTIFY %1-";
        };
        format "^[^#]" {
                target "nickserv";
                type services;
                parameters "IDENTIFY %1-";
        };
        type command;
};

alias "services" {
        format "^#" {
                target "chanserv";
                type services;
                parameters "%1-";
        };
        format "^[^#]" {
                target "nickserv";
                type services;
                parameters "%1-";
        };
        type command;
};

alias "identify" {
        format "^#" {
                target "chanserv";
                type services;
                parameters "IDENTIFY %1-";
        };
        format "^[^#]" {
                target "nickserv";
                type services;
                parameters "IDENTIFY %1-";
        };
        type command;
};

alias "glinebot" {
        format ".+" {
                command "gline";
                type real;
                parameters "%1 2d Bots are not allowed on this server, please read the faq at http://www.example.com/faq/123";
        };
        type command;
};

files
{
        /* The Message Of The Day shown to users who log in: */
        /* motd ircd.motd; */

        /*
         * A short MOTD. If this file exists, it will be displayed to
         * the user in place of the MOTD. Users can still view the
         * full MOTD by using the /MOTD command.
         */
        /* shortmotd ircd.smotd; */

        /* Shown when an operator /OPERs up */
        /* opermotd oper.motd; */

        /* Services MOTD append. */
        /* svsmotd ircd.svsmotd; */

        /* Bot MOTD */
        /* botmotd bot.motd; */

        /* Shown upon /RULES */
        /* rules ircd.rules; */

        /*
         * Where the IRCd stores and loads a few values which should
         * be persistent across server restarts. Must point to an
         * existing file which the IRCd has permission to alter or to
         * a file in a folder within which the IRCd may create files.
         */
        /* tunefile ircd.tune; */

        /* Where to save the IRCd's pid. Should be writable by the IRCd. */
        /* pidfile ircd.pid; */
};

/*
tld {
        mask *@*.fr;
        motd "ircd.motd.fr";
        rules "ircd.rules.fr";
};
*/

/* note: you can just delete the example block above,
 * in which case the defaults motd/rules files (ircd.motd, ircd.rules)
 * will be used for everyone.
 */

ban nick {
        mask "*C*h*a*n*S*e*r*v*";
        reason "Reserved for Services";
};

ban ip {
        mask 195.86.232.81;
        reason "Delinked server";
};

ban server {
        mask eris.berkeley.edu;
        reason "Get out of here.";
};

ban user {
        mask *tirc@*.saturn.bbn.com;
        reason "Idiot";
};

ban realname {
        mask "sub7server";
        reason "sub7";
};

except ban {
        /* don't ban stskeeps */
        mask           *stskeeps@212.*;
};

deny dcc {
        filename "*sub7*";
        reason "Possible Sub7 Virus";
};

deny channel {
        channel "*warez*";
        reason "Warez is illegal";
        class "clients";
};

vhost {
        vhost           i.hate.microsefrs.com;
        from {
                userhost       *@*.image.dk;
        };
        login           stskeeps;
        password        moocowsrulemyworld;
};

set {
        network-name            "Datente";
        default-server          "irc.datente.com";
        services-server         "irc.datente.com";
        stats-server            "irc.datente.com";
        help-channel            "#datente";
        hiddenhost-prefix       "rox";
        /* prefix-quit          "no"; */
        /* Cloak keys should be the same at all servers on the network.
         * They are used for generating masked hosts and should be kept secret.
         * The keys should be 3 random strings of 5-100 characters
         * (10-20 chars is just fine) and must consist of lowcase (a-z),
         * upcase (A-Z) and digits (0-9) [see first key example].
         * HINT: On *NIX, you can run './unreal gencloak' in your shell to let
         *       Unreal generate 3 random strings for you.
         */
        cloak-keys {
                "aoAr1HnR6gl3sJ7hVz4Zb7x4YwpW";
                "aaAr1HnR6gl3sJ7hVz4Zb7x4YwpW";
                "aeAr1HnR6gl3sJ7hVz4Zb7x4YwpW";
        };
        /* on-oper host */
        hosts {
                local           "locop.roxnet.org";
                global          "ircop.roxnet.org";
                coadmin         "coadmin.roxnet.org";
                admin           "admin.roxnet.org";
                servicesadmin   "csops.roxnet.org";
                netadmin        "netadmin.roxnet.org";
                host-on-oper-up "no";
        };
};

set {
        kline-address "your@email.tld";
        modes-on-connect "+ixw";
        modes-on-oper    "+xwgs";
        oper-auto-join "#opers";
        options {
                hide-ulines;
                /* You can enable ident checking here if you want */
                /* identd-check; */
                show-connect-info;
        };

        maxchannelsperuser 10;
        /* The minimum time a user must be connected before being allowed to use a QUIT message,
         * This will hopefully help stop spam */
        anti-spam-quit-message-time 10s;
        /* Make the message in static-quit show in all quits - meaning no
           custom quits are allowed on local server */
        /* static-quit "Client quit";   */

        /* You can also block all part reasons by uncommenting this and say 'yes',
         * or specify some other text (eg: "Bye bye!") to always use as a comment.. */
        /* static-part yes; */

        /* This allows you to make certain stats oper only, use * for all stats,
         * leave it out to allow users to see all stats. Type '/stats' for a full list.
         * Some admins might want to remove the 'kGs' to allow normal users to list
         * klines, glines and shuns.
         */
        oper-only-stats "okfGsMRUEelLCXzdD";

        /* Throttling: this example sets a limit of 3 connection attempts per 60s (per host). */
        throttle {
                connections 3;
                period 60s;
        };

        /* Anti flood protection */
        anti-flood {
                nick-flood 3:60;        /* 3 nickchanges per 60 seconds (the default) */
        };

        /* Spam filter */
        spamfilter {
                ban-time 1d; /* default duration of a *line ban set by spamfilter */
                ban-reason "Spam/Advertising"; /* default reason */
                virus-help-channel "#help"; /* channel to use for 'viruschan' action */
                /* except "#help"; channel to exempt from filtering */
        };
};


what is the “new” python?

9 years ago, Paul Graham made a controversial statement:

[W]hen you choose a language, you’re also choosing a community. The programmers you’ll be able to hire to work on a Java project won’t be as smart as the ones you could get to work on a project written in Python. And the quality of your hackers probably matters more than the language you choose. Though, frankly, the fact that good hackers prefer Python to Java should tell you something about the relative merits of those languages.

He had a follow-up the next month to expand a little on that thought:

[Y]ou could get smarter programmers to work on a Python project than you could to work on a Java project.

I didn’t mean by this that Java programmers are dumb. I meant that Python programmers are smart. It’s a lot of work to learn a new programming language. And people don’t learn Python because it will get them a job; they learn it because they genuinely like to program and aren’t satisfied with the languages they already know.

Which makes them exactly the kind of programmers companies should want to hire.

I wonder – what is the “new” Python? If Python was what the Cool Kids™ were picking up for fun a decade ago, what is it today? R? Ruby? Or something that isn’t as well known? Ruby is two years newer than Python, but seems to have only become truly popular with the advent of Ruby-on-Rails. R may be too focused (it being designed for statistics programming), though it is also 20 years old now.

What new languages / techniques are there? Are there any? Haskell is  nearly a quarter century old. Erlang is nearly 30.

If you were a hiring manager, what would strike you as “motivated” or “must be smart” in terms of language(s) on resume?

the deadly sins of programming – again?

InfoWorld this week published yet another article on “The 7 deadly sins of software development”. For those who don’t care to read the ~1 page article (that’s split unless you use the “print” option that puts it all on one page), here’s the list:

  1. Lust – overengineering
  2. Gluttony – not refactoring
  3. Greed – cross-team competition
  4. Sloth – not validating input
  5. Wrath – no/bad comments
  6. Envy – no version control
  7. Pride – no unit testing

Spiffy. Items 1, 4, 5, and 7 are beaten to DEATH in every computer science / information systems / intro programming / advanced programming / algorithms / data structures / etc / etc class I have every attended, read about, heard about, or thought about. Why is it rehashed AGAIN by InfoWorld?

Better yet, why does an article like this appear every 9-18 months (or more!) in a major publication or on a major website (InfoWorld, ComputerWorld, arstechnica, joelonsoftware, codinghorror, etc etc)?

Is it because, as my friend Steven said they’re ‘basically new writers {“i’m fresh out of college and i know everything”} or quotas on programming articles‘? Is it because programmers are really THAT lazy? Or that bad? Or that inconsiderate? Or that management hasn’t encouraged a culture of excellence and teamwork? Yes, shipping IS a feature. It’s really important. So is having developers who care about their work – and who care for their fellow workers who will have to look at / modify / care for / clean their work later.

Lack of version control will bite you HARD everytime you don’t use it (don’t ask how I know – call it a Bad Experience™). Competing with other teams is just dumb: you’re all supposed to be working for the same company, the same end goal, and, ultimately, the same customers who will eventually pay for whatever it is you’re writing (I’ll relate another moderately-humorous anecdote on that another time).

If developers really are that bad, or their employers are bad enough to not help/fix behavior, then we’re all in a lot of trouble. And if they’re not – then it must just be that it was a slow week, so somebody thought they’d regurgitate and modify the same thing we’ve all heard hundreds of times.

firsts – programming

I realized earlier this week that it’s been 19 years since I first started programming. Not my first exposure to computing, which was in about 1986 on my aunt’s Mac 512 .. but still a long time ago 🙂

My aunt gave me a Tandy 102 laptop that had a whole walloping 21446 bytes of storage. It had the capability to store up to 19 files, and the names had to be in a 6.2 form (ie, not the “standard” DOS 8.3 naming convention).

It shipped with MS BASIC somethingorother, and had a 40 character wide by 8 character tall screen. Oh, and don’t forget the built-in 300 bps modem (that ‘rotary’ dialed)!

I learned BASIC from Learning BASIC for the Tandy by David A Lien. I learned a LOT from that book – not the least of which was that color doesn’t work on a monochrome screen 🙂

I also learned how pseudorandom numbers can be “manipulated” to help you win games .. and that typos suck : mightily.

Some of my programming habits that I still carry (even in writing “throwaway” scripts), come from my time of writing programs on an extremely limited machine.

After playing with BASIC for a year or so, I started writing for my aunt’s old Mac iiVX (which had 5MB RAM and an 80MB hard disk!) using Microsoft QuickBASIC 1.0 (a compilable BASIC), then moved into Turbo Pascal for a couple months, and then into C++ in 1993. My introduction to C++ was in the form of working with a family friend from church who wanted to learn C++ (but knew C), and who wanted to try-out some ideas he had for work with finite element analysis software. So we (I built the mesh generator/parser, and acted as syntax fiend) built a FEA application using Borland C++ 4.0 on his 486 running Windows 3.11 for workgroups. That was a screamer compared to my little laptop: it ran at 66Mhz, and had 16MB RAM! Wow: those were the days 🙂

My cell phone has more RAM than that now, and a faster CPU, to boot!

I know I didn’t start as long ago, or as young, as some of my friends, colleagues, and cofiends – but there’s my story 🙂

shell scripting

I’ve been playing around with bash scripting quite a bit recently in relation to my current job.

Came up with one that’s really useful (imho) around chkconfig:

# mass set all services known to chkconfig to be `on` or `off` at given level
# written by warren myers - warren@warrenmyers.com
# 28 sep 2009

echo "USAGE:"
echo " $0 <level> [on|off]"
echo

# list all services, just the name, skip blank lines, do in order
SERVICES=`chkconfig --list | cut -f 1 | grep -v ^$ | grep -v ':' | sort`

for SERVICE in $SERVICES
do
  chkconfig --level $1 $SERVICE $2
  echo "$SERVICE has been altered for $1 to state $2"
done

Yes – there’s an evil you could perform:

for CS in `chkconfig --list | cut -f 1 | grep -v ^$ | grep -v ':'`
do
  chkconfig --level 12345 $CS off
done

So, if you wanted to stop all services from coming on at startup, you could – and not know you did it until you rebooted.