如何使用变异元音发送Perl Mail :: Sender?

时间:2016-05-06 14:13:37

标签: perl email

我使用Mail :: Sender创建了一个Perl脚本来发送邮件。一切都很好 - 一般来说都有效。

一些小问题。

主题和来自姓名(姓名不是电子邮件地址)包括变异元音(德语特殊字符)。

我搜索了一些提示但没找到任何提示。

是否有任何示例如何使用此功能,或者有人可以给我一个提示如何完成此操作。

修改

我做到了:

ref ($av_tmp_MAIL = new Mail::Sender 
{ 
    from => "$av_loc_FROME ($av_loc_FROMN)",
    replyto => $av_loc_FROME,
    to => @av_loc_TO,
    cc => @av_loc_CC,
    bcc => @av_loc_BCC,
  smtp => 'smtp.av.loc',
}
)
 or die "Error($av_tmp_MAIL) : $Mail::Sender::Error\n";

在“emailaddress(name)”表单中配置“from”部分时,您通常会在邮件客户端中获得返回,以便将发件人姓名放在表单中的发件人电子邮件地址之前:

“发件人姓名<发件人的电子邮件地址>”其中“<>”真的很好。

由于我的发件人名称有一些变异的元音(德语特殊字符)“GrundwasserfrühwarnsystemForstinning”我需要编码这部分。

我尝试过所有这些变种:

#$av_loc_FROMN = Encode::encode("MIME-Q", Encode::decode_utf8($av_loc_FROMN)); # ganz seltsam mit der leerstelle
#$av_loc_FROMN = Encode::encode("MIME-Header", $av_loc_FROMN); # ganz seltsam mit der leerstelle
#$av_loc_FROMN = Encode::encode("MIME-Q", $av_loc_FROMN); # ganz schlecht
#$av_loc_FROMN = Encode::encode("MIME-B", $av_loc_FROMN); # tut es nicht

但他们都没有做到这一点。

说实话 - 即使在阅读文档时,MIME-Q和MIME-B以及MIME-Header之间的差异对我来说肯定是一个奇迹。但我想,我需要学习前x年才能理解。

使用时:

$av_loc_SUBJECT = Encode::encode("MIME-Q", Encode::decode_utf8($av_loc_SUBJECT));

对于邮件的SUBJECT - 它有效。

文字是“FunktionstestGrundwasserfrühwarnsystemForstinning”。

但总的来说,它应该适用于所有类型的文本。

修改

我会试着讲述背后的全部故事。

我有一个Bash脚本来完成这项工作。这很好用。但是我在Bash中遇到了一些问题,无法创建精美的电子邮件。使用mailx工作,但也有一些代码问题。使用bash脚本并不容易使用sendmail,并且还有一些编码问题。至少我的经历。

我的Bash脚本做了一些工作,结果通过echo命令写入文件。然后,如果向某些收件人发出警报,则必须发送该文件的文本。

邮件文本文件似乎是UTF-8编码的,并且在某些词语中包含这些变异的元音(Deutsche Umlaute)。

我希望Perl能够更轻松地创建一个更有可能格式化电子邮件的邮件(可能是HTML)。所以我想创建一个Perl脚本,从bash脚本中调用一些位置参数作为切换,如from,to,cc,bcc,subject和文本已经准备好的文件。

这就是我所追求的目标。

现在我正在寻求解决方案。

是的,它是以某种方式制作的东西(你可以从你看过的主题中想象)。但它仍然是一个私人活动和一些领域,在Perl学习一些编程,我是新手。

修改

这不是它的工作原理;参数的设置是成功的关键,但甚至还有一些必须考虑的先决条件:

a)perl脚本由bash脚本调用。 b)bash脚本自然地移交参数(如--fromn)。其中一个参数包含已经重音的元音。 c)bash脚本将正文作为文件移交给perl脚本。 perl脚本期望文件内容以utf8编码。

到目前为止一切顺利。但主要问题是:bash脚本本身必须是一个utf8编码的文件。只有这时,交换参数和由“echo”命令创建的主体也使用utf8来编码字符串。 !!!!!!!

即使在bash脚本中将ENV设置为正确的语言也无济于事。

