Open main menu

Extension:AuthPOP3

MediaWiki extensions manual
OOjs UI icon advanced.svg
POP3 Authentication
Release status: experimental
Implementation User identity
Description Used to authenticate against POP3 mail servers. Tested with qmail
Author(s) dbu based on Extension:AuthIMAP
MediaWiki 1.8
License No license specified
Download see below
Translate the AuthPOP3 extension if it is available at translatewiki.net
Check usage and version matrix.

PurposeEdit

This extension authenticates a wiki user against POP3 servers.

InstallationEdit

Proceed at your own risk!

Place the source code below in a file titled Auth_pop3.php under the extensions folder of your installation.

Add these two lines to the bottom of your LocalSettings.php

require_once('extensions/Auth_pop3.php');
$wgAuth = new Auth_pop3();

It is necessary to edit the variables maildomain and mailserver to connect to your POP3 server.

You probably want to edit the initUser function to set the users real name and email address properly for your configuration.

NoteEdit

Code contains lots of die() to debug pop3 server misbehaviour. You should remove those once you verified the code is working. Or use decent logging right away... I am happy to hear if you successfully used the plugin or if you improved it.

Source codeEdit

<?php
// 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 3 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, see <http://www.gnu.org/licenses/>.
//
// Copyright 2008 David Buchmann, based on Auth_imap by Rusty Burchfield

// Add these two lines to the bottom of your LocalSettings.php
// require_once('extensions/Auth_pop3.php');
// $wgAuth = new Auth_pop3();

// The Auth_imap class is an AuthPlugin so make sure we have this included.
require_once('includes/AuthPlugin.php');

class Auth_pop3 extends AuthPlugin {
  /** The part of your email adresses after the @ */
  private $maildomain = 'example.com';
  /** The server name for the pop3 server */
  private $mailserver = 'mail.example.com';
  
  function Auth_pop3() {
  }

  /**
   * Disallow password change.
   *
   * @return bool
   */
  function allowPasswordChange() {
    return false;
  }

  /**
   * This should not be called because we do not allow password change.  Always
   * fail by returning false.
   *
   * @param $user User object.
   * @param $password String: password.
   * @return bool
   * @public
   */
  function setPassword($user, $password) {
    return false;
  }

  /**
   * We don't support this but we have to return true for preferences to save.
   *
   * @param $user User object.
   * @return bool
   * @public
   */
  function updateExternalDB($user) {
    return true;
  }

  /**
   * We can't create external accounts so return false.
   *
   * @return bool
   * @public
   */
  function canCreateAccounts() {
    return false;
  }

  /**
   * We don't support adding users to whatever service provides REMOTE_USER, so
   * fail by always returning false.
   *
   * @param User $user
   * @param string $password
   * @return bool
   * @public
   */
  function addUser($user, $password) {
    return false;
  }


  /**
   * Pretend all users exist.  This is checked by authenticateUserData to
   * determine if a user exists in our 'db'.  By returning true we tell it that
   * it can create a local wiki user automatically.
   *
   * @param $username String: username.
   * @return bool
   * @public
   */
  function userExists($username) {
    return true;
  }

  /**
   * Attempt to authenticate the user via IMAP.
   *
   * @param $username String: username.
   * @param $password String: user password.
   * @return bool
   * @public
   */
  function authenticate($user, $pass) {
        $user = "$user@$this->maildomain";
        require_once('Net/Socket.php');
        $socket = new Net_Socket();
        $result = $socket->connect($this->mailserver, 110, false, 3);

        if ($result === true) {
          if (PEAR::isError($response = $socket->readLine( 8192 ))) {
            die($data->getMessage());
          }
          if (@substr(strtoupper($response), 0, 3) == '+OK') {
            // the response begins with '+OK' ...
          } else {
            $socket->disconnect();
            die('Mail server sent '+$response);
          }
        } else {
          $socket->disconnect();
          die('Could not connect to mail server');
        }

        if (PEAR::isError($result = $socket->writeLine("USER $user") )){
          die($result->getMessage());
        }
        if (PEAR::isError( $data = $socket->readLine( 8192 ) ) ) {
          die($data->getMessage());
        }
        if (! strtoupper(substr($data, 0, 3)) == '+OK') {
          return false;
        }

        if (PEAR::isError($result = $socket->writeLine("PASS $pass") )){
          die($result->getMessage());
        }
        if (PEAR::isError( $data = $socket->readLine( 8192 ) ) ) {
          die($data->getMessage() );
        }
        if (! (strtoupper(substr($data, 0, 3)) == '+OK')) {
          return false;
        }

        //if we get here, everything is ok
        return true;

  }

  /**
   * Check to see if the specific domain is a valid domain.
   *
   * @param $domain String: authentication domain.
   * @return bool
   * @public
   */
  function validDomain($domain) {
    return true;
  }

  /**
   * When a user logs in, optionally fill in preferences and such.
   * For instance, you might pull the email address or real name from the
   * external user database.
   *
   * The User object is passed by reference so it can be modified; don't
   * forget the & on your function declaration.
   *
   * @param User $user
   * @public
   */
  function updateUser(&$user) {
    // We only set this stuff when accounts are created.
    return true;
  }

  /**
   * Return true because the wiki should create a new local account
   * automatically when asked to login a user who doesn't exist locally but
   * does in the external auth database.
   *
   * @return bool
   * @public
   */
  function autoCreate() {
    return true;
  }

  /**
   * Return true to prevent logins that don't authenticate here from being
   * checked against the local database's password fields.
   *
   * @return bool
   * @public
   */
  function strict() {
    return false;
  }

  /**
   * When creating a user account, optionally fill in preferences and such.
   * For instance, you might pull the email address or real name from the
   * external user database.
   *
   * @param $user User object.
   * @public
   */
  function initUser(&$user) {
    global $_SERVER;
    //    $username = $_SERVER['REMOTE_USER'];
    $username = $_REQUEST['wpName'];

    // Using your own methods put the users real name here.
    //    $user->setRealName('');
    // Using your own methods put the users email here.
    $user->setEmail("$username@$maildomain");

    $user->mEmailAuthenticated = wfTimestampNow();
    $user->setToken();

    //turn on e-mail notifications by default
    $user->setOption('enotifwatchlistpages', 1);
    $user->setOption('enotifusertalkpages', 1);
    $user->setOption('enotifminoredits', 1);
    $user->setOption('enotifrevealaddr', 1);

    $user->saveSettings();
  }

  /**
   * Modify options in the login template.  This shouldn't be very important
   * because no one should really be bothering with the login page.
   *
   * @param $template UserLoginTemplate object.
   * @public
   */
  function modifyUITemplate(&$template) {
    //disable the mail new password box
    $template->set('useemail', false);
    $template->set('create', false);
    $template->set('domain', false);
    $template->set('usedomain', false);
  }

  /**
   * Normalize user names to the mediawiki standard to prevent duplicate
   * accounts.
   *
   * @param $username String: username.
   * @return string
   * @public
   */
  function getCanonicalName($username) {
    // lowercase the username
    $username = strtolower($username);
    // uppercase first letter to make mediawiki happy
    $username[0] = strtoupper($username[0]);
    return $username;
  }
}