The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
<HTML>
<HEAD>
<TITLE>Net::Server::POP3</TITLE>
</HEAD>
<BODY BGCOLOR="#ffffff" TEXT="#000000">
<UL>
<LI><A HREF="#NAME">NAME

</A></LI>
<LI><A HREF="#SYNOPSIS">SYNOPSIS

</A></LI>
<LI><A HREF="#DESCRIPTION">DESCRIPTION

</A></LI>
<LI><A HREF="#USAGE">USAGE

</A></LI>
<LI><A HREF="#REQUIRES">REQUIRES

</A></LI>
<LI><A HREF="#BUGS">BUGS

</A></LI>
<LI><A HREF="#SUPPORT">SUPPORT

</A></LI>
<LI><A HREF="#AUTHOR">AUTHOR

</A></LI>
<LI><A HREF="#COPYRIGHT">COPYRIGHT

</A></LI>
<LI><A HREF="#SEE%20ALSO">SEE ALSO

</A></LI>
</UL>
<HR>
<H1><A NAME="NAME">NAME

</A></H1>

<P>Net::Server::POP3 - The Server Side of the POP3 Protocol for email

</P><H1><A NAME="SYNOPSIS">SYNOPSIS

</A></H1>

<PRE>  use Net::Server::POP3;
  my $server = Net::Server::POP3-&gt;new(
    severopts    =&gt; \%options,
    authenticate =&gt; \&amp;auth,
    list         =&gt; \&amp;list,
    retrieve     =&gt; \&amp;retrieve,
    delete       =&gt; \&amp;delete,
    size         =&gt; \&amp;size,
    welcome      =&gt; &quot;Welcome to my mail server.&quot;,
  );
  $server-&gt;startserver();</PRE>
<H1><A NAME="DESCRIPTION">DESCRIPTION

</A></H1>

<P>Net::Server::POP3 is intended to handle the nitty-gritty details of
talking to mail clients, so that in writing a custom POP3 server you
don't have to actually read RFC documents.  The backend things (such
as where mail comes from and what messages are in the user's mailbox
at any given time) are left up to your code (or another module), but
this module handles the POP3 protocol for you.  Also, the details of
listening for client connections and so on are handled by Net::Server.

</P>
<P>This approach allows for some flexibility.  Your code may choose to
generate messages on the fly, proxy them from another mail server,
retrieve them from a local maildir or mailbox of some kind, or
whatever.  See the sample scripts in this distribution for examples.

</P>
<P>This code is still very much beta.  There are known bugs.  Some things
(e.g., APOP) haven't even been implemented yet.  You have been warned.
See the Bugs section for details.

</P>
<P>The code as it stands now works, for some definition of &quot;works&quot;.  With
the included simpletest.pl script I have successfully served test
messages that I have retrieved with Mozilla Mail/News.  Additionally,
with the included proxytest.pl script I have successfully proxied mail
from an ISP mail server to a client.  However, much remains to be done.

</P>
<P>It is strongly recommended to run with Taint checking enabled.

</P>
<P>These are the RFCs that I know about and intend to implement:

</P><DL><DT><A NAME="http%3a%2f%2fwww.faqs.org%2frfcs%2frfc1939.html">http://www.faqs.org/rfcs/rfc1939.html

</A></DT>
<DD>
</DD>
<DT><A NAME="http%3a%2f%2fwww.faqs.org%2frfcs%2frfc2449.html">http://www.faqs.org/rfcs/rfc2449.html


</A></DT>
<DD>
</DD>
</DL>

<P>If you know of any other RFCs that seem pertinent, let me know.

</P><H1><A NAME="USAGE">USAGE

</A></H1>

<P>This module is designed to be the server/daemon itself and so to
handle all of the communication to/from the client(s).  The actual
details of obtaining, storing, and keeping track of messages are left
to other modules or to the user's own code.  (See the sample scripts
simpletest.pl (simple) and proxytest.pl (somewhat more involved) in
this distribution for examples.)

</P>
<P>The main method is startserver(), which starts the server.  The
following named arguments may be passed either to new() or to
startserver().  All callbacks should be passed as coderefs.
If you pass an argument to new() and then pass an argument of
the same name to startserver(), the one passed to startserver()
overrides the one passed to new().  stopserver() has not been
implemented yet and so neither has restartserver(), but they
are planned for an eventual future version.

