perl email unicode format

¿Cómo puedo usar caracteres Unicode cuando escribo en el formato de Perl?



email (5)

Básicamente tengo una base de datos donde obtengo $lastname , $firstname , $rid , $since , $times y $ip from.

Utilizando una secuencia de comandos de Perl, formateo los datos para enviarlos por correo electrónico. Como $lastname y $firstname pueden contener caracteres especiales (por ejemplo, ä, ü, ß, é, ...) primero decodifico las cadenas.

my $fullname = decode("utf8", $lastname) . '', '' . decode("utf8", $firstname); my $send = swrite(<<''END'', $ip, $fullname, $rid, $since, $times); @<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<< @<<<<<<<<<<<<<< @>>END

Sin decode , los caracteres especiales son basura (ä se convierte en à €) y el resto está bien.
Con decode , todo está bien, excepto que las líneas con nombre que contienen caracteres especiales tienen un par de < demasiadas.

¿Porqué es eso? ¿Y cómo los elimino?

Editar: swrite es de perldoc perlform

sub swrite { my $format = shift; $^A = ''''; formline($format, @_); return $^A; }

Edit2: El problema no es el terminal ni STDOUT. Yo suelo:

use Mail::Sender; use vars qw($sender); #... $sender->MailMsg({to => $mailto, cc=> "", bcc => "", subject => "subject", msg => $send});

Y los personajes se muestran mal al recibir el correo electrónico.

Editar 3:
La información que obtengo ya está codificada. Obtengo ''Ã'' ''en lugar de'' ä ''y es por eso que mi formato falla, porque el número de caracteres disminuye cuando se utiliza la decodificación.


Mi caso de prueba mínimo parece pensar que el formato maneja perfectamente Unicode:

perl -MEncode -e ''formline("X@<<X", Encode::decode("utf-8","ほげぼげ")); print $^A''

El resultado es de tres caracteres, como se esperaba. Pero de todos modos, el format está en grave desaprobación. Es hora de usar otra cosa en su lugar.


Nunca he tenido el deseo de aprender sobre formatos. Esta es una respuesta incorrecta porque no puedo ofrecer ninguna información sobre su problema y / o posibles soluciones, pero otros ya lo han hecho. Voy a ofrecer dos sugerencias para reemplazos.

El primero, Perl6::Form debería ser útil como un mejor format aunque nunca lo había usado hasta que reuní este ejemplo hoy. Por otro lado, he usado Text::Table y es muy útil para crear tablas en texto plano (la mayoría de las veces, solo genero HTML, pero el correo electrónico sigue siendo uno de esos lugares donde el texto plano es claramente mejor).

Perl6::Form Ejemplo de Perl6::Form :

#!/usr/bin/perl use strict; use warnings; use Perl6::Form; my @data = ( [''127.0.0.1'', ''Johnny Smithey'', ''JLNSJIV'', 14, 5], [''127.0.0.2'', ''Ömer Seyfettin Şınas'', ''OSS3'', 25, 5], ); for my $data_ref ( @data ) { print format_data($data_ref); } sub format_data { my ($data) = @_; return form ''{<<<<<<<<<<<<<<<} {<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<} '' . ''{<<<<<<<<<<} {<<<<<<<<<<<<<<} {>>}'', @$data; }

Text::Table Ejemplo de Text::Table :

#!/usr/bin/perl use strict; use warnings; use Text::Table; my %common_options = ( align => ''left'', title_align => ''center'', ); my $sep = /' ''; my $table = Text::Table->new( { title => ''IP Address'', sample => ''<'' x 15, %common_options, }, $sep, { title => ''Full Name'', sample => ''<'' x 34, %common_options, }, $sep, { title => ''RID'', sample => ''<'' x 10, %common_options, }, $sep, { title => ''Since'', sample => ''<'' x 14, %common_options, }, $sep, { title => ''Times'', sample => ''>'' x 2, align => ''right'', title_align => ''center'' }, ); $table->rule(''''); $table->load( [''127.0.0.1'', ''Johnny Smith-Jones'', ''JLNSJIV'', ''20090814010203'', 5], [''127.0.0.2'', ''Ömer Seyfettin Şınas'', ''OSS3'', ''20071211101112'', 3], [''192.168.172.144'', ''Jane Doe'', ''JD156'', ''20080101010101'', 1], ); print $table->table;


Si está utilizando la función perldoc perlform , su problema es que STDOUT no está configurado para UTF-8 o su terminal no puede manejar UTF-8. Para el primer caso, tiene algunas opciones. La primera es usar binmode para decirle a STDOUT que espere UTF-8:

#!/usr/bin/perl use strict; use warnings; use Carp; sub swrite { croak "usage: swrite PICTURE ARGS" unless @_; my $format = shift; $^A = ""; formline($format, @_); return $^A; } my $fmt = "@<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<< @<<<<<<<<<<<<<< @>>"; binmode STDOUT, ":utf8"; my ($ip, $rid, $since, $times) = qw/1.1.1.1 5 2009-08-19 20/; my $firstname = "Ch/x{e4}s"; my $lastname = "/x{d6}wens"; my $fullname = "$lastname, $firstname"; my $send = swrite $fmt, $ip, $fullname, $rid, $since, $times; print "$send/n";

Otra opción es establecer la variable de entorno PERL_UNICODE en SDL (esto es similar a -CSD de caos en la línea de comandos):

PERL_UNICODE=SDL perl script.pl

o

export PERL_UNICODE=SDL perl script.pl

Hay otras maneras de decirle a STDOUT que espere UTF-8, pero no puedo recordarlas en la parte superior de mi cabeza (pongo export PERL_UNICODE=SDL en mi .profile hace mucho tiempo).

Si el problema es tu terminal, debes configurarlo correctamente u obtener una terminal diferente. El código anterior funciona en un terminal configurado correctamente, por lo que puede usarlo como una prueba.


El problema es que el motor de format no está entendiendo su UTF-8; cree que cada byte es un personaje. En realidad, no sé si puedes obtener formline (el mecanismo subyacente de swrite ) para hablar Unicode, pero prueba esto:

use open qw( :std :encoding(UTF-8) );

Esto intenta aplicar la codificación UTF-8 de la manera más amplia posible.

Probablemente necesites omitir tu uso de decode con esto.


No sé sobre formatos o swrite, pero sí sé sobre su problema de correo electrónico.

Los caracteres que ves en el correo electrónico recibido son UTF-8. Sin embargo, su correo está configurado para mostrar otra cosa por defecto (como Windows-1252 o Latin-1).

La solución es agregar un encabezado en su correo electrónico que informa al programa de correo acerca de la codificación de caracteres, para que pueda mostrarlo correctamente. Los encabezados que debe agregar al correo electrónico son:

Mime-version: 1.0 Content-type: text/plain; charset="UTF-8"

(u otro juego de caracteres, asegurándose de que corresponda con el cuerpo del correo electrónico)

Además, puede codificar el correo electrónico en una codificación de 7 bits como "imprimible entre comillas" y agregar el encabezado correspondiente:

Content-transfer-encoding: quoted-printable

Esa última codificación se puede hacer con el módulo MIME :: QuotedPrint.