1. Скрипт.
Код: Выделить всё
#!/usr/bin/perl
use MIME::Base64;       #для кодирования авторизационных параметров, темы и тела письма
use IO::Socket;         #для общения с SMTP-сервером
use Text::Iconv;        #для перекодирования текста
my $mailbox = 'майл';  # ящик-отправитель
my $mailpwd = 'пароль';                # пароль
my $mailrcpt = 'кому';        # ящик-получатель
my $subj = ' тема ';
my $mail = ' тело сообщение ';
my $attachment = 'вложение';               # файл-вложение
my $attachpath = '/путь/';    # путь к нему
# поскольку данный скрипт я пишу в кодировке UTF-8,
# а письмо хочу отправлять в кодировке Windows, то мне просто необходим
# перекодировщик для кодирования из UTF-8(юникод) в CP1251(Windows)
my $cnv = Text::Iconv->new('UTF8','CP1251');
my $reply;      # код ответа сервера
my $message;    # текст ответа сервера
#открываем сокет к SMTP-серверу
my $socket = IO::Socket::INET->new('smtp.сервер:25');
defined $socket or die "ERROR: $!\n";
# читаем ответ
if(ReadReply() ne 220){print "Ошибка установки связи = $message\n"; $socket->close(); exit}
# здороваемся с сервером - не стал использовать ehlo,
# потому что расширенные возможности не требуются
$socket->print ("helo lo\n");
# получаем ответ и проверяем код
if(ReadReply() != 250){print "Ошибка приветствия сервера = $message\n"; $socket->close(); exit}
# теперь проводим авторизацию
$socket->print("AUTH LOGIN\n");
# получаем ответ
if(ReadReply() ne 334){print "Ошибка авторизации = $message\n"; $socket->close(); exit}
# кодируем логин-пароль
$socket->print(encode_base64($mailbox).encode_base64($mailpwd));
# после авторизации выдается две строчки
ReadReply();
if(ReadReply() ne 235){print "Ошибка авторизации = $message\n"; $socket->close(); exit}
# начинаем транзакцию - даем команду отправки письма
$socket->print('mail from: '."$mailbox\n");
if(ReadReply() ne 250){print "Ошибка в почтовом ящике отправителя = $message\n"; $socket->close(); exit}
# указываем получателя
$socket->print("rcpt to: $mailrcpt\n");
if(ReadReply() ne 250){print "Ошибка в почтовом ящике получателя = $message\n"; $socket->close(); exit}
# теперь начинаем формировать письмо
$socket->print("data\n");
if(ReadReply() ne 354){print "Ошибка при начале формирования письма = $message\n"; $socket->close(); exit}
# теперь сформируем тему письма, перекодировав ее из юникода в ср-1251
# и потом закодировав все это в base64.
# Таким образом, в теме письма можно нормально писать по русски
# Если вы используете другую кодировку в системе и/или при подготовке
# этого скрипта под свои нужды - скорректируйте создание конвертера в начале
# или вообще откажитесь от него
$subj = encode_base64($cnv->convert($subj));
$subj =~ s/\n//ig;      # уберем символы перевода строки
$subj =~ s/\r//ig;      # и возврата каретки, поскольку они все ломают :)
$subj = '=?Windows-1251?B?'.$subj.'?=';
# создадим тело письма
$msg = encode_base64($cnv->convert($mail));
# здесь формируем заголовок, минимальная версия
$body = "Mime-Version: 1.0\n";
$body .= "Content-Type: multipart/mixed; boundary=\"-\"\n\n";
# вставляем тело письма
$body .= "---\nContent-Type: text/plain;\n\tcharset=\"Windows-1251\"\nContent-Transfer-Encoding: base64\n\n$msg\n";
# и прицепляем файл-вложение
$body .= "---\nContent-Type: application/octet-stream; name=\"$attachment\"\n";
$body .= "Content-Transfer-Encoding: base64\n";
$body .= "Content-Disposition: inline; filename=\"$attachment\"\n\n";
# чтобы сформировать вложение, открываем файл
# в двоичном режиме, считываем его в память и кодируем в base64
$txt = '';
open f,"$attachpath$attachment";
binmode f;
while($str=<f>){$txt.=$str};
close f;
$body .= encode_base64($txt)."\n---\n";
# и наконец соберем письмо в одну переменную :)
$mailmessage = "From:$mailbox\nTo:$mailrcpt\nSubject:$subj\n$body\n.\n";
# скинем письмо серверу
$socket->print($mailmessage);
# и посмотрим что получилось
if(ReadReply() ne 250){print "Ошибка при отправке письма = $message\n"; $socket->close(); exit}
# если дошли до этого места, значит письмо ушло
$socket->close();
print "Письмо отправлено\n";
sub ReadReply{
        # процедура чтения ответа от сервера
        # цикл используется для того, чтобы прочитать многострочный ответ
        # например, при выдаче ответа на команду EHLO
        # формат строк
        # Трехзначное число-пробел или дефис-текстовое сообщение
        # причем, если ответ многострочный, то дефис используется во всех
        # строках, кроме последней, в которой используется пробел
        # именно по этому признаку и будет определятся конец цикла
        # и возвращаемый код будет браться также из последней строки
        $val = 1;
        while($val eq 1){
                $r = <$socket>;
                $val = $r =~ m/^\d{3}-/g;
        }
        ($reply,$message) = split(/ /,$r,2);
        return $reply;
}2. Скрипт
смотрим тут
Пример запуска.
Код: Выделить всё
/usr/bin/sendEmail.pl -v -f ваш@ящик -t ваш@ящик -u "Проверка sendEmail" -m "Проверка sendEmail" -s smtp.gmail.com:587 -xu ваш@ящик -xp ваш_пароль -o tls=yes