Mail::Spool::Node - Mail Spool inode encapsulization


Mail-Spool documentation Contained in the Mail-Spool distribution.

Index


Code Index:

NAME

Top

Mail::Spool::Node - Mail Spool inode encapsulization

SYNOPSIS

Top

  #!/usr/bin/perl -w
  package MySpoolNode;

  use Mail::Spool::Node;
  @ISA = qw(Mail::Spool::Node);

  # OR

  sub new {
    my $self = __PACKAGE__->SUPER::new(@_);

    ### do my own stuff here

    return $self;
  }

DESCRIPTION

Top

Mail::Spool::Node is intended as an encapsulization of an inode for use by Mail::Spool::Handle. It has been written with the intent of being able to use a database or other "file" system as a backend.

PROPERTIES

Top

Properties of Mail::Spool::Node are accessed methods of the same name. They may be set by calling the method and passing the new value as an argument. For example:

  my $from = $self->from;
  $self->from($new_from);

The following properties are available:

to

Returns the "To" email address of this node.

from

Returns the "From" email address of this node.

id

Returns the message id of this node.

time

Returns the time this node was placed in the spool.

msh

Returns the mail spool handle that this node is in.

name

Returns the filename of this node in the mail spool handle directory.

METHODS

Top

new

Returns a Mail::Spool::Node object. Arguments in the form of a hash or hash ref are used to populate the object. Also calls load_node_properties.

can_process

Returns whether the node is eligible for processing. This is based upon how long it has been in the mail spool handle.

size

Returns the size of the node in bytes.

lock_node

Locks the node to prevent any other process from trying to write to it. This is done via File::NFSLock. Returns the lock object.

lock_error

Returns the error of File::NFSLock should something happen during the locking process.

filehandle

Returns an IO::Handle style object opened to the filename of this node.

filename

Returns the filename of this node.

fallback_filename

Returns the place to put this file in case the node could not be sent right now. Returns undef if fallback cannot proceed (undeliverable).

fallback

Actually perform the fallback operation.

delete_node

Unlink the node from the directory.

SEE ALSO

Top

Please see also Mail::Spool, Mail::Spool::Handle.

COPYRIGHT

Top


Mail-Spool documentation Contained in the Mail-Spool distribution.

# -*- perl -*-
#
#  Mail::Spool::Node - adpO - Mail::Spool inode encapsulization
#
#  $Id: Node.pm,v 1.1 2001/12/08 05:52:59 rhandom Exp $
#
#  Copyright (C) 2001, Paul T Seamons
#                      paul@seamons.com
#                      http://seamons.com/
#
#  This package may be distributed under the terms of either the
#  GNU General Public License
#    or the
#  Perl Artistic License
#
#  All rights reserved.
#
#  Please read the perldoc Mail::Spool::Node
#
################################################################

package Mail::Spool::Node;

use strict;
use vars qw($AUTOLOAD $VERSION);
use File::NFSLock 1.10 ();
use IO::File ();

$VERSION = $Mail::Spool::VERSION;

###----------------------------------------------------------------###

sub new {
  my $type  = shift;
  my $class = ref($type) || $type || __PACKAGE__;
  my $self  = @_ && ref($_[0]) ? shift() : {@_};

  bless $self, $class;

  if( ! $self->load_node_properties ){
    return undef;
  }

  return $self;
}

###----------------------------------------------------------------###

sub load_node_properties {
  my $node = shift;
  
  return undef if $node->name =~ /\.NFSLock$/i; # skip lock files
  return undef if $node->name =~ /^\.+$/;       # skip root directory nodes
  return undef if -d $node->filename;           # skip directories

  # looking for stuff like 995909015-80EA68E2D942BA85-forward@b.c-paul@seamons.com
  if( $node->name !~ /^(\d+)-([^\-]+)-([^\-]+)-([^\-]*)$/ ){
    die "Strange file found in spool dir \"".$node->filename."\"\n";
  }

  my($time,$message_id,$to_addr,$from_addr) = ($1,$2,$3,$4);
  $from_addr ||= ''; # allow for undeliverables

  ### unencode the to and from
  foreach ( $to_addr, $from_addr ){
    s/%([a-f0-9]{2})/chr(hex($1))/eig;
  }

  ### store some properties
  $node->time( $time );
  $node->id( $message_id );
  $node->to( $to_addr );
  $node->from( $from_addr );
  
  return 1;
}

###----------------------------------------------------------------###

### is this node up for processing
sub can_process {
  my $node = shift;

  die "No wait property found in mail spool handle"
    if ! defined $node->msh->wait;

  return (time() - $node->time >= $node->msh->wait);
}

sub size {
  my $node = shift;
  return -s $node->filename || 0;
}

###----------------------------------------------------------------###

### exclusive lock (NFS or not)
sub lock_node {
  my $node = shift;
  my $lock = File::NFSLock->new($node->filename,
                                "NONBLOCKING",
                                0,
                                ($node->msh->spool->max_connection_time+2),
                                );
  $node->{lock_error} = $File::NFSLock::errstr;
  return $lock;
}

sub lock_error {
  return shift()->{lock_error};
}

###----------------------------------------------------------------###

sub filehandle {
  my $node = shift;
  my $mode = shift;
  $mode = 'r' if ! $mode || $mode !~ /^(a|w|r|wr)$/;

  my $fh = IO::File->new($node->filename,$mode);

  if( ! $fh ){
    warn "Couldn't open file ".$node->filename." [$!]";
    return undef;
  }
  return $fh;
}

sub filename {
  my $node = shift;
  return $node->msh->spool_dir .'/'. $node->name;
}

sub fallback_filename {
  my $node = shift;
  my $name = join("-",time(),$node->id,$node->to,$node->from);
  return undef if ! defined $node->msh->fallback_dir;
  return $node->msh->fallback_dir .'/'. $name;
}

sub fallback {
  my $node = shift;
  
  if( ! rename($node->filename,
               $node->fallback_filename) ){
    warn "Couldn't rename ".$node->filename." to ".$node->fallback_filename." [$!]";
    unlink $node->filename; # maybe some more error checking
  }
}

sub delete_node {
  my $node = shift;
  unlink $node->filename;
}

###----------------------------------------------------------------###

sub AUTOLOAD {
  my $node = shift;
  my ($method) = $AUTOLOAD =~ /([^:]+)$/;
  die "No method found in \$AUTOLOAD \"$AUTOLOAD\"" unless defined $method;
  
  ### allow for dynamic installation of some subs
  if( $method =~ /^(to|from|id|time|msh|name)$/ ){
    no strict 'refs';
    * { __PACKAGE__ ."::". $method } = sub {
      my $self = shift;
      my $val = $self->{$method};
      $self->{$method} = shift if @_;
      return $val;
    };
    use strict 'refs';
    
    ### now that it is installed, call it again
    return $node->$method( @_ );
  }

  die "Unknown method \"$method\"";
}

sub DESTROY {}

1;



__END__