houseabsolute / Log-Dispatch

Dispatches messages to one or more outputs
https://metacpan.org/release/Log-Dispatch/
Other
12 stars 29 forks source link

Log::Dispatch::Email::MIMELite dies when passed message has non utf8 wide characters (eg ansi cp1252) #70

Open rkapl123 opened 11 months ago

rkapl123 commented 11 months ago

Hi, I just wanted to suggest an addition of removing non syswritable characters in Log::Dispatch::Email::MIMELite before sending the message, as MIME::Lite doesn't catch this and dies with "Wide character in syswrite at Net::Cmd.pm line 210".

E.g. you could do eval {decode( 'UTF-8', $p{message}, $Encode::FB_CROAK )} or $p{message} =~ s/[^\x00-\x7f]/?/g; before adding the message to the mail in order to remove the offending non-ascii characters if the string contains non UTF-8 wide chars (which are supported by Net::Cmd).

-regards, Roland

autarch commented 11 months ago

I don't think silently altering the messages passed to a logger is a good idea. It might make sense to add some sort of parameter to do this, but really, this seems like a problem that should be addressed in the app doing the logging.

rkapl123 commented 11 months ago

Dear Dave, I agree with you on adding a parameter, however I don't think that the app (or module in my case) can really do much about checking every log message for valid wide characters (e.g. doing the above mentioned check), as this would mess up the code a lot and wide characters don't throw fatal exceptions with other appenders (file, screen).

I wouldn't open an issue here if 1) Net::Cmd being used by MIME::Lite wouldn't die on receiving wide characters and 2) MIME::Lite wouldn't be openly declared as "not recommended by its current maintainer", presumably being not actively maintained anymore.

An Alternative might be to directly address this in Net::Cmd as it isn't obviously necessary to throw an exception here. Of course the exception could be handled by MIME::Lite but here we are again at 2).

-regards, Roland

autarch commented 11 months ago

A simple stopgap would be to subclass Log::Dispatch::Email::MIMELite to do what you want. All you need to do is override the send_email method to munge the message parameter.

rkapl123 commented 5 months ago

OK, I've found out the real problem now (and I have solved it in my created subclass): When passing UTF-8 containing wide characters, the passed parameters are not containing correct UTF-8 due to a missing use feature 'unicode_strings';, I've added this in your suggested subclass as follows:

package Log::Dispatch::Email::LogSender;

use feature 'unicode_strings';
use Log::Dispatch::Email;
use base qw( Log::Dispatch::Email );

sub send_email {
    my $self = shift;
    my %p    = @_;
    my $msg = MIME::Lite->new(
            From    => $self->{from},
            To      => ( join ',', @{ $self->{to} } ),
            Subject => $self->{subject},
            Type    => "TEXT",
            Data    => $p{message},
        );
    eval {$msg->send();} or warn("couldn't send error mail: $@");
}

I don't know if adding use feature 'unicode_strings'; to the base class would be harmful, however it seems to be helpful for non-plain ascii users of the package.