UPDATE 2/13/09: There is a newer version of the IMAP Authentication plugin for Wordpress 2.7.1.
It seems like IMAP authentication would be a pretty basic plugin to find for Wordpress. A google search doesn’t turn up much. I found this one which was apparently written for an older version of Wordpress. Never having written a Wordpress plugin before, naturally I decided to fix it to work with version 2.6.
Below is the result of my efforts. I started with Norman’s code, and modified it until it worked with version 2.6. I apologize if it is written poorly or if I missed something terribly obvious; I’ve never written a Wordpress plugin before.
Download imap-authentication2.php
<?php /* Plugin Name: IMAP Authentication Version: 0.1 Plugin URI: http://blog.neverusethisfont.com/2008/08/imap-authentication-for-wordpress/ Description: Authenticate users using IMAP authentication. Author: Aaron Parecki Author URI: http://www.aaronparecki.com Assumes a successful login against the IMAP server is a valid user, and auto-creates the user in Wordpress if they don't already exist. Copyright 2007 by Aaron Parecki (email : aaron@parecki.com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ add_action('admin_menu', array('IMAPAuthentication', 'admin_menu')); add_action('lost_password', array('IMAPAuthentication', 'disable_password')); add_action('retrieve_password', array('IMAPAuthentication', 'disable_password')); add_action('password_reset', array('IMAPAuthentication', 'disable_password')); add_filter('show_password_fields', array('IMAPAuthentication', 'show_password_fields')); if( is_plugin_page() ) { $mailbox = IMAPAuthentication::get_mailbox(); $user_suffix = IMAPAuthentication::get_user_suffix(); ?> <div class="wrap"> <h2>IMAP Authentication Options</h2> <form name="imapauthenticationoptions" method="post" action="options.php"> <?php wp_nonce_field('update-options'); ?> <input type="hidden" name="action" value="update" /> <input type="hidden" name="page_options" value="imap_authentication_mailbox,imap_authentication_user_suffix" /> <fieldset class="options"> <table width="100%" cellspacing="2" cellpadding="5" class="form-table"> <tr valign="top"> <th width="33%" scope="row"><label for="imap_authentication_mailbox">Mailbox</label></th> <td><input name="imap_authentication_mailbox" type="text" id="imap_authentication_mailbox" value="<?php echo htmlspecialchars($mailbox) ?>" size="80" /><br />eg: {mail.example.com/readonly}INBOX or {mail.example.com:993/ssl/novalidate-cert/readonly}INBOX</td> </tr> <tr valign="top"> <th scope="row"><label for="imap_authentication_user_suffix">User Suffix</label></th> <td><input name="imap_authentication_user_suffix" type="text" id="imap_authentication_user_suffix" value="<?php echo htmlspecialchars($user_suffix) ?>" size="50" /><br />A suffix to add to usernames (typically used to automatically add the domain part of the login).<br />eg: @example.com</td> </tr> </table> </fieldset> <p class="submit"> <input type="submit" name="Submit" value="<?php _e('Save Changes') ?>" /> </p> </form> </div> <?php } if( !class_exists('IMAPAuthentication') ) { class IMAPAuthentication { /* * Add an options pane for this plugin. */ function admin_menu() { add_options_page('IMAP Authentication', 'IMAP Authentication', 10, __FILE__); } /* * Return the mailbox option from the database, creating the option if it doesn't exist. */ function get_mailbox() { global $cache_nonexistantoptions; $mailbox = get_settings('imap_authentication_mailbox'); if (! $mailbox or $cache_nonexistantoptions['imap_authentication_mailbox']) { $mailbox = '{localhost:143}INBOX'; IMAPAuthentication::add_mailbox_option($mailbox); } return $mailbox; } /* * Add the mailbox option to the database. */ function add_mailbox_option($mailbox) { add_option('imap_authentication_mailbox', $mailbox, 'The mailbox to try and log into.'); } /* * Return the user_suffix option from the database, creating the option if it doesn't exist. */ function get_user_suffix() { global $cache_nonexistantoptions; $user_suffix = get_settings('imap_authentication_user_suffix'); if (! $user_suffix or $cache_nonexistantoptions['imap_authentication_user_suffix']) { $user_suffix = ''; IMAPAuthentication::add_user_suffix_option($user_suffix); } return $user_suffix; } /* * Add the user_suffix option to the database. */ function add_user_suffix_option($user_suffix) { add_option('imap_authentication_user_suffix', $user_suffix, 'A suffix to add to usernames (typically used to automatically add the domain part of the login).'); } // custom error handler function eh($type, $msg, $file, $line, $context) { $error = $error.$msg; } function login($username, $password) { global $wpdb; $mbox = imap_open(IMAPAuthentication::get_mailbox(), $username.IMAPAuthentication::get_user_suffix(), $password, OP_HALFOPEN) or $error = imap_last_error(); if ($mbox) { $user = get_userdatabylogin($username); if( $user === false ) { // the user checked out on the IMAP server, but there was no record in the database. Automatically add it now. $wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->users (user_login, user_nicename, user_email, display_name) VALUES(%s, %s, %s, %s)", $username, $username, $username.IMAPAuthentication::get_user_suffix(), $username) ); $user = get_userdatabylogin($username); $wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->usermeta (user_id, meta_key, meta_value) VALUES(%d, %s, %s)", $user->ID, 'nickname', $username) ); $wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->usermeta (user_id, meta_key, meta_value) VALUES(%d, %s, %s)", $user->ID, 'rich_editing', 'true') ); $wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->usermeta (user_id, meta_key, meta_value) VALUES(%d, %s, %s)", $user->ID, 'wp_capabilities', 'a:1:{s:6:"author";b:1;}') ); $wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->usermeta (user_id, meta_key, meta_value) VALUES(%d, %s, %s)", $user->ID, 'wp_user_level', '2') ); } imap_close($mbox); return new WP_User($user->ID); } else { do_action( 'wp_login_failed', $username ); return new WP_Error('incorrect_password', __('<strong>ERROR</strong>: Incorrect password.')); } } /* * Used to disable certain login functions, e.g. retrieving a * user's password. */ function disable_password() { login_header('Login', '<p class="message"><strong>ERROR</strong>: You can\'t do that here. This blog uses the IMAP login mechanism. Your password is set with your email account.</p>', 'error'); die(); } /* * Used to disable certain display elements, e.g. password * fields on profile screen. */ function show_password_fields($username) { return false; } } } if( !is_plugin_page() ) : function wp_authenticate($username, $password) { return IMAPAuthentication::login($username, $password); } endif; ?>
#1 by SpringCreek on August 28th, 2008
Nice! Great programming technique. Quiet useful even for the WordPress experts!
#2 by Jeremy Blanchard on February 13th, 2009
Hey Aaron!
The web is a small small place. I was just making a new website for the comp sci ACM club (http://acm.cs.uoregon.edu) and I wanted to let people authenticate against their CS email accounts. I finally ran across your plugin and when I actived it I saw your name as the author and was like “what?! are you kidding me!”
Good times. I just activated it on WP 2.7. Got this error:
Fatal error: Cannot redeclare wp_authenticate() (previously declared in /Library/WebServer/Documents/wp-includes/pluggable.php:438) in /Library/WebServer/Documents/wp-content/plugins/imap-authentication2.php on line 177
I’ll play with it for a bit and see if I can make any progress.
#3 by aaron on February 13th, 2009
Hey Jeremy,
Small world indeed! I updated this plugin to work in Wordpress 2.7.1. Check it out and let me know if you have problems.