#!/usr/bin/perl

use strict;
use warnings;
use utf8;
use warnings qw/ all FATAL /;
use Net::Domain qw(hostname hostfqdn hostdomain domainname);
use Net::Ping;
use Getopt::Long;
use autodie; # die if problem reading or writing a file
use DateTime;
use DateTime::Format::Strptime;
use DateTime::TimeZone;
use feature qw{say};

use File::Spec;
use File::Basename;

use Mail::Sender;

use Log::Logger;






#  _      __        _       _     _      
#   \    / /       (_)     | |   | |     
#  \ \  / /_ _ _ __ _  __ _| |__ | | ___ 
#   \ \/ / _` | '__| |/ _` | '_ \| |/ _ \
#    \  / (_| | |  | | (_| | |_) | |  __/
#     \/ \__,_|_|  |_|\__,_|_.__/|_|\___|
#                                        
#                                        
### variables block
our $av_std_ARG=1;
our $av_std_BASE='';
our $av_std_BIN='/usr/local/share/averlon';
our $av_std_DEBUG=0;
our $av_std_DIRNAME=dirname(__FILE__); # gibt dann u.U. nur "." wieder
our $av_std_EXIT=0;
our $av_std_FORCE=0;
our $av_std_LOGFILE='/var/log/'.hostname().'.log';
our $av_std_LOGGING=0;
our $av_std_MESSAGEFILE='/usr/local/share/averlon/av_messages.xml';
our $av_std_POSPAR;
our $av_std_RETVAL;
our $av_std_STORAGE='/ourtmp/';
our $av_std_USER;
our $av_std_TEST=0;
our $av_std_TMP='/tmp/';
our $av_std_VERBOSE=0;
our $av_std_VERSION='01.0a';

our $av_loc_FROMN="";
our $av_loc_FROME="";
our $av_loc_TO="";
our @av_loc_TO=();
our $av_loc_CC="";
our @av_loc_CC=();
our $av_loc_BCC="";
our @av_loc_BCC=();
our $av_loc_SUBJECT;
our $av_loc_FBODY;
our $av_loc_FATT="";
our @av_loc_FATT=();

###
### predefined objects
###
our $av_tmp_DT=DateTime->today();
our $av_tmp_LOGFILE;
our $av_tmp_TMP;
our $av_tmp_MAIL;

our $av_tmp_STRING;
our $av_tmp_FN;
our $av_tmp_FILE;

#dialogelemente
my $av_WINDOW;
my $av_BUTTON;
my $av_HBOX;
my $av_VBOX;
my $av_TEXTBOX1;
my $av_LABEL1;

#  ______                _   _                 
#    ____|              | | (_)                
#   |__ _   _ _ __   ___| |_ _  ___  _ __  ___ 
#    __| | | | '_ \ / __| __| |/ _ \| '_ \/ __|
#   |  | |_| | | | | (__| |_| | (_) | | | \__ \
#  _|   \__,_|_| |_|\___|\__|_|\___/|_| |_|___/
#                                              
#                                              
### functions commands block

sub av_help
{
    print "Benutzung:\n";
    print "/usr/local/share/averlon/av_sendmail.pl [-d, --debug] [-f, --force] [-h, --help] [-l, --logging] [-t, --test] [-v, --verbose] [-V, --version]\n";
    print "[--fromn=<sender name>] [--frome=<e-mail>] [--to=<e-mail>[,<e-mail>]]\n";
    print "[--cc=<e-mail>[,<e-mail>]] [--bcc=<e-mail>[,<e-mail>]] [--subject=<subject>]\n";
    print "[--fbody=<filename of body>] [--fatt=<filename of attachment>[,<filename of attachment>]]\n";
    print "Bedeutung der Optionen:\n";
    print "  --fromn := Name of sender\n";
    print "  --frome := e-Mail address of sender\n";
    print "  --to := comma separated list of e-mail addresses to send to\n";
    print "  --cc := comma separated list of e-mail addresses for carbon copy\n";
    print "  --bcc := comma separated list of e-mail addresses for blind copy\n";
    print "  --subject := subject to show in mail\n";
    print "  --fbody := file which contains body text\n";
    print "  --fatt := list of filenames which to attach to e-Mail\n";
    print "  -d, --debug := debugging mode\n";
    print "  -f, --force := force running\n";
    print "\tforce will omit to check dates or other conditions\n";
    print "  -h, --help := diese Information\n";
    print "  -l, --logging := log all output to file in /var/userlog/\n";
    print "\tfile is stored in /var/userlog and will have job_ as prefix and .log as suffix\n";
    print "  -t, --test := test mode on\n";
    print "  -v, --verbose := verbose logging\n";
    print "  -V, --version := Version wird ausgegeben\n";
}

