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

NAME

POE::Component::Client::SMTP - Sending emails using POE

VERSION

Version 0.05

SYNOPSIS

    use POE::Component::Client::SMTP;

    POE::Component::Client::SMTP->send(
        alias               => 'smtp_client',
        smtp_sender         => 'foo@bar.com',   # will croak if emtpy
        smtp_recipient      => 'foo@baz.com',   # will croak if empty
        smtp_data           =>  $ref_to_scalar,
        smtp_timeout        => 30,              # seconds, defaults to 30
        debug               => 1,               # defaults to 0
        SMTPSendSuccessEvent => $success_event,
        SMTPSendFailureEvent => $failure_event,
    );

DESCRIPTION

POE::Component::Client::SMTP can be used to send asynchronous e-mail messages while your POE program still does something else in the meantime.

Currently it doesn't support ESMTP features like sending mails trough an encrypted connection, honouring SMTP authentification or fancy stuff like this. It just sends electronic messages trough a SMTP daemon.

METHODS

send

This method handles everything needed to send an email message (SMTP compliant, not ESMTP aware).

Arguments

alias

The component's alias

smtp_server

SMTP server address; defaults to localhost

smtp_ehlo

Message to be appended to the EHLO/HELO command; defaults to 'localhost'

smtp_port

SMTP server port; defaults to 25

smtp_bind_address

Parameter to be passed to POE::Wheel::SocketFactory as the BindAdress attribute.

smtp_sender

Email address from where the message originates; This option is mandatory

smtp_recipient

Email address for the message delivery; This option is mandatory

to

Recipient's name as it appears in the message's "To:" field; defaults to smtp_recipient

from

Sender's name as it appears in the message's "From:" field; defaults to smtp_sender

cc

Not implemented yet;

bcc

Not implemented yet;

subject

The subject of the message

smtp_body

The body of the message; must be a ref to a scalar or an array.

smtp_data

Scalar ref to the entire message, constructed outside the module; i.e. using a helper module like Email::MIME::Creator or MIME::Lite

Using this parameter results in ignoring POE::Component::Client::SMTP's parameters: to, from, subject

Note: that your POE program will block during the MIME creation.

SMTPSendSuccessEvent

Specify what event is to be sent back upon successful mail delivery

SMTPSendFailureEvent

Specify what event is to be sent back upon failure of mail delivery

smtp_timeout

Timeout to SMTP connection; defaults to 30 seconds

debug

Run in debug mode

Events

PoCo::Client::SMTP sends two events: SMTPSendFailureEvent and SMTPSendFailureEvent.

SMTPSendSuccessEvent

SMTPSendSuccessEvent is sent back to the session that spawned PoCo::Client::SMTP when the message is accepted by the SMTP server

SMTPSendFailureEvent

SMTPSendFailureEvent is sent back to the session that spawned PoCo::Client::SMTP when the message has not been delivered.

There are three main reasons for failure:

1) A connection could not be established

2) An error occured while network connection still active with the SMTP server

3) An error occured while talking with the SMTP daemon; this means that a misunderstanding between PoCo::Client::SMTP and the SMTP server has occured; if y ou feel this shouldn't have happened, fill a bug report along with the session log.

The SMTPSendFailureEvent handler receives the following parameters:

  • If ARG0 has a value of 1, then the error occured because of a SMTP session failure

    In this case, ARG1 contains the SMTP numeric code, ARG2 contains a string message giving a short explanation of the error.

  • If ARG0 has a value of 2, then the error occured because of a network failure

    In this case, ARG1, ARG2, and ARG3 have the values as returned by POE::Wheel::SocketFactory

  • If ARG0 has a value of 3, then the error occured because of a network failure

    In this case, ARG1, ARG2, and ARG3 have the values as returned by POE::Wheel::ReadWrite

  • If ARG0 has a value of 4, then the error occured because a timeout

    In this case, ARG1 holds the SMTP state the PoCoCl::SMTP is while timeouting

If running in debug mode, you will receive not only the last line received from the server, but the entire SMTP session log.