</P><DL><DT><A NAME="EOL">EOL

</A></DT>
<DD>

<P>A string containing the characters that should be printed on a socket
to cause perl to emit an RFC-compliant CRLF.  The new default is
&quot;\015\012&quot;, which theoretically should work perfectly everywhere, from
what I have read, but if you get mangled newlines, this may be why.
This new default needs testing on as many platforms as possible to
ensure that it is, in fact, correct everywhere.

</P>
<P>The default used to be &quot;\n&quot;, which worked on my development platform
(Linux Mandrake 9.2).  On some systems this needed to be set to
&quot;\r\n&quot;.  Setting it to the wrong thing caused breakage either way.  If
the default doesn't work for you, experiment.  If you set it to &quot;\r\n&quot;
on systems where &quot;\n&quot; will work, you get extraneous ^M characters on
the ends of all the lines at the recieving end, which among other
things can cause most of the headers not to be recognized as such and
instead to be displayed in the body, depending on the mail client.
Going the other way, if you set it to &quot;\n&quot; on platforms where &quot;\r\n&quot;
would work correctly, the whole thing may just not work at all, or
other weirdness may ensue, such as the entire message (headers, body,
and all) appearing on one line.

</P>
<P>The EOL string is optional; you only need to specify it if the default
is the wrong value.

</P></DD>
<DT><A NAME="port">port

</A></DT>
<DD>

<P>The port number to listen on.  110 is the default.  The user or group
you are running as needs permission to listen on this port.

</P>
<P>The port number is optional.  You only need to specify it if you want
to listen on a different port than 110.

</P></DD>
<DT><A NAME="servertype">servertype

</A></DT>
<DD>

<P>A type of server implemented by Net::Server (q.v.)  The default is
'Fork', which is suitable for installations with a small number of
users.

</P>
<P>The servertype is optional.  You only need to specify it if you want
to use a different type other than 'Fork'.

</P></DD>
<DT><A NAME="serveropts">serveropts

</A></DT>
<DD>

<P>A hashref containing extra named arguments to pass to Net::Server.
Particularly recommended for security reasons are user, group, and
chroot.  See the docs for Net::Server for more information.

</P>
<P>The serveropts hashref is optional.  You only need to supply it if you
have optional arguments to pass through to Net::Server.

</P></DD>
<DT><A NAME="connect">connect

</A></DT>
<DD>

<P>This callback, if supplied, will be called when a client connects.
This is the recommended place to allocate resources such as a database
connection handle.

</P>
<P>The connect callback is optional; you only need to supply it if you
have setup to do when a client connects.

</P></DD>
<DT><A NAME="disconnect">disconnect

</A></DT>
<DD>

<P>This callback, if supplied, is called when the client disconnects.  If
there is any cleanup to do, this is the place to do it.  Note that
message deletion should not be handled here, but in the delete callback.

</P>
<P>The disconnect callback is optional; you only need to supply it if you
have cleanup to do when a client disconnects.

</P></DD>
<DT><A NAME="authenticate">authenticate

</A></DT>
<DD>

<P>The authenticate callback is passed a username, password, and IP
address.  If the username and password are valid and the user is
allowed to connect from that address and authenticate by the USER/PASS
method, then the callback should try to get a changelock on the
mailbox and return 1 if successful; it must return something other
than 1 if any of that fails.  (Returning 0 does not specify the
details of what went wrong; other values may in future versions have
particular meanings.)

</P>
<P>The authenticate callback is technically optional, but you need to
supply it if you want any users to be able to log in using the USER
and PASS commands.

</P></DD>
<DT><A NAME="apop">apop

</A></DT>
<DD>

<P>Optional callback for handling APOP auth.  If the user attempts APOP
auth and this callback exists, it will be passed the username, the
digest sent by the user, and the server greeting.  If the user's
digest is indeed the MD5 digest of the concatenation of the server
greeting and the shared secret for that user, then the callback
should attempt to lock the mailbox and return true if successful;
otherwise, return false.

</P>
<P>The apop callback is only needed if you want to supply APOP
authentication.