###
### routine für das logging
###
sub av_logit
{
    $av_tmp_STRING=DateTime->now(time_zone=>'Europe/Berlin')->strftime('%b')
    ." ".
    DateTime->now(time_zone=>'Europe/Berlin')->strftime('%d')
    ." ".
    DateTime->now(time_zone=>'Europe/Berlin')->strftime('%H:%M:%S')
    ." ".hostname()
    ." ";
    $av_tmp_LOGFILE->log("$av_tmp_STRING"."@_");
}
#  _____                                _   _             
#    __ \                              | | (_)            
#   |__) | __ ___ _ __   __ _ _ __ __ _| |_ _  ___  _ __  
#    ___/ '__/ _ \ '_ \ / _` | '__/ _` | __| |/ _ \| '_ \ 
#   |   | | |  __/ |_) | (_| | | | (_| | |_| | (_) | | | |
#  _|   |_|  \___| .__/ \__,_|_|  \__,_|\__|_|\___/|_| |_|
#                | |                                      
#                |_|                                      
### preparation commands block

GetOptions (
"fromn=s" => \$av_loc_FROMN,
"frome=s" => \$av_loc_FROME,
"to=s" => \$av_loc_TO,
"cc=s" => \$av_loc_CC,
"bcc=s" => \$av_loc_BCC,
"subject=s" => \$av_loc_SUBJECT,
"fbody=s" => \$av_loc_FBODY,
"fatt=s" => \$av_loc_FATT,
"d" => \$av_std_DEBUG,    # debug
"debug"   => \$av_std_DEBUG,      # debug
"f"   => \$av_std_FORCE,      # debug
"force"   => \$av_std_FORCE,      # debug
"h"   => \&av_help,      # help
"help"   => \&av_help,      # help
"l"   => \$av_std_LOGGING,      # logging
"logging"   => \$av_std_LOGGING,      # logging
"t"   => \$av_std_TEST,      # test
"test"   => \$av_std_TEST,      # test
"v"   => \$av_std_VERBOSE,      # verbose
"verbose"  => \$av_std_VERBOSE,   # verbose
"V"   => \$av_std_VERSION,      # version
"version"  => sub { say "Version: $av_std_VERSION" }    # version
)
or say ("Error in command line arguments: @ARGV");

###
### prepare logging
###
$av_tmp_LOGFILE=Log::Logger->new();
$av_tmp_LOGFILE->open_append("$av_std_LOGFILE");
&av_logit("gestartet");

$av_std_DEBUG && say "debug \$av_std_DEBUG: $av_std_DEBUG";
$av_std_DEBUG && say "debug \$av_std_FORCE: $av_std_FORCE";
$av_std_DEBUG && say "debug \$av_std_LOGGING: $av_std_LOGGING";
$av_std_DEBUG && say "debug \$av_std_TEST: $av_std_TEST";
$av_std_DEBUG && say "debug \$av_std_VERBOSE: $av_std_VERBOSE";

$av_std_DEBUG && say "debug \$av_loc_FROMN: $av_loc_FROMN";
$av_std_DEBUG && say "debug \$av_loc_FROME: $av_loc_FROME";
$av_std_DEBUG && say "debug \@av_loc_TO: $av_loc_TO";
$av_std_DEBUG && say "debug \@av_loc_CC: $av_loc_CC";
$av_std_DEBUG && say "debug \$av_loc_BCC: $av_loc_BCC";
$av_std_DEBUG && say "debug \$av_loc_SUBJECT: $av_loc_SUBJECT";
$av_std_DEBUG && say "debug \$av_loc_FBODY: $av_loc_FBODY";
$av_std_DEBUG && say "debug \@av_loc_FATT: $av_loc_FATT";

