X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FMailer.pm;h=b04af08ddf5943ee4d7df2753080048571881c9d;hb=e435033ee174eb5028b6e56b825533c1caf698ea;hp=52691e277f75f208c1d51ce68e087759194694f9;hpb=8f3ecba98c0f85f2b48735c1ac110c3c9d957100;p=kivitendo-erp.git diff --git a/SL/Mailer.pm b/SL/Mailer.pm index 52691e277..b04af08dd 100644 --- a/SL/Mailer.pm +++ b/SL/Mailer.pm @@ -31,23 +31,46 @@ package Mailer; use Email::Address; +use Encode; use SL::Common; +use SL::MIME; use SL::Template; +use strict; + my $num_sent = 0; sub new { $main::lxdebug->enter_sub(); - my ($type) = @_; - my $self = {}; + my ($type, %params) = @_; + my $self = { %params }; $main::lxdebug->leave_sub(); bless $self, $type; } +sub _create_driver { + my ($self) = @_; + + my %params = ( + mailer => $self, + form => $::form, + myconfig => \%::myconfig, + ); + + my $cfg = $::lx_office_conf{mail_delivery}; + if (($cfg->{method} || 'smtp') ne 'smtp') { + require SL::Mailer::Sendmail; + return SL::Mailer::Sendmail->new(%params); + } else { + require SL::Mailer::SMTP; + return SL::Mailer::SMTP->new(%params); + } +} + sub mime_quote_text { $main::lxdebug->enter_sub(); @@ -57,30 +80,29 @@ sub mime_quote_text { my $l_start = length($q_start); my $new_text = "$q_start"; - $chars_left -= $l_start; + $chars_left -= $l_start if (defined $chars_left); for (my $i = 0; $i < length($text); $i++) { my $char = ord(substr($text, $i, 1)); - if (($char < 32) || ($char > 127) || - ($char == ord('?')) || ($char == ord('_'))) { - if ($chars_left < 5) { + if (($char < 32) || ($char > 127) || ($char == ord('?')) || ($char == ord('_'))) { + if ((defined $chars_left) && ($chars_left < 5)) { $new_text .= "?=\n $q_start"; $chars_left = 75 - $l_start; } $new_text .= sprintf("=%02X", $char); - $chars_left -= 3; + $chars_left -= 3 if (defined $chars_left); } else { $char = ord('_') if ($char == ord(' ')); - if ($chars_left < 5) { + if ((defined $chars_left) && ($chars_left < 5)) { $new_text .= "?=\n $q_start"; $chars_left = 75 - $l_start; } $new_text .= chr($char); - $chars_left--; + $chars_left-- if (defined $chars_left); } } @@ -96,28 +118,22 @@ sub send { my ($self) = @_; - local (*IN, *OUT); + local (*IN); $num_sent++; my $boundary = time() . "-$$-${num_sent}"; $boundary = "LxOffice-$self->{version}-$boundary"; - my $domain = $self->{from}; + my $domain = $self->recode($self->{from}); $domain =~ s/(.*?\@|>)//g; my $msgid = "$boundary\@$domain"; my $form = $main::form; my $myconfig = \%main::myconfig; - my $email = $myconfig->{email}; - $email =~ s/[^\w\.\-\+=@]//ig; - - my %temp_form = ( %{ $form }, 'myconfig_email' => $email ); - my $template = PlainTextTemplate->new(undef, \%temp_form, $myconfig); - my $sendmail = $template->parse_block($main::sendmail); - - if (!open(OUT, $sendmail)) { + my $driver = eval { $self->_create_driver }; + if (!$driver) { $main::lxdebug->leave_sub(); - return "$sendmail : $!"; + return "send email : $@"; } $self->{charset} ||= Common::DEFAULT_CHARSET; @@ -125,44 +141,55 @@ sub send { foreach my $item (qw(to cc bcc)) { next unless ($self->{$item}); + $self->{$item} = $self->recode($self->{$item}); $self->{$item} =~ s/\</{$item} =~ s/\$<\$/{$item} =~ s/\>/>/g; $self->{$item} =~ s/\$>\$/>/g; } + $self->{from} = $self->recode($self->{from}); + + my %addresses; my $headers = ''; - foreach my $item (qw(from to cc)) { + foreach my $item (qw(from to cc bcc)) { + $addresses{$item} = []; next unless ($self->{$item}); + my (@addr_objects) = Email::Address->parse($self->{$item}); next unless (scalar @addr_objects); foreach my $addr_obj (@addr_objects) { - $addr_obj->phrase($self->mime_quote_text($addr_obj->phrase(), 60)) if ($addr_obj->phrase()); - $addr_obj->comment($self->mime_quote_text($addr_obj->comment(), 60)) if ($addr_obj->comment()); + push @{ $addresses{$item} }, $addr_obj->address; + my $phrase = $addr_obj->phrase(); + if ($phrase) { + $phrase =~ s/^\"//; + $phrase =~ s/\"$//; + $addr_obj->phrase($self->mime_quote_text($phrase)); + } - $headers .= sprintf("%s: %s\n", ucfirst($item), $addr_obj->format()); + $headers .= sprintf("%s: %s\n", ucfirst($item), $addr_obj->format()) unless $driver->keep_from_header($item); } } - $headers .= sprintf("Subject: %s\n", $self->mime_quote_text($self->{subject}, 60)); + $headers .= sprintf("Subject: %s\n", $self->mime_quote_text($self->recode($self->{subject}), 60)); + + $driver->start_mail(from => $self->{from}, to => [ map { @{ $addresses{$_} } } qw(to cc bcc) ]); - print OUT qq|${headers}Message-ID: <$msgid> + $driver->print(qq|${headers}Message-ID: <$msgid> X-Mailer: Lx-Office $self->{version} MIME-Version: 1.0 -|; +|); if ($self->{attachments}) { - print OUT qq|Content-Type: multipart/mixed; boundary="$boundary" - -|; + $driver->print(qq|Content-Type: multipart/mixed; boundary="$boundary"\n\n|); if ($self->{message}) { - print OUT qq|--${boundary} + $driver->print(qq|--${boundary} Content-Type: $self->{contenttype}; charset="$self->{charset}" -$self->{message} +| . $self->recode($self->{message}) . qq| -|; +|); } foreach my $attachment (@{ $self->{attachments} }) { @@ -178,43 +205,49 @@ $self->{message} $filename =~ s/(.*\/|\Q$self->{fileid}\E)//g; } - my $application = - ($attachment =~ /(^\w+$)|\.(html|text|txt|sql)$/) - ? "text" - : "application"; + my $application = ($attachment =~ /(^\w+$)|\.(html|text|txt|sql)$/) ? "text" : "application"; + my $content_type = SL::MIME->mime_type_from_ext($filename); + $content_type = "${application}/$self->{format}" if (!$content_type && $self->{format}); + $content_type ||= 'application/octet-stream'; open(IN, $attachment); if ($?) { - close(OUT); $main::lxdebug->leave_sub(); return "$attachment : $!"; } - print OUT qq|--${boundary} -Content-Type: $application/$self->{format}; name="$filename"; charset="$self->{charset}" + # only set charset for attachements of type text. every other type should not have this field + # refer to bug 883 for detailed information + my $attachment_charset; + if (lc $application eq 'text' && $self->{charset}) { + $attachment_charset = qq|; charset="$self->{charset}" |; + } + + $driver->print(qq|--${boundary} +Content-Type: ${content_type}; name="$filename"$attachment_charset Content-Transfer-Encoding: BASE64 -Content-Disposition: attachment; filename="$filename"\n\n|; +Content-Disposition: attachment; filename="$filename"\n\n|); my $msg = ""; while () { ; $msg .= $_; } - print OUT &encode_base64($msg); + $driver->print(encode_base64($msg)); close(IN); } - print OUT qq|--${boundary}--\n|; + $driver->print(qq|--${boundary}--\n|); } else { - print OUT qq|Content-Type: $self->{contenttype}; charset="$self->{charset}" + $driver->print(qq|Content-Type: $self->{contenttype}; charset="$self->{charset}" -$self->{message} -|; +| . $self->recode($self->{message}) . qq| +|); } - close(OUT); + $driver->send; $main::lxdebug->leave_sub(); @@ -249,5 +282,11 @@ sub encode_base64 ($;$) { return $res; } -1; +sub recode { + my $self = shift; + my $text = shift; + return $::locale->is_utf8 ? Encode::encode('utf-8-strict', $text) : $text; +} + +1;