Использую примерно такой код для отправки почты через GMail:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
my @hdr = ();
push @hdr, 'Date: ' . strftime("%a, %d %b %Y %H:%M:%S %z", localtime(time()));
push @hdr, 'From: ' . encode('MIME-Header', $from) if (defined($from));
push @hdr, 'To: ' . encode('MIME-Header', $rcpt) if (defined($rcpt));
push @hdr, 'Cc: ' . encode('MIME-Header', $copy) if (defined($copy));
push @hdr, 'Reply-To: ' . encode('MIME-Header', $copy) if (defined($copy));
push @hdr, 'Subject: ' . encode('MIME-Header', $subj) if (defined($subj));
push @hdr, 'MIME-Version: 1.0';
push @hdr, 'Content-Type: text/plain; charset=utf-8';
push @hdr, 'Content-Transfer-Encoding: base64';
my $smtp = Net::SMTPS->new('smtp.gmail.com', 'Port'=>587, 'doSSL'=>'starttls', 'Debug'=>0);
$smtp->auth('...', '...');
$smtp->mail($from);
$smtp->to($rcpt) if (defined($rcpt));
$smtp->cc($copy) if (defined($copy));
$smtp->data();
$smtp->datasend("$_\n") foreach (@hdr);
$smtp->datasend("\n");
$smtp->datasend(encode_base64(encode('UTF-8',$body)));
$smtp->datasend("\n");
$smtp->dataend();
$smtp->quit;
На сравнительно небольших письмах все работает нормально.
На больших письмах (от 100 КБ) вылетает ошибка.
Если включить отладку, выглядит примерно так:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
...
Net::SMTPS=GLOB(0x638e600)>>> sNGC0LUgMzAwINC00L4gMjAxNS0xMC0yNAoKCtCh0L/QuNGB0L7QuiAn0KHRgNC10LTRgdGC0LIg
Net::SMTPS=GLOB(0x638e600)>>> 0LTQvtGB0YLQsNGC0L7Rh9C90L4nIC0gMjgzMwoK0KHQv9C40YHQvtC6ICfQndC1INGD0LrQsNC3
Net::SMTPS=GLOB(0x638e600)>>> 0LDQvSDRgtC10LvQtdGE0L7QvScgLSAzMQoK0KHQv9C40YHQvtC6ICfQo9C20LUg0L7RgtC/0YDQ
Net::SMTPS=GLOB(0x638e600)>>> sNCy0LvRj9C70L7RgdGMJyAtIDQK
Net::SMTPS: Net::Cmd::datasend(): unexpected EOF on command channel: at ./test.pl line 164.
Net::SMTPS: Net::Cmd::_is_closed(): unexpected EOF on command channel: at ./test.pl line 165.
Net::SMTPS: Net::Cmd::_is_closed(): unexpected EOF on command channel: at ./test.pl line 166.
Net::SMTPS: Net::Cmd::_is_closed(): unexpected EOF on command channel: at ./test.pl line 167.
readline() on closed filehandle GEN0 at /usr/lib/perl/5.14/IO/Handle.pm line 178.
Строка 164 это $smtp->datasend(encode_base64(encode('UTF-8',$body))).
Видимо слишком большой блок данных в datasend.
Я сделал так:
1.
2.
$body = encode_base64(encode('UTF-8',$body));
$smtp->datasend($_) foreach (unpack("(A4096)*", $body));
Теперь письма уходят и даже читаются нормально.
Это оптимальный способ или может быть у Net::SMTP есть какое-то штатное свойство или опция, чтобы автоматически буферизовать данные при выводе?
________________________
Мы смотрим с оптимизмом...
...в оптический прицел.