#  __  __       _         _____                  
#    \/  |     (_)       |  __ \                 
#   \  / | __ _ _ _ __   | |__) | __ ___   ___   
#   |\/| |/ _` | | '_ \  |  ___/ '__/ _ \ / __|  
#   |  | | (_| | | | | | | |   | | | (_) | (__ _ 
#  _|  |_|\__,_|_|_| |_| |_|   |_|  \___/ \___(_)
#                                                
#                                                
### main procedure

###
### prepare variables
###
if ($av_loc_TO) 
{
  $av_loc_TO =~s/ //u; # leerzeichen eleminieren
  push(@av_loc_TO,split(/,/,join(',',$av_loc_TO))); # hier werden die einzelnen einträge in ein array überführt; trennzeichen=,
  $av_std_DEBUG && say "debug \@av_loc_TO: @av_loc_TO";
  if ($#av_loc_TO >= 1) # wenn 1 oder mehr elemente im array vorhanden sind muss das array in einen komma-getrennten string überführt werden
  { 
    $av_std_DEBUG && say "debug \@av_loc_TO: @av_loc_TO";
    $av_std_DEBUG && print "$_"."\n" foreach (@av_loc_TO);
    $av_loc_TO=''; # string löschen
    foreach (@av_loc_TO)
    {
        $av_loc_TO=$_.",".$av_loc_TO; #elemente des array mit komma getrennt zusammenführen - vorsicht - zum schluss ist 1 komma zuviel
    }
    $av_loc_TO=substr($av_loc_TO,0,length($av_loc_TO)-1); # das letzte komma entfernen
  }
  else
  {
    $av_loc_TO=join(' ', @av_loc_TO);
  }
}
else
{
    # To darf nicht leer sein
    exit ($?+=2); # exit mit exit status gesetzt
}
$av_std_DEBUG && say "debug \$av_loc_TO: $av_loc_TO";


$av_loc_CC =~s/ //u; # leerzeichen eleminieren
push(@av_loc_CC,split(/,/,join(',',$av_loc_CC))); # hier werden die einzelnen einträge in ein array überführt; trennzeichen=,
$av_std_DEBUG && say "debug \@av_loc_CC: @av_loc_CC";
if ($#av_loc_CC >= 1) # wenn 1 oder mehr elemente im array vorhanden sind muss das array in einen komma-getrennten string überführt werden
{ 
    $av_std_DEBUG && say "debug \@av_loc_CC: @av_loc_CC";
    $av_std_DEBUG && print "$_"."\n" foreach (@av_loc_CC);
    $av_loc_CC=''; # string löschen
#   shift(@av_loc_CC);
    foreach (@av_loc_CC)
    {
        $av_loc_CC=$_.",".$av_loc_CC; #elemente des array mit komma getrennt zusammenführen - vorsicht - zum schluss ist 1 komma zuviel
    }
    $av_loc_CC=substr($av_loc_CC,0,length($av_loc_CC)-1); # das letzte komma entfernen
}
else
{
    $av_loc_CC=join(' ', @av_loc_CC);
}
$av_std_DEBUG && say "debug \$av_loc_CC: $av_loc_CC";


#@av_loc_BCC=('dummy@av.loc');
$av_loc_BCC =~s/ //u; # leerzeichen eleminieren
push(@av_loc_BCC, split(/,/,join(',',$av_loc_BCC))); # hier werden die einzelnen einträge in ein array überführt; trennzeichen=,
$av_std_DEBUG && say "debug \@av_loc_BCC: @av_loc_BCC";
if ($#av_loc_BCC >= 1) # wenn 1 oder mehr elemente im array vorhanden sind muss das array in einen komma-getrennten string überführt werden
{ 
    $av_std_DEBUG && say "debug \@av_loc_BCC: @av_loc_BCC";
    $av_std_DEBUG && print "$_"."\n" foreach (@av_loc_BCC);
    $av_loc_BCC=''; # string löschen
#   shift(@av_loc_BCC);
    foreach (@av_loc_BCC)
    {
        $av_loc_BCC=$_.",".$av_loc_BCC; #elemente des array mit komma getrennt zusammenführen - vorsicht - zum schluss ist 1 komma zuviel
    }
    $av_loc_BCC=substr($av_loc_BCC,0,length($av_loc_BCC)-1); # das letzte komma entfernen
}
else
{
    $av_loc_BCC=join(' ', @av_loc_BCC);
}
$av_std_DEBUG && say "debug \$av_loc_BCC: $av_loc_BCC";


#@av_loc_FATT=('dummy.txt');
$av_loc_FATT =~s/ //u; # leerzeichen eleminieren
push(@av_loc_FATT, split(/,/,join(',',$av_loc_FATT))); # hier werden die einzelnen einträge in ein array überführt; trennzeichen=,
$av_std_DEBUG && say "debug \@av_loc_FATT: @av_loc_FATT";
if ($#av_loc_FATT >= 1) # wenn 1 oder mehr elemente im array vorhanden sind muss das array in einen komma-getrennten string überführt werden
{ 
    $av_std_DEBUG && say "debug \@av_loc_FATT: @av_loc_FATT";
    $av_std_DEBUG && print "$_"."\n" foreach (@av_loc_FATT);
    $av_loc_FATT=''; # string löschen
#   shift(@av_loc_FATT);
    foreach (@av_loc_FATT)
    {
        $av_loc_FATT=$_.",".$av_loc_FATT; #elemente des array mit komma getrennt zusammenführen - vorsicht - zum schluss ist 1 komma zuviel
    }
    $av_loc_FATT=substr($av_loc_FATT,0,length($av_loc_FATT)-1); # das letzte komma entfernen
}
else
{
    $av_loc_FATT=join(' ', @av_loc_FATT);
}
$av_std_DEBUG && say "debug \$av_loc_FATT: $av_loc_FATT";

@av_loc_FATT=($av_loc_FATT);
$av_std_DEBUG && say "debug \@av_loc_FATT: @av_loc_FATT";
foreach $av_tmp_STRING (@av_loc_FATT)
{
  if ( !-f "$av_tmp_STRING" )
  {
    say "$av_tmp_STRING existiert nicht";
    exit ($?+=4);
  }
}

$Mail::Sender::NO_X_MAILER=1; # wichtig der unterdrückt eine meldung im header wo auf das skript rückschlüsse gezogen werden kann.

$av_loc_FROMN = Encode::encode("MIME-Q", Encode::decode('UTF-8', $av_loc_FROMN));
$av_std_DEBUG && say "debug \$av_loc_FROMN: $av_loc_FROMN";
$av_loc_SUBJECT = Encode::encode("MIME-Q", Encode::decode('utf8', $av_loc_SUBJECT));
$av_std_DEBUG && say "debug \$av_loc_SUBJECT: $av_loc_SUBJECT";

$av_std_DEBUG && say "debug \$av_loc_TO: $av_loc_TO";
$av_std_DEBUG && say "debug \$av_loc_CC: $av_loc_CC";
$av_std_DEBUG && say "debug \$av_loc_BCC: $av_loc_BCC";
$av_std_DEBUG && say "debug \$av_loc_FROMN: $av_loc_FROMN";
$av_std_DEBUG && say "debug \$av_loc_FROME: $av_loc_FROME";
$av_std_DEBUG && say "debug \$av_loc_SUBJECT: $av_loc_SUBJECT";


ref ($av_tmp_MAIL = new Mail::Sender 
{ 
    from => $av_loc_FROMN.'<'.$av_loc_FROME.'>',
    replyto => $av_loc_FROME,
    to => $av_loc_TO,
    cc => $av_loc_CC,
    bcc => $av_loc_BCC,
  smtp => 'smtp.av.loc',
}
) or $av_std_DEBUG && say "debug Return code $av_tmp_MAIL" and exit (1);
$av_std_DEBUG && $Mail::Sender::Error && say "\$Mail::Sender::Error: $Mail::Sender::Error" && exit (1);


$av_tmp_MAIL->OpenMultipart (
  {
    subject => $av_loc_SUBJECT,
    encoding => "Quoted-printable",
    multipart => 'Mixed',
    charset => 'UTF-8',
  }
);
$av_std_DEBUG && $Mail::Sender::Error && say "\$Mail::Sender::Error: $Mail::Sender::Error" && exit (1);


open(BODY, '<', "$av_loc_FBODY") || # zum Lesen geöffnet
  say "debug: Cannot open file $av_loc_FBODY for reading! error: $!" && exit (1);

$av_tmp_STRING='';
while(my $eingabe=<BODY>){
  chomp($eingabe);
  $av_tmp_STRING = $av_tmp_STRING.Encode::decode("UTF-8", $eingabe)."\r\n";
}
$av_std_DEBUG && say "$av_tmp_STRING";

close(BODY); 
$av_std_DEBUG && say "debug \$ERRNO: $!";

$av_tmp_MAIL->Body (
  {
    charset => 'UTF-8',
    encoding => 'Quoted-printable',
    ctype => 'text/plain',
    msg => $av_tmp_STRING,
  }
);
$av_std_DEBUG && $Mail::Sender::Error && say "\$Mail::Sender::Error: $Mail::Sender::Error" && exit (1);
$av_std_DEBUG && say "debug \$ERRNO: $!";


$av_tmp_MAIL->Attach(
{
    description => 'Grundwasser Statistikdaten',
  file => @av_loc_FATT,
}
);
$av_std_DEBUG && $Mail::Sender::Error && say "\$Mail::Sender::Error: $Mail::Sender::Error" && exit (1);
$av_std_DEBUG && say "debug \$ERRNO: $!";

$av_tmp_MAIL->Close;
$av_std_DEBUG && $Mail::Sender::Error && say "\$Mail::Sender::Error: $Mail::Sender::Error" && exit (1);
$av_std_DEBUG && say "debug \$ERRNO: $!";

#  ______           _   _____                  
# |  ____|         | | |  __ \                 
# | |__   _ __   __| | | |__) | __ ___   ___   
# |  __| | '_ \ / _` | |  ___/ '__/ _ \ / __|  
# | |____| | | | (_| | | |   | | | (_) | (__ _ 
# |______|_| |_|\__,_| |_|   |_|  \___/ \___(_)
#                                              
#                                              
### end procedure
&av_logit("beendet");
exit (0);

2 个答案:

答案 0 :(得分:0)

查看适合您的解决方案,您的输入变量似乎是编码的UTF-8字符串。这就是为什么你必须先解码它们的原因。这可能本身就是一个问题,但如果不了解其余的代码,就无法判断。

要将编码为UTF-8的字符串转换为MIME标头编码,from_to function比您的解决方案简单一点:

# Re-encodes $av_loc_FROMN in place.
Encode::from_to($av_loc_FROMN, "UTF-8", "MIME-Header");

如@Andrzej所述,您应该考虑MIME-Q编码。使用MIME-Q,您的编码电子邮件标头在大多数情况下都是人类可读的。无论你使用&#34; MIME-Header&#34;它真的不应该有任何区别。 (有效地&#34; MIME-B&#34;)或&#34; MIME-Q&#34;,所以我很困惑为什么你的尝试

$av_loc_FROMN = Encode::encode("MIME-Q", Encode::decode_utf8($av_loc_FROMN)); # ganz seltsam mit der leerstelle

没有工作。但是,较早版本的Encode发行版有许多与MIME头编码有关的错误。也许你正在遇到其中一个。

如果您真的对代码的正确性感兴趣,我也不会推荐Encode::MIME::Header用于包含RFC 2822&#34;邮箱&#34;的邮件标题。和&#34;短语&#34;,如From,To,Cc,Reply-To等。因为此模块不会触及<"等字符,或@,所有这些都可以在这种情况下具有特殊含义,应该引用。通常,Encode::MIME::Header仅对主题标题或仅包含字母数字字符的显示名称是安全的。为了稳健地处理邮箱,我建议Email::MIME::RFC2047。 (披露:我是本次发行的作者。)

答案 1 :(得分:-1)

我获得了!

这是有效的结果 - 不要问我原因!

$av_loc_FROMN = Encode::encode("MIME-Header", Encode::decode_utf8($av_loc_FROMN));

此致

卡尔 - 亨氏