我使用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);
答案 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));
此致
卡尔 - 亨氏