Пример отправки e-mail на Perl с помощью Mail::Sender

6 ноября 2015

Недавно передо мной возникла задача иногда отправлять письма на один e-mail адрес. Притом, в силу некоторых причин, делать это через веб-интерфейс к нужному почтовому ящику отправителя не представлялось возможным, а добавлять сей ящик в десктопный почтовый клиент очень не хотелось. Тогда я порылся в архивах и нашел свой старенький скрипт на Perl для отправки электронной почты, которым и намерен сегодня с вами поделиться. Данный конкретный скрипт предназначен для проведения почтовых рассылок, но может быть легко адаптирован и под другие задачи.

Сам скрипт:

#!/usr/bin/env perl

# mailsend.pl
# (c) Aleksander Alekseev 2015
# http://eax.me/

use strict;
use warnings;

use Mail::Sender;

my $fname = shift;
die "Usage: $0 <email_list>\n" unless $fname;

$| = 1;

open my $fid, '<', $fname or die $!;

my $subj = 'Очень важное письмо';
my $msg = q{
Здравствуйте.

Это письмо с очень важной информацией.

С уважением,
Василий Пупкин

- Это письмо отправлено автоматически, отвечать на него не нужно.

- Чтобы отписаться от рассылки, отправьте письмо с темой unsubscribe
  на admin@example.ru
};

$Mail::Sender::NO_X_MAILER = 1;
my $sender = Mail::Sender->new({
    smtp => 'nicmail.ru',
    port => 25,
    auth => 'LOGIN',
    authid => '__email@example.ru__',
    authpwd => '__password__',
    from => 'Pupkin <__email@example.ru__>',
  }) or die "Mail::Sender->new() failed: $Mail::Sender::Error";

my @err_list;
my $mail_number = 0;
while(my $email = <$fid>) {
  chomp($email);
  $mail_number++;
  print "[$mail_number] $email\n";

  my $sent_ok = 0;
  for my $attempt (1..3) {
    if( $sender->MailMsg({
        to => $email,
        encoding => 'base64',
        ctype => 'text/plain; charset=UTF-8',
        subject => $subj,
        msg => $msg,
      }) >= 0 ) {

      $sent_ok = 1;
      last;
    }

    warn "MailMsg($email ...) failed: $Mail::Sender::Error";
    last if $Mail::Sender::Error =~ /unknown user account/i;
    last if $Mail::Sender::Error =~ /syntax error for/i;
    sleep $attempt * 60;
  }

  push @err_list, $email unless $sent_ok;
  sleep 15;
}
close $fid;

print "--- errors ---\n";
print join("\n", @err_list);
print "\ntotal errors = ".scalar(@err_list)."\n";

Очевидно, для больших рассылок, скажем, с 10 000 получателями, этот скрипт будет работать очень долго. Для решения этой проблемы его нужно как-то распараллеливать. Если же рассылка не срочная, а получателей всего лишь несколько тысяч, то скрипт вполне неплохо справляется со своей задачей.

Собственно, это все. Надеюсь, вы нашли эту информацию полезной. Также вас могут заинтересовать заметки Как отправить электронное письмо в Scala и Достаточно полное описание протокола SMTP.

А как вы решаете подобные задачи?

Дополнение: Пример скрипта для посылки электронных писем на Python можно найти в заметке Как я выбирал скриптовый язык и остановился на Python.

Метки: .


Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.