Examples

 # Send an email, having an attachments

 my $mail_body = create_message();

 POE::Session->create(
     inline_states => {
         _start       => \&start,
         send_mail    => \&send_mail,
         smtp_success => \&smtp_success,
         smtp_error   => \&smtp_error,
         _stop        => \&stop,
     },
     heap => { smtp_data => \$mail_body, },
 );
 
 POE::Kernel->run();
 
 sub start {
     $_[KERNEL]->yield("send_mail");
 }
 
 sub send_mail {
     POE::Component::Client::SMTP->send(
         alias          => 'smtp_client',
         smtp_server    => $server,
         smtp_port      => $port,
         smtp_sender    => $sender,
         smtp_recipient => $recipient,
         smtp_data      => $_[HEAP]->{'smtp_data'},
         smtp_timeout   => 10,
         debug          => 2,
 
         SMTPSendSuccessEvent => "smtp_success",
         SMTPSendFailureEvent => "smtp_error",
     );
 }

 sub create_message {
     my @parts;
     my $email;
     my $message;
 
     @parts = (
         Email::MIME->create(
             attributes => {
                 content_type => "text/plain",
                 disposition  => "attachment",
                 charset      => "US-ASCII",
             },
             body => "Hello there!",
         ),
 
         Email::MIME->create(
             attributes => {
                 filename     => 'picture.jpg',
                 content_type => "image/jpg",
                 encoding     => "quoted-printable",
                 name         => "Nokia.jpg",
             },
             # BLOCKING!
             body => io('picture.jpg')->all,
         ),
     );
 
     $email = Email::MIME->create(
         header => [ From => 'ultradm@cpan.org' ],
         parts  => [@parts],
         charset => "UTF-8",
     );
     $email->header_set('Date' => 'Thu, 23 Jun 2005 8:18:35 GMT');
 
     return $email->as_string;
 
 }

 # No use of external modules
 ...

 POE::Session->create(
   ...
   
     SMTP_Send_Success_Event => \&smtp_success,
     SMTP_Send_Failure_Event => \&smtp_failure,

   ...
   
 );

 ...

 $data = "Here is the info I want to send you:";
 $data .= "1 2 3 4 5 6";
 
 ...

 POE::Component::Client::SMTP->send(
    alias => 'smtp_client',
    smtp_server         => 'mail-host.foo.bar',
    smtp_port           => 25,
    smtp_sender         => 'me@foo.bar',
    smtp_recipient      => 'my_girlfriend@baz.com',
    from                => "My Name Here",
    to                  => "The Girls's Name",
    subject             => "I've just did your homework",
    smtp_body           =>  \$data,
    SMTPSendSuccessEvent => 'SMTP_Send_Success_Event',
    SMTPSendFailureEvent => 'SMTP_Send_Failure_Event',
 );

 ...
 
 sub smtp_success{
    Logger->log("MAIL sent successfully ");
    # do something useful here ...
 }

 sub smtp_failure{
    # Oops
    
    my $err_type = @_[ARG0];

    if ( $err_type eq == 1 ){
        my $error_code = @_[ARG1];
        my $error_message = @_[ARG2];
        Logger->log( "Received: [$err_code] $error_message from the server" );
    }elsif ( $err_type == 2 ) {
        
        ...

    }
 } 

Note

Note that SMTPSendSuccessEvent and SMTPSendFailureEvent are relative to what the SMTP server tells us; even if the SMTP server accepts the message fo r delivery, it is not guaranteed that the message actually gets delivered. In case an error occurs after the SMTP server accepted the message, an error mes sage will be sent back to the sender.

BUGS

* Beware that the interface can be changed in the future!

Please report any bugs or feature requests to bug-poe-component-client-smtp@rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=POE-Component-Client-SMTP. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

CAVEATS

Values given to send() are minimally checked.

The module assumes that the given smtp_server is a relay or the target server. This doesn't conform to the RFC 2821.

The MIME creation is left to an external module of your own choice. This means that the process will block until the attachment(s) is (are) slurped from the disk.

ACKNOWLEDGEMENTS

Thanks to Mike Schroeder for giving me some good ideas about PoCoClSMTP enhancements.

TODO

See the TODO file in the distribution.

Changes

See the Changes file in the distribution.

SEE ALSO

POE::Kernel, POE::Session, POE::Component, POE::Wheel::SocketFactory, POE::Wheel::ReadWrite

RFC 2821

AUTHOR

George Nistorica, ultradm@cpan.org

COPYRIGHT & LICENSE

Copyright 2005 George Nistorica, All Rights Reserved.

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