</P>
<P>This is not implemented yet, but I plan to implement it in an
eventual future version.

</P></DD>
<DT><A NAME="list">list

</A></DT>
<DD>

<P>The list callback, given a valid, authenticated username, must return
a list of message-ids of available messages.  (Most implementations
will ingore the username, since they will already be locked in to the
correct mailbox after authentication.  That's fine.  The username is
passed as a help for minimalist implementations.)

</P>
<P>The list callback is required.

</P></DD>
<DT><A NAME="size">size

</A></DT>
<DD>

<P>The size callback if it exists will be passed a valid, authenticated
username and a message id (from the list returned by the list
callback) and must return the message size in octets.  If the size
callback does not exist, the size will be calculated using the
retrieve callback, which is inefficient.  Providing the size callback
will prevent the retrieve callback from being called unnecessarily,
thus improving performance.  (Most implementations will ingore the
username, since they will already be locked in to the correct mailbox
after authentication.  That's fine.  The username is passed as a help
for minimalist implementations.)

</P>
<P>Note that very early versions passed only the message id, not the
username, to the size callback.  This changed in 0.0005, breaking
backward-compatibility for the size callback.

</P>
<P>The size callback is optional.  You only need to provide it if you
care about performance.

</P></DD>
<DT><A NAME="retrieve">retrieve

</A></DT>
<DD>

<P>The retrieve callback must accept a valid, authenticated username and
a message-id (from the list returned by the list callback) and must
return the message as a string.  (Most implementations will ingore the
username, since they will already be locked in to the correct mailbox
after authentication.  That's fine.  The username is passed as a help
for minimalist implementations.)

</P>
<P>The retrieve callback is required.

</P></DD>
<DT><A NAME="delete">delete

</A></DT>
<DD>

<P>The delete callback gets called with a valid, authenticated username
and a message-id that the user/client has asked to delete.  (Most
implementations will ingore the username, since they will already be
locked in to the correct mailbox after authentication.  That's fine.
The username is passed as a help for minimalist implementations.)

</P>
<P>The delete callback is only called in cases where the POP3 protocol
says the message should actually be deleted.  If the connection
terminates abnormally before entering the UPDATE state, the callback
is not called, so code using this module does not need to concern
itself with marking and unmarking for deletion.  When called, it can
do whatever it wants, such as actually delete the message, archive it
permanently, mark it as no longer to be given to this specific user,
or whatever.

</P>
<P>This callback is technically optional, but you'll need to supply one
if you want to know when to remove messages from the user's maildrop.

</P></DD>
<DT><A NAME="welcome">welcome

</A></DT>
<DD>

<P>This string is used as the welcome string sent to the client upon
connection.  It must not be longer than 506 bytes, for arcane reasons
involving RFC1939.  (startserver will generate a warning at runtime if
it is too long.)

</P>
<P>The welcome string is optional; a default welcome is supplied.

</P></DD>
<DT><A NAME="logindelay">logindelay

</A></DT>
<DD>

<P>If a number is given, it will be announced in the capabilities list as
the minimum delay (in seconds) between successive logins by the same
user (which applies to any user).  This does NOT enforce the delay; it
only causes it to be announced in the capabilities list.  The
authenticate callback is responsible for enforcement of the delay.
The delay SHOULD be enforced if it is announced (RFC 2449).

</P>
<P>If the delay may vary per user, logindelay should be a callback
routine.  If the callback is passed no arguments, it is being asked
for the maximum delay for all users; if it is passed an argument, this
will be a valid, authenticated username and the callback should return
the delay for that particular user.  Either way, the return value
should be a number of seconds.  Again, this does NOT enforce the
delay; it only causes it to be announced in the capabilities list.
(Some clients may not even ask for the capabilities list, if they do
not implement POP3 Extensions (RFC 2449).)

</P>
<P>The default is not to announce any particular delay.

</P></DD>
<DT><A NAME="expiretime">expiretime

</A></DT>
<DD>

<P>If a number or the string 'NEVER' is given, it will be announced in
the capabilities list as the length of time a message may remain on
the server before it expires and may be automatically deleted by the
server.  (The number is a whole number of days.)

