# -*- Mode: perl; tab-width: 4; indent-tabs-mode: nil; -*- # # This file is MPL/GPL dual-licensed under the following terms: # # The contents of this file are subject to the Mozilla Public License # Version 1.1 (the "License"); you may not use this file except in # compliance with the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See # the License for the specific language governing rights and # limitations under the License. # # The Original Code is PLIF 1.0. # The Initial Developer of the Original Code is Ian Hickson. # # Alternatively, the contents of this file may be used under the terms # of the GNU General Public License Version 2 or later (the "GPL"), in # which case the provisions of the GPL are applicable instead of those # above. If you wish to allow use of your version of this file only # under the terms of the GPL and not to allow others to use your # version of this file under the MPL, indicate your decision by # deleting the provisions above and replace them with the notice and # other provisions required by the GPL. If you do not delete the # provisions above, a recipient may use your version of this file # under either the MPL or the GPL. package PLIF::Output::Generic::Email; use strict; use vars qw(@ISA); use PLIF::Service; @ISA = qw(PLIF::Service); 1; sub provides { my $class = shift; my($service) = @_; return ($service eq 'output.generic.email' or $service eq 'protocol.email' or $service eq 'setup.configure' or $service eq 'dataSource.configuration.client' or $class->SUPER::provides($service)); } sub init { my $self = shift; my($app) = @_; $self->SUPER::init(@_); require Net::SMTP; import Net::SMTP; # DEPENDENCY eval { $app->getService('dataSource.configuration')->getSettings($app, $self, 'protocol.email'); }; if ($@) { $self->dump(9, "failed to get the SMTP configuration, not going to bother to connect: $@"); $self->handle(undef); } else { $self->open(); } } sub open { my $self = shift; my($app, $session, $string) = @_; eval { local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required (so it says in man perlfunc) local $^W = 0; # XXX shut up warnings in Net::SMTP $self->handle(Net::SMTP->new($self->host, 'Timeout' => $self->timeout)); alarm(0); }; if ($@) { if ($@ ne "alarm\n") { # propagate unexpected errors die($@); } # timed out } else { # everything ok } if (not defined($self->handle)) { $self->warn(4, 'Could not create the SMTP handle'); } } sub close { my $self = shift; if (defined($self->handle)) { $self->handle->quit(); } } # output.generic.email sub output { my $self = shift; my($app, $session, $string) = @_; $self->assert(defined($self->handle), 1, 'No SMTP handle, can\'t send mail'); eval { local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required (so it says in man perlfunc) $self->assert($self->handle->mail($self->from), 1, 'Could not start sending mail'); $self->assert($self->handle->to($session->getAddress('email')), 1, 'Could not set mail recipient (was going to send to '.($session->getAddress('email')).')'); $self->assert($self->handle->data($string), 1, 'Could not send mail body'); alarm(0); }; if ($@) { if ($@ ne "alarm\n") { # propagate unexpected errors die($@); } # timed out $self->error(1, 'Timed out while trying to send e-mail'); } else { # everything ok } } # protocol.email sub checkAddress { my $self = shift; my($app, $username) = @_; return (defined($username) and $username =~ m/^[^@\s]+@[^@\s]+\.[^@.\s]+$/os); # XXX this doesn't seem to be working: # $self->assert(defined($self->handle), 1, 'No SMTP handle, can\'t check address'); # $self->assert(defined($username), 1, 'Internal error: no username passed to checkAddress'); # my $result = $self->handle->verify($username); # return $result; } sub DESTROY { my $self = shift; $self->close(); $self->SUPER::DESTROY(@_); } # dataSource.configuration.client sub settings { return qw(host address timeout); } # setup.configure sub setupConfigure { my $self = shift; my($app) = @_; $self->dump(9, 'about to configure protocol.email...'); $app->output->setupProgress('protocol.email'); $self->close(); my $value; $value = $self->host; if (not defined($value)) { $value = 'localhost'; } $value = $app->input->getArgument('protocol.email.host', $value); if (not defined($value)) { return 'protocol.email.host'; } $self->host($value); $value = $self->address; if (defined($value)) { # default to existing value $value = $app->input->getArgument('protocol.email.address', $value); } else { # don't default to anything as our guess is most likely going # to be wrong: "$USER@`hostname`" is rarely correct. $value = $app->input->getArgument('protocol.email.address'); } if (not defined($value)) { return 'protocol.email.address'; } $self->address($value); $value = $self->timeout; if (not defined($value)) { $value = 5; } $value = $app->input->getArgument('protocol.email.timeout', $value); if (not defined($value)) { return 'protocol.email.timeout'; } $self->timeout($value); $self->open(); $app->getService('dataSource.configuration')->setSettings($app, $self, 'protocol.email'); $self->dump(9, 'done configuring protocol.email'); return; } sub hash { my $self = shift; return { 'address' => $self->address, # XXX RFC822 date -- need to provide this WITHOUT duplicating code in StdOut outputter }; }