Access Gmail from Ruby using Net::POP3 and Stunnel
I Googled around for this at one point, however, all I could find were ill-fated attempts by a couple of tortured souls on ruby-talk. Google offers POP3S access to Gmail, but, unfortunately, Ruby’s Net::POP3S module is still under development. POP3S is the much reviled and revered Post Office Protocol tunneled over a thick blanket of SSL obfuscation. Fortunately, the good Stunnel folks have anticipated this kind of thing and they’re giving out some code that can encode and decode SSL to a standard socket.
This was done on OS X, but Stunnel seems to work on most platforms. However, I wasn’t finding it in ports or fink. So, I had to roll my own stunnel binary.
wget http://www.stunnel.org/download/stunnel/src/stunnel-3.22.tar.gz tar zxf stunnel-3.22.tar.gz cd stunnel-3.22 ./configure make sudo make install
Whew. So, after you’ve installed stunnel, you need to invoke it to redirect a local port to Google’s secure POP3 port located at pop.gmail.com on port 995. You can redirect any local port to Google’s pop server. I chose to use port 42 because that’s as good as anything else. Here’s my stunnel invocation.
sudo /usr/local/sbin/stunnel -c -d 42 -r pop.gmail.com:995
So, now you can use Ruby’s Net::POP3 to access your gmail from port 42 on your local machine. Stunnel will handle the details of SSL.
require 'net/pop'
pop = Net::POP3.new('localhost', 42)
pop.start('mrbeastly', 'sUp3Rs3kRiT!')
if pop.mails.empty?
puts 'No mail.'
else
i = 0
pop.each_mail do |m|
exit if i > 20
puts m.pop
i=i+1
end
end
Running this code will display the first 20 emails in Gmail to your terminal. This is really a stopgap solution until the fabled POP3S patch gets accepted into Ruby’s Net library. This is rumored to be soon. So, I’ll keep my hopes up.
Reflection
Jim once believed that the following Ruby code constitutes an example of reflection.
def create(klass, value)
klass.new(value)
end
g = create(Greeting, "Hello")
g.show
Neither introspection nor metaprogramming occur in this code. This is not reflection. However, Jim argues that since getConstructor exists in Sun’s Java reflect class and because the Ruby code accomplishes the same task as his Java example that this is reflection. This logic is tenuous. However, I can defeat it because his Java code does not exemplify reflection.
public static Object create(Class c, String value)
throws Exception
{
Constructor ctor = c.getConstructor(
new Class[] { String.class } );
return ctor.newInstance(
new Object[] { "Hello" } );
}
public static void main (String args[])
throws Exception
{
Greeting g =
(Greeting) create(Greeting.class, "Hello");
g.show();
}
Using Java’s reflect class does not preclude that reflection has occured. If these examples are reflection, I could argue that the following C code is an example of reflection.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void* create(void* klass, char* value);
void* create(void* klass, char* value) {
size_t value_length = strlen(value);
klass = malloc(value_length+1);
strncpy(klass,value, value_length);
return klass;
}
int main() {
char* Greeting;
Greeting = create(Greeting, "Hello");
printf("%s", Greeting);
free(Greeting);
return 0;
}
Oh dear. Why did I switch to Ruby anyway if I can reflect in C?
Metaprogramming with Darkie The Fridge
m = "mr_beastly_"
(1..50).collect { |darkie_the_fridge|
thefun = m + darkie_the_fridge.to_s + "!"
eval %{
def #{thefun}(cinnamocha)
puts cinnamocha * #{darkie_the_fridge}
end
}
}
mr_beastly_5! 'boogiebot '
The result of this is boogiebot boogiebot boogiebot boogiebot boogiebot.
Ruby $1 vs \1
I was attempting to take some unordered SQL values and order them today with a single line of ruby. Essentially, the sql values look like (1, "value1"), (2, "value2"), and so on. I started out with this, but I couldn’t for the life of me figure out why the gsub statement wouldn’t work.
INCORRECT: ruby -e " y = []; STDIN.readlines.each { |x| if x=~/^\(/; y[x.gsub(/\(([0-9]+),.*/, $1.to_s).to_i]=x; end }; y.each { |z| puts z if ! z.nil?; } " < unordered.sql > ordered.sql
The weird thing is, if I take the if x=~ /^\(/; statement out, the code works. So, someone in #ruby-lang on Freenode reminded me that I need to use '\1' instead of $1.to_s in this case. I ran into this once before, however, I’m still not 100% sure on what the exact rules are for the syntax. So, this was the correct way to do it.
CORRECT: ruby -e " y = []; STDIN.readlines.each { |x| if x=~/^\(/; y[x.gsub(/\(([0-9]+),.*/, '\1').to_i]=x; end }; y.each { |z| puts z if ! z.nil?; } " < unordered.sql > ordered.sql
RSS Parser in 10 lines of Ruby or in 153 lines of C++
I know there’s like 10 libraries to do this already, but they all seemed a bit heavy to me. I just wanted to grab the items from an RSS feed. Plain and simple. What’s amazing to me is that it could be done in 10 lines of Ruby. This parser reads an RSS feed, and stores the descriptions, items, and links into a hash of arrays.
#!/usr/bin/env ruby
require 'http-access2'
h = HTTPAccess2::Client.new()
element = Hash.new {|h,k| h[k] = []}
while urlstr = ARGV.shift
response = h.get(urlstr) { |data|
data.gsub(/<(description|title|link)>(.*?)<\/(description|title|link)>/m) {
element[$1].push($2.gsub(/\s\s+/m,' '))
}
}
end
site_description = element['description'].shift
site_title = element['title'].shift
Stupidly, I wrote the same code in C++ first because I thought it would run faster. After starting down that path, I found myself wanting to use ActiveRecord. So, I ported over to Ruby.
The C++ version is here if you really want to see it. It’s 121 lines of C++ with a 32 line h-file. Truth be told, it actually took me less time to code the C++ because I made a couple of mistakes in my Ruby version at first. All said and done, the Ruby version is a helluva lot easier to maintain than the C++ which I think is why I spent the time to do it in the first place.






