The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.


Net::Server::POP3::Skeleton - A simple skeleton POP3 server


  package MyServer;
  use base 'Net::Server::POP3::Skeleton';

  sub user {
    my $self = shift;
    my $name = shift;

    unless(defined $name) {
      $client->senderr("missing argument");

    $self->set('username', $name);
    $self->sendok("username accepted, send password");

  sub pass {
    my $self = shift;
    my $pass = shift;
    my $name = $self->get('username');

    # PASS not allowed before USER
    return $self->unknown() unless defined $name;

    return $self->senderr('invalid username or password')
      unless $Auth{$name} eq $pass;


  package main;

  $server = MyServer->new(
    greeting => "POP3 My server ready",



This module implements a bare-bones skeleton POP3 server. It is intended as a base class. You should inherit from this class (which, in turn, inherits from Net::Server::Fork). The only POP3 command implemented by this module is the QUIT command. All others should be implemented by your code as methods.

The purpose of this module is for easily creating non-standard POP3 servers in Perl. If you want a normal POP3 server (ie, one that simply serves emails from an MBOX or MailDirs file), you would probably be better off using one of the pre-built, faster C-based servers. If, on the other hand, you want to create a specialized POP3 server that, for instance, generates the content of the messages dynamically based on data from a website, this module is what you want.


When useing this module, you can specify an import option of nonFork. This will cause the module to inherit from Net::Server instead of Net::Server::Fork. See CAVEATS for more information



Creates a new instance of the server. This method can be inherited.

The following options are recognized:


Port to listen on. Defaults to 110.


Greeting to send clients when they connect. Defaults to "POP3 Net::Server::POP3::Skeleton ready"


Message sent to clients when they sign off. Defaults to "goodbye"


Server debug flag. Set to enable logging of extra information, and printing of some debug data to STDERR. Defaults to 0.


Number of seconds to wait after receiving data from the client before terminating the connection. This option is especially important when using the nonfork option, since a client who leaves the connection open prohibits others from connecting. Set to a false value to disable timeout. This uses alarm. Defaults to 60.


Transmit uncaught error messages to the client. If this option is set, uncaught, fatal error messages in the command handlers are passed along to the client. Otherwise, a generic message is sent. Defaults to 0.

Note that setting this option could present a security risk, as debugging info might be given to a potential attacker. It is recommended to leave this option disabled.


Capture otherwise fatal errors in command handlers. If this option is set, fatal errors in the command handlers are caught so that they don't bring down the server. Otherwise, the program halts on an uncaught error. Defaults to 1.


Handles connections accepted by Net::Server.

Commands are read from the client and dispatched appropriately (see "COMMANDS") until either the client disconnects, or $obj->{hasquit} becomes true (usually set by the QUIT command).

This method should be considered internal and should not be called (it will be called automatically by Net::Server). You probably will not ever need to overload this method.

state [NEWSTATE]

Set or return the current server state.

To change the server's state, pass the new state to this method. States can be upper, lower, or mixed case, and the AUTHORIZATION and TRANSACTION states may be abbreviated as AUTH and TRANS, respectively.

The new (or current if no new state is passed) is returned. The returned state is always the full state name, and is always upper case.

See "STATES" for more information.

add_command STATE[[, STATE]...], COMMAND

Example: $server->add_command(state => 'auth', command => 'hello');

Add a new command to the server's list of allowed commands.

You must used named-argument notation (see example above), and specify at least one state, and one command. The command will then be allowed in all of the states given.

Neither the state nor command name are case-sensitive.

Note that all the standard POP3 commands are already in the allowed commands list, so this method should only be called to add new, non-standard commands.

sendok MSG

Send to the client a positive response including the message passed to this method. The response will be of the form:


Where MSG is the message passed. The response will automatically have the end-of-line added. Do not add any end-of-line characters.

senderr MSG

Send to the client a negative response including the message passed to this method. The response will be of the form:


Where MSG is the message passed. The response will automatically have the end-of-line added. Do not add any end-of-line characters.

senddata MSG [DATA...]

Send to the client a positive response and some lines of data (eg, a message list, or message body).

For example:

  chomp(@lines = <$msgfh>);
  $server->senddata('message follows', @lines);

Note that end-of-line characters will be added to each line as it is sent, so they should be chomped.

send MSG

Send a raw message to the client. You should almost always use one of the other send- methods mentioned above. EOL's will be added to the end of each argument.

Note that, since STDIN and STDOUT are opened to the client socket, you could just write directly to them instead.


Flags the client connection to be closed. This should be called from your QUIT handler (assuming you don't use the one provided).


Stores some arbitrary data in the server object. The data can be accessed calling the get() method with NAME later.

DATA should be a single scalar value (though it can be a reference).

Returns DATA.

get NAME

Retrieves data stored earlier via set().


The server has four possible states: CONNECT, AUTHORIZATION, TRANSACTION, UPDATE, and DISCONNECT.

When a client connects to the server, it begins in the CONNECT state. $obj->connect()> is called, if implemented, and the state is then switched to AUTHENTICATION. When the user is authenticated, the state should then move into the TRANSACTION state.

If the user enters the QUIT command, the server will move into the UPDATE state and call $obj->commit(), which you should implement (see "COMMANDS"). In this state, any changes (such as deleting a message) should be committed. Note that this state can be skipped if the client disconnects without entering the QUIT command, in which case any changes should be rolled back during the DISCONNECT state.

After the client has disconnected, the server moves into the DISCONNECT state and calls $obj->disconnect(), which you may implement. This state can be entered either from the UPDATE state, or directly from the AUTHENTICATION or TRANSACTION states. In this state, any changes that were not previously committed should be rolled back.


Each line read from the user is split into two parts at the first group of whitespace encountered. The first part is the command name, and the possible second part is the parameter to the command. Any case is accepted in the command names, though the parameters to the commands may be case sensitive.

Before a command is dispatched, it is checked against a list of allowed commands. If the command is not in this list, an error is returned to the client and the command is not dispatched. This is for security reasons, as the command supplied by the user is used directly to dispatch the command.

A command is dispatched by looking for the similarly named (but lower case) method of the object. For example, when dispatching the USER command, the method called is $obj->user().

The QUIT command is already implemented by this package. It changes the state to UPDATE, calls $obj->commit(@_), and then flags the client's connection to be closed by calling $obj->close_client(). In almost all cases, this implementation of QUIT should be sufficient.


  • There are some issues with Net::Server::Fork on Win32. The tests for Net::Server are not designed to work under Win32, though Net::Server itself does. You should be able to skip the tests and it should work. However, see the next caveat.

  • If you are on Win32 and you don't specify the nonFork import option to use the non-forking personality of Net::Server, this module requires perl 5.8. This is because of a bug in the fork emulation of perl 5.6.1 that causes perl to crash when forking is used in conjunction with sockets.

  • I have had some issues with the forking personality of this module causing my programs to leak memory on Win32. I believe this has something to do with the way fork is emulated on Win32 using threads, but I have not looked into it exhaustively.

    I recommend you test the forking personality for memory leaks before deploying your program, and you may need to fall back to the nonforking personality.


  L<Net::Server>, L<IO::Select>, L<Carp>


Copyright (C) 2004, Cory Johns. All rights reserved.

This module is free software; you can redistribute and/or modify it under the same terms as Perl itself.

Address bug reports and comments to: Cory Johns <>