Email can be a pain in the gazoo. Your code works, you've set up dovecot and postfix correctly, and email recipients... are not receiving emails from your application. The most common cause of failure, of course, is spam filters. Depending on the nature of the spam filter, the email might be automatically deleted!
The key to avoiding this sort of problem is ensuring that your emails never get classified as spam. There are many services that help with this, but the one I selected was SendGrid. Signup was a breeze. They have two different APIs, one for using SMTP and one using web services. SendGrid recommends using SMTP, but I want to get away from having email on my servers at all.
The only difficulty in using SendGrid was their PHP documentation (http://sendgrid.com/docs/Code_Examples/php.html), which is simply wrong. The following line is what they show as the last step in sending an email using their object library using web or smtp services.
The problem is that the web and smtp properties do not exist, which results in a fatal error when you try to send web or smtp a send() message.
Making SendGrid work
I can only guess that SendGrid's documentation applied to an earlier version of their library. In any case, after spending a bit of quality time with their code, I was able to make it work.
// In a configuration file
// Create the SendGrid mail object
$email = new SendGrid\Mail();
->setSubject('Important Application Notice')
->setText('This is a plain text message')
->setHtml('<p>This is an HTML message</p>');
// Use the SendGrid Web object to send the email
$web = new SendGrid\Web(SENDGRID_USERNAME, SENDGRID_PASSWORD);
Create a URL shortener
December 3, 2012 under PHP, PostgreSQL
URL shorteners are all the rage. At their core, they have two functions. First, encode an existing complete URL. Second, decode a shortened version of a URL and redirect to the (restored) URL.
Obviously, there are a number of services already available to do this for you, but I was very interested in adapting my framework to a very different kind of application. Since the framework uses a front controller design pattern, I can put almost all the key logic in the ApplicationDelegate object.
So, the first steps are to create a database to handle the data, and an application directory to handle the logic.
psql template1 postgres
CREATE USER iwurl WITH PASSWORD 'dbpassword' CREATEDB;
I am going to adapt the ApplicationDelegate to respond to the two different possible requests.
For the moment, I am going to ignore anything but the actual shortening and expanding. Eventually, the schema will include tables for managing demographics and usage.
CREATE TABLE url (
ALTER TABLE url ADD CONSTRAINT pkey_url PRIMARY KEY (url_id);
php orm_install -d -p -n URL Shortener -w /Users/markf/Sites -a url -r url
The processing can be entirely handled in the ApplicationDelegate object. Whenever a request is received, the framework gives the application an opportunity to intercede. Often, this means taking an SEO-friendly URL and turning it into an application module name (sometimes with translated parameters). For this example, however, either a request is being made to shorten a URL, or to take a shortened URL and redirect to its expanded URL. This can be done by updating the modifyPageRequest() method of ApplicationDelegate.
// Performing a url shortening
if ($url == 'shorten') return 'Shorten';
// Redirecting to the appropriate place
$url = UrlFactory::retrieveUrl($url, 'short');
$destination = $url ? $url->long : APPL_ROOT_DIR . 'error.html';
header('Location: ' . $destination);
To shorten a URL, I need to create a new entry in the url table.
class Shorten extends IWRenderModule
// can be passed via post or get (for now)
if (! $this->long = IWRequest::postValue('url'))
$this->long = IWRequest::getValue('url');
if ($this->long) $this->long = urldecode($this->long);
if (! $this->long) return ApplicationDelegate::ERROR; // constant set to -1
class UrlFactory extends DefaultUrlFactory
public static function createShortenedURL($long)
// If URL already encoded, return its short version
if ($url = UrlFactory::retrieveUrl($long, 'long')) return 'http://istrl.ws/' . $url->short;
// Create a new URL
$url = new Url;
return 'http://istrl.ws/' . $url->short;
The IWCodeMaker object (part of the Istarel Workshop Application Framework) is a handy utility object for creating codes (including temporary passwords). In this case, we're creating a five character smart alphanumeric code (the non-zero numerals and non-confusing letters).
And that is a simple implementation of a URL shortening service. Of course, there is a lot of potential work to be done, including validation of the url, preventing duplicates, implementing the whole process via RESTful services, and so on. Those will be topics of future blog entries.
PHP Sendmail under Mountain Lion
October 9, 2012 under Mac OS X, PHP
With an upgrade to Mac OS X 10.8 (Mountain Lion), PHP's sendmail() inexplicably ceased working. I knew that a number of things got re-defaulted (like /etc/paths) but this seemed a bit different.
The telltale error message in your Apache log is:
sendmail: fatal: chdir /Library/Server/Mail/Data/spool: No such file or directory