</P>
<P>This does NOT actually delete anything; it just announces the
timeframe to the client.  Clients that do not support POP3 Extensions
will not get this announcement.  'NEVER' means the server will never
expire messages; 0 means that expiration is immanent and the client
should not count on leaving messages on the server.  0 should be
announced for example if the mere act of retrieving a message may
cause it to expire shortly afterward.

</P>
<P>If the message expiration time may vary by user, expiretime should be
a callback routine.  If the callback is passed no arguments, it is
being asked for the minimum expiration time for all users, which it
should return (as a whole number of days; 0 is acceptable); if it is
passed an argument, this will be a valid, authenticated username and
the callback should return the expiration time for this particular
user, either as a whole number of days or the string 'NEVER'.

</P>
<P>The default is not to announce an expiration time.

</P></DD>
<DT><A NAME="DEBUG">DEBUG

</A></DT>
<DD>

<P>Set the level of debugging information desired on standard output.
undef means no debug info at all.  0 means only warn when the client
uses commands that are not understood.  A value of 1 produces various
other information about functions that are being called, arguments
they are passed, and so on.  A value of 2 also uses Data::Dumper to
show the state of certain data structures at various times, possibly
including entire messages, possibly more than once per message.  This
can get really verbose.  A value of 3 is even more verbose and really
doesn't add anything for debugging your code.  (Level 3 is intended
for debugging the module itself.  Actually, all of it was mainly
intended for that originally, but the lower levels also proved useful
for debugging sample scripts.)

</P>
<P>The DEBUG level is optional.  The default is 0.

</P></DD>
<DT><A NAME="linetimeout">linetimeout

</A></DT>
<DD>

<P>Give the mail client (or user) this many seconds to type or send each
line.  My reading of RFC1939 is that this shouldn't be less than ten
minutes (at least, between commands), but Net::Server::POP3 does not
enforce this minimum.

</P>
<P>The linetimeout is optional.  The default is currently 600 (ten
minutes), the minimum specified by the RFC.  The default value may
change in a future version.

</P></DD>
</DL>
<H1><A NAME="REQUIRES">REQUIRES

</A></H1>

<P>Net::Server, Exporter

</P><H1><A NAME="BUGS">BUGS

</A></H1>
<DL><DT><A NAME="DEBUG%20makes%20authentication%20fail">DEBUG makes authentication fail

</A></DT>
<DD>
This is really bad, and I hope to fix it very soon.  My apologies to
anyone who has been bitten by this.  The gplproxy example has
uncovered a bug wherein passing a nonzero value for DEBUG to new (or
probably also startserver) causes authentication to fail.  Fixing this
will be top priority for the next release.

</DD>
<DT><A NAME="APOP%20is%20not%20implemented%20yet.">APOP is not implemented yet.

</A></DT>
<DD>
</DD>
<DT><A NAME="stopserver%20and%20restartserver%20are%20not%20implemented">stopserver and restartserver are not implemented

</A></DT>
<DD>
For now, the only way to stop the server is to kill it.  Actually,
this may not be true; I'm still investigating this stuff about the
Net::Server module.

</DD>
<DT><A NAME="UIDL">UIDL

</A></DT>
<DD>
The UIDL implementation uses the message-id as the unique id, rather
than calculating a hash as suggested by RFC 1939.  In practice, this
seems to be what my ISP's mail server does (it calls itself
InterMail), which has worked with every client I've thrown at it, so
it should be mostly okay, but it's not strictly up to spec I think and
may be changed in a later version.  I intend to investigate what other
major POP3 servers do in this regard before making any changes; if you
happen to know e.g. what the POP3 servers do that are usually used
with Postfix, Exim, or Qmail, et cetera, drop me a line and let me
know.  Data about what the POP3 servers used by various ISPs do would
also be appreciated.

</DD>
<DT><A NAME="threads">threads

</A></DT>
<DD>
The issue of thread safety has not even been considered, other than to
include this warning that it has not been considered.  If someone who
actually has experience with threaded programming wants to look it
over, that would be great; otherwise, I may try to get to it
eventually, but for now it's several items down the Todo list.

</DD>
<DT><A NAME="character%20handling">character handling

