Email Routing Troubleshoting

Having trouble getting mail sent from your server delivered?

First check to see if your sending IP is on any sending blacklists:

Blacklist Check

And check the reputation of your IP: – Transparency into your email marketing reputation

Make sure you have your Sender Policy Framework set up.

Sender Policy Framework – Wikipedia

SPF Record Syntax

SPF Syntax Validator

Review sending best practices:

Email Delivery for IT Professionals

Q: Should I send an email blast with WordPress and WP Engine?

SMTP Error Codes

Other diagnostic tools:


Installing mcrypt on CentOS via EPEL

I have a Media Temple DV 4.0 running CentOS 5.5 which needed php-mcrypt.

yum install php-mcrypt fails with a conflict between php-common and php53-common. Here’s how to to get php53-mcrypt via EPEL.

First download the repo rpm: wget

Note CentOS 6 has a different rpm.

Install the repo: rpm -ivh epel-release-5-4.noarch.rpm has this warning about EPEL:
“So, make SURE you are using the Priorities yum plugin if you are using EPEL….”

So, let’s do that:
yum install yum-priorities

Check to make sure it’s enabled:
cat /etc/yum/pluginconf.d/priorities.conf

and add the priority rules per, setting the default repos high and EPEL low.
vi /etc/yum.repos.d/*

Now we can install the module: yum install php53-mcrypt.

/etc/init.d/httpd graceful and you’re done.

Learning Git

I think I finally get git!

Some resources I found useful while learning:

The graphs in Git for Computer Scientists really helped me understand how git works on the inside, which answers a lot of questions about why commands behave as they do.

Git Immersion is a follow-along-style walkthrough covering basic git interactions.

A successful Git branching model describes general branching model practices as applied to git, but uses the --no-ff for all merges.

Understanding the Git Workflow talks about why this is bad and offers alternatives.

I find that GitHub Flow works much better for web development than git-flow.

Other useful links:

How To Fix “_arguments:comparguments:208: invalid argument: ARG” SVN Tab Completion Error

SVN 1.5 changed the Subversion help output to print ARG instead of arg. Unfortunately, the file which ZSH uses to parse the Subversion help output to generate the tab completion options was only looking for a lower case arg. The result is the error _arguments:comparguments:208: invalid argument: ARG when trying to tab-complete svn commands in ZSH.

The fix was committed to the ZSH source in Jan 2008, but still has yet to make its way into all the machines being sold by hosting providers.

If you get stuck with a box with the new SVN but the old ZSH you can fix this yourself by editing /usr/share/zsh/x.x.x/functions/_subversion and replacing




both places it occurs.

VoilĂ ! SVN tab completion works again.

Downloading Podcasts With CRON

I used to open iTunes so I could click the “update” button to get the latest version of a podcast. Then I got tired of waiting for iTunes and decided I could keep my podcasts updated via CRON. Here’s the script I use which should work for most podcasts with an XML feed:

wget --output-document=- --quiet | grep mp3 | head -1 | sed -e "s/^.*\(http.*mp3\).*/\1/" | wget --input-file=- --quiet --output-document /tmp/marketplace.`date +\%Y-\%m-\%d`.mp3

Connecting to MS SQL Server with Ruby on Rails


If you’re running the Rails app on a Windows box you’ll first need the the DevKit toolkit in order to build gems:

Regardless of platform you’ll need to install the ODBC Binding for Ruby and SQL Server 2005 and 2008 Adapter For ActiveRecord. Add the latter (at least) to your project by adding config.gem "activerecord-sqlserver-adapter" to your environment.rb config section.


On Linux we’ll need the FreeTDS libraries in order to talk to the MS SQL. You’ll need to add an entry to the freetds.conf file specifying how your database can be reached. Be sure to confirm the installation to make sure it’s possible to connect to the database.

To bridge the gap between Rails and FreeTDS you’ll need to add your database configuration settings to two additional files, /etc/odbc.ini and /etc/odbcinst.ini.

In /etc/odbcinst.ini add something to the effect of:

Description = TDS driver (Sybase/MS SQL)
Driver = /usr/lib64/
Setup = /usr/lib64/
CPTimeout =
CPReuse =
FileUsage = 1

Make sure the Driver and Setup paths point to the actual libraries.

In /etc/odbc.ini add something to the effect of:

Driver = FreeTDS
Description = ODBC connection via FreeTDS
Trace = No
Servername = SERVER_NAME

Then, in your database.yml file:

adapter: sqlserver
mode: ODBC
username: USER
password: PASS

Customize the all-caps strings as needed, except the mode, which really is ODBC.

Installing Tomcat 6 on a cPanel Server

The cPanel EasyApache system makes it easy to recompile Apache with various add-ons and modules. There’s even a checkbox for adding Tomcat. Unfortunately, this installs Tomcat 5.5, and I needed Tomcat 6.0. Here’s how I got it:

1) install Tomcat 5.5 using EasyApache (see this .pdf for details)

2) download and expand Tomcat 6 in /usr/local/jakarta

3) change the tomcat symlink to point to your new version (i.e. /usr/local/jakarta/apache-tomcat-6.0.XX)

4) from

#cd apache-tomcat-6.0.18
# cd bin
# tar xvfz jsvc.tar.gz
# cd jsvc-src
# chmod +x configure
# ./configure
# make
# cp jsvc ..
# cd ..

5) copy over any Host blocks from tomcat/conf/server.xml from the old Tomcat install to the new Tomcat install (you may or may not be able to set up new hosts through WHM)

6) copy over conf/ from the old Tomcat install to the new Tomcat install

7) start tomcat normally (/usr/sbin/starttomcat)

The /manager/html/ Tomcat manager application doesn’t load, though, so it’s not perfect.

If you ever need your old Tomcat back just stop Tomcat, flip the tomcat symlink back to the old install, and restart Tomcat.

Dreamhost to Google Apps naked domain name redirection

I’ve had this problem twice in recent memory, which warrants taking notes.

Dreamhost has a handy “Google Hosted” feature where with a single click they’ll completely configure your domain to use Google Apps. You can then use Google Sites and the rest of the Apps suite for your entire website. Unfortunately, while Google Sites allows you to map a subdomain to a Google Site page, mapping naked domains (e.g. are not supported. If one maps the www subdomain to a Google Site then the traditional will resolve, but gives a Google-served 404 error. When using the Dreamhost “Google Hosted” feature all of the generated domain DNS records are non-editable, so you’re stuck with an A record which maps the domain to a nonexistent site.

My solution was to not use the Dreamhost “Google Hosted” feature at all, but to instead use the “DNS Only” option. I copied down all the generated DNS entries from the “Google Hosted” setup and manually recreated them, with one exception. The A record for the naked domain I directed to, which is the IP address of WWWizer, a free service which handily redirects any naked domain request the the corresponding www subdomain.

Now I have a site set up on my www subdomain with Google footing the hosting bill, and naked domain requests are seamlessly redirected to the www-based home page.

Enabling chat outside Google Apps

Google Apps users can chat with other users on the Google Talk network, but it’s also possible to set up federation on your domain to allow your users to chat with anyone using the XMPP protocol.

The Google Help page on the topic, at, is pretty weak. “If you require assistance making these changes in your domain host account”, they offer, “we suggest contacting your domain host.”

The change involves adding SRV DNS records for your domain. The records to be added are: IN SRV 5 0 5269 IN SRV 20 0 5269 IN SRV 20 0 5269 IN SRV 20 0 5269 IN SRV 20 0 5269 IN SRV 5 0 5269 IN SRV 20 0 5269 IN SRV 20 0 5269 IN SRV 20 0 5269 IN SRV 20 0 5269

where is replaced by your apps domain name.

Wikipedia takes a SRV record in the form 86400 IN SRV 0 5 5060

and breaks it down thusly:

_Service._Proto.Name TTL Class SRV Priority Weight Port Target


  • Service: the symbolic name of the desired service.
  • Proto: the transport protocol of the desired service; this is usually either TCP or UDP.
  • Name: the domain name for which this record is valid.
  • TTL: standard DNS time to live field.
  • Class: standard DNS class field (this is always IN).
  • Priority: the priority of the target host, lower value means more preferred.
  • Weight: A relative weight for records with the same priority.
  • Port: the TCP or UDP port on which the service is to be found.
  • Target: the canonical hostname of the machine providing the service.

Taking the first of the Google provided record definitions as an example, IN SRV 5 0 5269

we have:

  • Service: xmpp-server
  • Proto: tcp
  • Name:
  • TTL: (none given)
  • Class: IN
  • Priority: 5
  • Weight: 0
  • Port: 5269
  • Target:

where, again, is replaced by your Google Apps domain.

My DNS settings provider doesn’t offer a “Name” field while adding SRV records; instead they have a “Record/Hostname” field where the domain fixed but with the opportunity to enter a subdomain. This is usually not necessary with Google Apps, unless your primary Google Apps domain is actually a subdomain. For me I just left the “Record/Hostname” field blank and the “Name” was set correctly.

You can test that your new SRV records were created correctly using dig:

dig SRV

You should get back, in the ANSWER SECTION, just what the Google Help page listed for that service (with a TTL added): 86400 IN SRV 20 0 5269 86400 IN SRV 20 0 5269 86400 IN SRV 20 0 5269 86400 IN SRV 20 0 5269 86400 IN SRV 5 0 5269

If you don’t want to wait for the DNS updates to propagate you can ask your domains name server directly:

dig @ SRV

Where is replaced with the IP address of your domains name server.

Shell Script

A fun little shell script:


Next Page »

powered by WordPress     themed by Mukkamu     presented by     everything else by steve hulet