package Contenido::Mail; use strict; use warnings; use Net::SMTP; use MIME::Lite; use MIME::Base64; use Data::Dumper; use parent 'Contenido::Accessor'; __PACKAGE__->mk_accessors(qw(enable mailer from login password server hello timeout ssl port)); use Contenido::Globals; use Contenido::Email; sub new { my ($proto, $args) = @_; my $class = ref($proto) || $proto; $args //= {}; my $self = {}; bless $self, $class; $self->enable( $state->{email_enable} ); if ( $self->enable ) { $self->mailer( $state->{email_mailer} ); $self->from( $state->{email_from} ); $self->login( delete $args->{login} || $state->{email_auth_login} ); $self->password( delete $args->{password} || $state->{email_auth_password} ); if ( $self->mailer eq 'smtp' ) { $self->server( $state->{email_smtp_server} ); $self->hello( $state->{email_smtp_hello} ); $self->timeout( $state->{email_smtp_timeout} ); $self->ssl( $state->{email_smtp_ssl} ); $self->port( $state->{email_smtp_port} ); } } warn Dumper $self if $DEBUG; return $self; } sub send { return unless @_; my $self; if ( ref $_[0] eq 'Contenido::Mail' ) { $self = shift; } elsif ( !ref $_[0] && $_[0] eq 'Contenido::Mail' ) { my $class = shift; $self = $class->new; } else { $self = Contenido::Mail->new; } my $opts = shift // {}; my $debug = $state->development || $DEBUG || $opts->{debug} ? 1 : 0; my $email = delete $opts->{email} // return undef; warn Dumper $email if $debug; return unless ref $email && exists $email->{to} && $email->{subject} && $email->{body}; my $etype = delete $opts->{etype} // 'mixed'; my $subject = $email->{subject}; $subject = MIME::Base64::encode($subject); $subject =~ s/\s//sgi; $subject = '=?utf-8?B?'.$subject.'?='; my $error; my $emailfrom; if ( $email->{from} ) { my ($from, $efrom) = $email->{from} =~ /^(.*?)<(.*?)>/ ? ($1, $2) : $email->{from} =~ /<(.*?)>/ ? ('',$1) : ('',$email->{from}); if ( $from ) { $from = MIME::Base64::encode($from); $from =~ s/\s+$//si; $from = '=?utf-8?B?'.$from.'?='; $emailfrom = $from.' <'.$efrom.'>'; } else { $emailfrom = $efrom; } } elsif ( $self->from ) { $emailfrom = $self->from; } my ($emailto, @to); if ( ref $email->{to} eq 'ARRAY' ) { foreach my $tostr ( @{$email->{to}} ) { my ($to, $eto) = $tostr =~ /^(.*?)<(.*?)>/ ? ($1, $2) : $tostr =~ /<(.*?)>/ ? ('',$1) : ('',$tostr); if ( $to ) { $to = MIME::Base64::encode($to); $to =~ s/\s+$//si; $to = '=?utf-8?B?'.$to.'?='; push @to, $to.' <'.$eto.'>'; } else { push @to, '<'.$eto.'>'; } } $emailto = join ', ', @to; } else { my ($to, $eto) = $email->{to} =~ /^(.*?)<(.*?)>/ ? ($1, $2) : $email->{to} =~ /<(.*?)>/ ? ('',$1) : ('',$email->{to}); if ( $to ) { $to = MIME::Base64::encode($to); $to =~ s/\s+$//si; $to = '=?utf-8?B?'.$to.'?='; $emailto = $to.' <'.$eto.'>'; } else { $emailto = $eto; } push @to, $emailto; } my $ccmail; if ( exists $email->{cc} && ref $email->{cc} eq 'ARRAY' ) { my @cc; foreach my $cc ( @{ $email->{cc}} ) { my ($cce, $ecce) = $cc =~ /^(.*?)<(.*?)>/ ? ($1, $2) : $cc =~ /<(.*?)>/ ? ('',$1) : ('',$cc); if ( $cce ) { $cce = MIME::Base64::encode($cce); $cce =~ s/\s+$//si; $cce = '=?utf-8?B?'.$cce.'?='; push @to, $cce.' <'.$ecce.'>'; push @cc, $cce.' <'.$ecce.'>'; } else { push @to, '<'.$ecce.'>'; push @cc, '<'.$ecce.'>'; } } $ccmail = join ', ', @cc; } elsif ( exists $email->{cc} && $email->{cc} ) { my ($cce, $ecce) = $email->{cc} =~ /^(.*?)<(.*?)>/ ? ($1, $2) : $email->{cc} =~ /<(.*?)>/ ? ('',$1) : ('',$email->{cc}); if ( $cce ) { $cce = MIME::Base64::encode($cce); $cce =~ s/\s+$//si; $cce = '=?utf-8?B?'.$cce.'?='; $ccmail = $cce.' <'.$ecce.'>'; } else { $ccmail = $ecce; } push @to, $ccmail; } my $body = $email->{body}; warn Dumper($email) if $debug; my $dt = Contenido::DateTime->new; $dt->set_locale('en_EN'); my $pdate = $dt->strftime("%a, %d %b %Y %H:%M:%S %z"); my $msg = MIME::Lite->new( To => $emailto, From => $emailfrom, $ccmail ? ( Cc => $ccmail ) : (), Subject => $subject, # Encoding=> 'binary', Date => $pdate, Type => ($etype eq 'mixed' ? 'multipart/mixed' : $etype eq 'related' ? 'multipart/related;type="multipart/alternative";charset="utf-8"' : $etype), ); $msg->attach( 'Type' => 'text/html;charset="utf-8"', 'Data' => $body, 'Disposition' => '', ); my $email_body = $msg->as_string; if ( $self->mailer eq 'smtp' ) { my $mailer = Net::SMTP->new( $self->{server}, $self->{hello} ? (Hello => $self->{hello}) : (), Port => $self->{port}, Timeout => $self->{timeout}, SSL => $self->{ssl}, Debug => $debug, ); warn Dumper $mailer if $debug; if ( ref $mailer ) { if ( $self->{login} && $self->{password} ) { $mailer->auth( $self->{login}, $self->{password} ); unless ( $mailer->ok ) { $error = $mailer->message; } } unless ( $error ) { $mailer->mail( $emailfrom ); unless ( $mailer->ok ) { $error = $mailer->message; } } unless ( $error ) { $mailer->to( @to ); unless ( $mailer->ok ) { $error = $mailer->message; } } unless ( $error ) { $mailer->data; $mailer->datasend( $email_body ); $mailer->dataend; } $mailer->quit; } else { $error = "MAIL ERROR! Can't create SMTP object"; warn "$error\n"; } } return $error; } sub add { return unless @_; my $self; if ( ref $_[0] eq 'Contenido::Mail' ) { $self = shift; } elsif ( !ref $_[0] && $_[0] eq 'Contenido::Mail' ) { my $class = shift; $self = $class->new; } else { $self = Contenido::Mail->new; } my $opts = shift // {}; my $debug = $state->development || $DEBUG || $opts->{debug} ? 1 : 0; my $email = delete $opts->{email} // return undef; warn Dumper $email if $debug; return unless ref $email && exists $email->{to} && $email->{subject} && $email->{body}; my $que = Contenido::Email->new( $keeper ); $que->status( 0 ); if ( ref $email->{to} eq 'ARRAY' ) { my @to = grep { $_ } @{$email->{to}}; return unless @to; $que->name( join ',', @to ); } else { return unless $email->{to}; $que->name( $email->{to} ); } if ( exists $email->{cc} && ref $email->{cc} eq 'ARRAY' ) { $que->cc( join("\n", @{$email->{cc}}) ); } elsif ( exists $email->{cc} && $email->{cc} ) { $que->cc( $email->{cc} ); } if ( exists $email->{from} && $email->{from} ) { $que->from( $email->{from} ); } $que->subject( $email->{subject} ); $que->body_html( $email->{body} ); if ( exists $email->{text} ) { $que->body_text( $email->{text} ); } if ( exists $email->{date} && ref $email->{date} eq 'DateTime' ) { $que->dtime( $email->{date}->ymd('-').' '.$email->{date}->hms ); } elsif ( exists $email->{date} && $email->{date} ) { my $dt; eval{ $dt = Contenido::DateTime->new( postgres => $email->{date} ) }; if ( ref $dt ) { $que->dtime( $dt->ymd('-').' '.$dt->hms ); } } else { my $now = Contenido::DateTime->new; $que->dtime( $now->ymd('-').' '.$now->hms ); } if ( $que->store ) { return $que; } warn "Store failed!!!!\n" if $debug; return undef; } 1;