</A></DT>
<DD>
My code all assumes that each character is stored in one byte.  I
suspect most mail servers do this, but if your code that uses the
module produces any Unicode strings, this could make issues.  The
sample proxy modules are naively assuming that Mail::POP3Client
returns strings with octet symantics; I do not know whether this is
actually the case.  At minimum, this could cause the sizes of the
messages to be reported incorrectly (e.g. by LIST).

</DD>
<DT><A NAME="client%20IP%20address">client IP address

</A></DT>
<DD>
The authenticate callback was not passed the client's IP address as
documented, but I think this is fixed now.

</DD>
<DT><A NAME="line%20endings">line endings

</A></DT>
<DD>

<P>I think the new default value for EOL fixes this bug, but I'm
leaving the old information here until I confirm that:

</P>
<P>Depending on your platform and possibly your perl version, you might
need to set the EOL to &quot;\r\n&quot; instead of the default &quot;\n&quot;.  However,
if your perl version already handles this the way mine does (Linux
Mandrake 9.2), setting it to &quot;\r\n&quot; will break it, resulting in the
mail client only seeing the first header you send as a header and
viewing the rest of the headers as part of the body, which is ugly; in
that case you should use &quot;\n&quot;.  You can now pass an EOL parameter to
new or to startserver for this, until I figure out how to fix it for
real.  The default is &quot;\n&quot; if you don't specify.

</P></DD>
<DT><A NAME="Caveat%20user">Caveat user

</A></DT>
<DD>

<P>There may be other bugs as well; this is not release-quality code yet.
Significant changes may be made to the code interface before release
quality is reached, so if you use this module now you may have to
change your code when you upgrade.

</P>
<P>The Todo list is long, and contributions are welcome, especially code
but also documentation, sample scripts, or other information such as
how the module works with various clients, what platforms and perl
versions need which setting for EOL (and how to determine this at
runtime), what POP3 servers do what for the UIDL, ...

</P></DD>
</DL>
<H1><A NAME="SUPPORT">SUPPORT

</A></H1>

<P>Use the source, Luke.  You can also contact the author with questions,
but the code is supplied on an as-is basis with no warranty.  I will
try to answer any questions, but this is spare-time stuff for me.

</P><H1><A NAME="AUTHOR">AUTHOR

</A></H1>

<PRE>	Jonadab the Unsightly One (Nathan Eady)
	jonadab@bright.net
	http://www.bright.net/~jonadab/</PRE>
<H1><A NAME="COPYRIGHT">COPYRIGHT

</A></H1>

<P>This program is free software licensed under the terms of...

</P>
<PRE>	The BSD License</PRE>

<P>The full text of the license can be found in the
LICENSE file included with this module.

</P>
<P>Note that the modules (such as Net::Server) that are used by this
module or by the sample scripts are covered under their respective
license agreements and are not governed by the license of
Net::Server::POP3.

</P><H1><A NAME="SEE%20ALSO">SEE ALSO

</A></H1>

<PRE>  perl(1)
  Net::Server http://search.cpan.org/search?query=Net::Server
  Mail::POP3Client http://search.cpan.org/search?query=Mail::POP3Client
  The simpletest.pl script included in the scripts directory in this distribution.
  The proxytest.pl script also included in the scripts directory in this distribution.</PRE>

<P><A HREF="http://search.cpan.org/search?query=Net::Server">Net::Server</A>

</P>
<P><A HREF="http://search.cpan.org/search?query=Mail::POP3Client">Mail::POP3Client</A>

</P>
<P><A HREF="http://search.cpan.org/src/JONADAB/Net-Server-POP3-0.0009/scripts/simpletest.pl">simpletest.pl</A>

</P>
<P><A HREF="http://search.cpan.org/src/JONADAB/Net-Server-POP3-0.0009/scripts/proxytest.pl">proxytest.pl</A>

</P>
<P><A HREF="http://search.cpan.org/src/JONADAB/Net-Server-POP3-0.0009/scripts/gplproxy.pl">gplproxy.pl</A>

</P>
<P>For a more minimalist framework with a different interface, see
<A HREF="http://perlmonks.org/index.pl?node_id=342754">Net::Server::POP3::Skeleton</A>

</P>
</BODY>
</HTML>