NAME

Net::QMTP - Quick Mail Transfer Protocol (QMTP) client

SYNOPSIS

use Net::QMTP;

$qmtp = Net::QMTP->new('mail.example.org');

$qmtp->sender('sender@example.org');
$qmtp->recipient('foo@example.org');
$qmtp->recipient('bar@example.org');

$qmtp->message($bodytext);

$qmtp->encoding('unix');
$qmtp->message_from_file($filename);

$qmtp->server('server.example.org');
$qmtp->new_envelope();
$qmtp->new_message();

$qmtp->reconnect()
$qmtp->send();
$qmtp->disconnect()

DESCRIPTION

This module implements an object orientated interface to a Quick Mail Transfer Protocol (QMTP) client which enables a perl program to send email by QMTP.

CONSTRUCTOR

new(HOST [, OPTIONS])

The new() constructor creates an new Net::QMTP object and returns a reference to it if successful, undef otherwise. HOST is the FQDN or IP address of the QMTP server to connect to and it is mandatory. By default, the TCP session is established when the object is created but it may be brought down and up at will by the disconnect() and reconnect() methods.

OPTIONS is an optional list of hash key/value pairs from the following list:

DeferConnect - set to 1 to disable automatic connection to the server when an object is created by new(). You must explicitly call reconnect() when you want to connect.

ConnectTimeout - change the default connection timeout associated with the IO::Socket socket we use. Specify this value in seconds.

Port - connect to the specified port on the QMTP server. The default is to connect to port 209.

Debug - set to 1 to enable debugging output.

See "EXAMPLES".

METHODS

sender(ADDRESS) sender()

Return the envelope sender for this object or set it to the supplied ADDRESS. Returns undef if the sender is not yet defined. An empty envelope sender is quite valid. If you want this, be sure to call sender() with an argument of an empty string.

recipient(ADDRESS) recipient()

If supplied, add ADDRESS to the list of envelope recipients. If not, return a reference to the current list of recipients. Returns a reference to an empty list if recipients have not yet been defined.

server(HOST) server()

If supplied, set HOST as the QMTP server this object will connect to. If not, return the current server. You will need to call reconnect() to give effect to your change.

message(TEXT) message()

If supplied, append TEXT to the message body. If not, return the current message body. It is the programmer's responsibility to create a valid message including appropriate RFC 2822/822 header lines. An empty message body is quite valid. If you want this, be sure to call message() with an argument of an empty string.

This method cannot be used on a object which has had a message body created by the message_from_file() method. Use new_message() to erase the current message contents.

message_from_file(FILE)

Use the contents of FILE as the message body. It is the programmer's responsibility to create a valid message in FILE including appropriate RFC 2822/822 header lines.

This method cannot be used on a object which has had a message body created by message(). Use new_message() to erase the current message contents.

encoding(TYPE) encoding()

Set the line-ending encoding for this object to one of:

unix - Unix-like line ending; lines are delimited by a line-feed character.

dos - DOS/Windows line ending; lines are delimited by a carraige-return line-feed character pair.

The constructor will make a guess at which encoding to use based on the value of $/. Call encoding() without an argument to get the current line-encoding. It will return a line-feed for unix, a carraige-return for dos or undef if the encoding couldn't be set.

Be sure the messages you create with message() and message_from_file() have approproiate line-endings.

send()

Send the message. It returns a reference to a hash or undef if the operation failed. The hash is keyed by recipient address. The value for each key is the response from the QMTP server, prepended with one of:

success: - the message was accepted for delivery

deferral: - temporary failure. The client should try again later

failure: - permanent failure. The message was not accepted and should not be tried again

See "EXAMPLES".

You almost certainly want to use reconnect() if send() fails as the server will be in an undetermined state and probably won't be able to accept a new message over the existing connection. The protocol allows a client to close the connection early; the server will discard the data already sent without attempting delivery.

new_envelope()

Reset the object's envelope information; sender and recipients. Does not affect the message body.

new_message()

Reset the object's message information; message text or message file. Does not affect the envelope.

disconnect()

Close the network connection to the object's server. Returns undef if this fails. The object's destructor will call disconnect() to be sure any open socket is closed cleanly when the object is destroyed.

reconnect()

Reestablish a network connection to the object's server, disconnecting the current connection if present. Returns undef if the operation could not be completed.

EXAMPLES

 use Net::QMTP;
 my $qmtp = Net::QMTP->new('server.example.org', Debug => 1) or die;

 $qmtp->sender('sender@example.org');
 $qmtp->recipient('joe@example.org');
 $qmtp->message('From: sender@example.org' . "\n" .
 		'To: joe@example.org' . "\n" .
		"Subject: QMTP test\n\n" .
		"Hi Joe!\nThis message was sent over QMTP");

 my $response = $qmtp->send() or die;
 foreach (keys %{ $response }) {
	 print $_ . ": " . ${$response}{$_} . "\n";
 }
 $qmtp->disconnect();

SEE ALSO

qmail-qmtpd(8), maildirqmtp(1), IO::Socket(3).

NOTES

The QMTP protocol is described in http://cr.yp.to/proto/qmtp.txt

QMTP is a replacement for SMTP and, as such, requires a QMTP server in addition to this client. The qmail MTA includes a QMTP server; qmail-qmtpd. Setting up the server is outside the scope of the module's documentation. See http://www.qmail.org/ for more QMTP information.

CAVEATS

Be aware of your line endings! \n means different things on different platforms.

If, on a Unix system, you say:

$qmtp->encoding("dos");

with the intention of later supplying a DOS formatted file, don't make the mistake of substituting message_from_file() with something like:

$qmtp->message($lineone . "\n" . $linetwo);

On Unix systems \n is (only) a line-feed. You should either explicitly change the encoding back to unix or supply your text with the proper encoding:

$qmtp->message($lineone . "\r\n" . $linetwo);

BUGS

Also known as the TODO list:

  • how to report an error message? An error() method?

  • a message body can't be created from message() and message_from_file()

  • socket timeout granularity? we don't handle a timeout well read timeout? alarm, SIG{ALRM} w/anon. sub to undef SOCKET?

  • client does NOT need to wait for a server response before sending another package (sec. 2) client's responsibility to avoid deadlock; if it sends a package before receiving all expected server responses, it must continuously watch for those responses (sec. 2)

  • we should write more tests

  • server is permitted to close the connection at any time. Any response not received by the client indicates a temp. failure (sec. 2)

  • a QMTP session should take at most 1 hour (sec. 2)

AUTHOR

James Raftery <james@now.ie>.