Surpassing Mailing Limits

Author: Jeff Anderson

Bluehost enforces a maximum outgoing email per limit on their service. Most tasks, such as personal email, and mass mailings can easily be routed through other mail servers. As long as the process sending the mail does not reside on the server, then it's as simple as changing the settings to use another mail service.

If your application has to run on the server, such as a web application, forum, business contact tracker, or cms, then you are out of luck. There is no way to send email to an outside server from Bluehost. Port 25 is blocked, because that would be open season for spammers. Any sane shared hosting company would enforce the same policy. The only way to get an email out to the rest of the world is to use either the sendmail binary, or connect to port 25 on localhost to send a message.

There are a few ways to get around this limitation, and almost all of them require that you have SSH enabled. SSH has many more features beyond providing a remote command prompt. It can carry just about any type of information.

SSH can do port forwarding. This is essential for almost every method that I've found to work. This assumes that you will be SSHing from a machine that has access to an smtp server. You can use your ISP's mail server, or your own if you run one.

Port forwarding is one of the many blades in the swiss-army-knife of a utility that SSH is. Essentially, we'll be taking a network service available to my computer, and then forward that to my shared hosting account.

Let's try out my mail server locally:

$ telnet mail.programmerq.net 25
Trying 208.75.84.102...
Connected to saffron.programmerq.net.
Escape character is '^]'.
220 saffron.programmerq.net ESMTP Postfix

This is the smtp server for my domain. I can access it here. Let's try accessing it from my Bluehost shared hosting account:

# telnet mail.programmerq.net 25
Trying 208.75.84.102...
telnet: connect to address 208.75.84.102: Connection refused

Bluehost does active port blocking. They actually fabricate a connection refused response if you try to connect to an outside mail server.

Unfortunately they also block outgoing ssh as well. There is no fabricated connection refused packet that comes back, the request simply times out.

Let's set up this port forward now. This ssh command is to be run on my workstation:

$ ssh -R 4690:mail.programmerq.net:25 username@example.com
username@example.com's password: 
#

Now that I'm connected, I can test out connectivity to my mail server:

# telnet localhost 4690
Trying 127.0.0.1...
Connected to localhost (127.0.0.1).
Escape character is '^]'.
220 saffron.programmerq.net ESMTP Postfix

I'm in business. As long as my SSH tunnel is opened, and the connection is established, I can send mail using hostname=localhost, port=4445, and any authentication method I'd normally use to connect to my mail server.

I can write a script to run somewhere that will attempt to re-establish the connection if lost, and more or less make my smtp server available to my website scripts always.

This approach has a few flaws. PHP's mail function doesn't use an SMTP connection on unix based servers. It depends on being able to use the sendmail binary.

Fortunately, using SSH, we can run the sendmail binary remotely, but first we need to port forward an SSH service on over:

$ ssh -R 20433:localhost:22 username@example.com
username@example.com's password: 
#

Now, my local ssh service is accessible on my shared hosting account on localhost:20433. I can connect to it with the -p option while logged into my shared hosting account:

ssh -p 20433 username@localhost

SSH can run commands remotely without giving you a shell. It does so transparently, and even sets the same return codes when SSH exits.

$ ssh username@example.com killall -9 php
$ echo $?
0
$ ssh username@example.com killall -9 php
php: no process killed
$ echo $?
1

The first time I run this command, killall kills at least one process successfully called php. The second time I run the command, there are no matching processes, so SSH spits out the same stdout and stderr that killall does, and then sets the same return code status, which is 1

Notice I don't have to type a password. I have set up ssh keys that allow me to login in a passwordless manner. I highly suggest doing this if you plan to use this in production.

Alright, so let's apply that to our shared hosting account. I've forwarded the ssh service running on port 22 of my mail server to port 46874 on my shared hosting account's localhost already. Now, from my shared hosting account, I can access the sendmail binary on my mail server by running the following:

# ssh -p 46874 username@localhost sendmail -t
From: Test Account <test@example.com>
To: Test Account 2 <test2@example.com>
Subject: sending out mail via SSH

I've tunneled through the internet, just to send an email.
#

The message will be queued on my mail server instead of on Bluehost's mail server. I can send 5000 messages if I really need to, and Bluehost's mail count for my domain will be close to zero.

Personally, I hate PHP, but PHP is by far the most common language in the shared hosting environment. All I have to do is set up passwordless ssh login that allows the remote user to access the sendmail binary, and then I set the following in my php.ini:

sendmail_path = "ssh -p 46874 username@localhost sendmail -t -i"

PHP won't know any difference, because SSH simply mimics the behavior of the remote sendmail. Bluehost won't know any difference, because no mail messages enter their system, and only ssh traffic goes in/out.

Posted: Jun 10, 2009 | Tags: Bluehost Hosting email PHP SSH

Comments are closed.