transport redirect и возможность отредактировать тело письма

EXIM, sendmail, postfix, Dovecot и прочие. Решение проблем связанных с работой электронной почты

Модератор: xM

Правила форума
Убедительная просьба юзать теги [code] при оформлении листингов.
Сообщения не оформленные должным образом имеют все шансы быть незамеченными.
mumg
рядовой
Сообщения: 30
Зарегистрирован: 2009-03-03 22:39:15

transport redirect и возможность отредактировать тело письма

Непрочитанное сообщение mumg » 2009-03-03 22:45:12

Есть у кого какие предложения как это сделать.

Могу через pipe, встроеный перл и так далее.
Смысл вот в чем.
Есть группы в лдапе, по ним я в перловых вставках создаю data для redirect. Но в некоторых случаях мне нужно отредактировать тело письма, а точнее добавить footer. Причем правило для footer динамическое ( когда добавлять а когда нет).
Есно я могу через пайп получить все письмо, отредактировать его и отбрадкастить отдельным вызовом exim.
Но, может можно сделать красивее ?

Хостинговая компания Host-Food.ru
Хостинг HostFood.ru
 

Услуги хостинговой компании Host-Food.ru

Хостинг HostFood.ru

Тарифы на хостинг в России, от 12 рублей: https://www.host-food.ru/tariffs/hosting/
Тарифы на виртуальные сервера (VPS/VDS/KVM) в РФ, от 189 руб.: https://www.host-food.ru/tariffs/virtualny-server-vps/
Выделенные сервера, Россия, Москва, от 2000 рублей (HP Proliant G5, Intel Xeon E5430 (2.66GHz, Quad-Core, 12Mb), 8Gb RAM, 2x300Gb SAS HDD, P400i, 512Mb, BBU):
https://www.host-food.ru/tariffs/vydelennyi-server-ds/
Недорогие домены в популярных зонах: https://www.host-food.ru/domains/

Аватара пользователя
Alex Keda
стреляли...
Сообщения: 35456
Зарегистрирован: 2004-10-18 14:25:19
Откуда: Made in USSR
Контактная информация:

Re: transport redirect и возможность отредактировать тело письма

Непрочитанное сообщение Alex Keda » 2009-03-04 0:53:43

врятли
Убей их всех! Бог потом рассортирует...

mumg
рядовой
Сообщения: 30
Зарегистрирован: 2009-03-03 22:39:15

Re: transport redirect и возможность отредактировать тело письма

Непрочитанное сообщение mumg » 2009-03-05 21:23:49

Может кому пригодится. Сильно не пинайте, перл знаю плохо.
если есть вопросы, you're welcome

exim4.conf

Код: Выделить всё


maillist_with_subscription_transport:
    driver = pipe
    command = /etc/exim4/exim4_maillist.pl ${local_part}@${domain}
    return_path_add = false
    return_fail_output = true
    log_output = true
    user = mail
    group = mail
    message_prefix = ""
    message_suffix = ""
exim4_maillist.pl

Код: Выделить всё

#!/usr/bin/perl

use Mail::Internet;
use Mail::Address;
use Net::LDAP;
use Socket;

my $group;
my $sendmail = "/usr/sbin/sendmail"; 
my $ldap_base_dn = 'dc=xxx,dc=com';
my $ldap_host = "localhost";


sub trim($)
{
	my $string = shift;
	$string =~ s/^\s+//;
	$string =~ s/\s+$//;
	return $string;
}

sub get_text_footer()
{
    my @footer;
    push( @footer , "\n");
    push( @footer , "--------------------------------------------------------------------------------------------------------------\n");
    push( @footer , "FOOOOOOOOOOOOOOTER\n");
    return @footer;
}

sub get_html_footer($)
{
    local ($xmlns) = @_;
    #  if $xmlns == 1 then http://some.link?arg=3Dvalue
    #  if $xmlns == 0 then http://some.ling?arg=value
    local $delimiter = $xmlns == 1 ? "3D" : "";
    local @footer;
    push( @footer , "<br>\n");
    push( @footer , "------------------------------------------------------------------------------------------------------------------------<br>\n");
    push( @footer , "FOOOOOOOOTER<br>\n");
    return @footer;
}


sub inject_subscription_text($)
{
    local (*part ) = @_;
    local @result;
    push(@result , @part);
    push(@result , get_text_footer());
    push(@result , "\n\n");
    return @result;
}

sub inject_subscription_html($)
{
    local (*html ) = @_;
    local @result;
    local $xmlns = 0;
    foreach $html_line (@html)
    {
        if ($html_line =~ m/<html xmlns/i)
	{
	    $xmlns = 1;
	    push(@result , $html_line);
	}
        elsif ($html_line =~ m/<\/body>/i)
        {
            $html_line =~ m/(.+?)<\/body>/;
            push(@result , $1);
            push(@result , "<div>\n");
            push(@result , get_html_footer($xmlns));
            push(@result , "</div>\n");
            push(@result , "</body>\n");
            $html_line =~ m/<\/body>(.+?)/;
            push(@result , $1);
        }
        else
        {
            push(@result , $html_line);
        }
    }
    return @result;
}


sub inject_subscription_multipart($$)
{
    local (*body, $boundary) = @_;
    local @result;
    local @current_part;
    local $content_type = undef;
    local $is_attachment = false;
    foreach $line ( @body )
    {
         if ($line =~ m/Content-Type:\ (.+?)\n/)
         {
             $content_type = trim($1);
	     if ($content_type =~ m/(.+?)\;/)
	     {
	         $content_type = $1;
	     }
         }
         elsif (rindex($line , "--$boundary") == 0)
         {
            if ( @current_part != 0 )
            {
                 if ( $content_type eq "text/plain" )
                 {
                    push(@result, inject_subscription_text(*current_part));
                 }
                 elsif ( $content_type eq "text/html" )
                 {
                    push(@result, inject_subscription_html(*current_part));
                 }
                 else
                 {
                     push(@result , @current_part);
                 }
            }
            undef @current_part;
         }
         push(@current_part, $line);
    }
    if ( @current_part != 0 )
    {
         push(@result , @current_part);
    }
    return @result;
}


sub inject_subscription($)
{
    local ($mail) = @_;
    $content_type = $mail->get('Content-Type');
    local $use_sub_boundary = 0;
    if ($content_type =~ m/multipart\/related/ ||
        $content_type =~ m/multipart\/alternative/ ||
        $content_type =~ m/multipart\/mixed/ )
    {
        foreach $alternative_line (@{$mail->body})
        {
            if ($alternative_line =~ m/multipart\/alternative/ ||
                $alternative_line =~ m/multipart\/related/ )
            {
                $use_sub_boundary ++;
            }
        }
    }
    if ( $use_sub_boundary > 0 && $content_type =~ m/boundary=\"(.+?)\"/)
    {
        local @sub_content;
        local @content;
        local $boundary_found = 0;
        local $boundary  = $1;
        local $sub_boundary = "";
	    local $wait_for_boundary = 0;
        foreach $alternative_line (@{$mail->body})
        {
             if(rindex($alternative_line , "--$boundary") == 0)
             {
                 if ( $boundary_found == 0 )
                 {

                    $boundary_found = 1;
                    push(@content , $alternative_line);
                 }
                 else
                 {
                    push(@content , inject_subscription_multipart(*sub_content , $sub_boundary));
                    push(@content , $alternative_line);
                    undef @sub_content;
                 }
             }
             elsif(rindex($alternative_line , "--$boundary--") == 0)
             {
                    push(@content , inject_subscription_multipart(*sub_content , $sub_boundary));
                    $boundary_found = 0;
                    $sub_boundary = "";
                    push(@content , $alternative_line);
                    undef @subcontent;
             }
             elsif ($boundary_found == 1 &&
                    $sub_boundary eq ""  &&
                    ($alternative_line =~ m/multipart\/alternative/ ||
                     $alternative_line =~ m/multipart\/related/) &&
                    $alternative_line =~ m/boundary=\"(.+?)\"/)
             {
                 $sub_boundary = $1;
                 push(@content , $alternative_line);
             }
             elsif($boundary_found == 1 &&
                   $sub_boundary eq ""  &&
                   ($alternative_line =~ m/multipart\/alternative/ ||
                    $alternative_line =~ m/multipart\/related/))
            {
	            $wait_for_boundary = 1;
                push(@content , $alternative_line);
            }
            elsif($boundary_found == 1 &&
                  $sub_boundary eq ""  &&
                  $wait_for_boundary == 1 &&
                  $alternative_line =~ m/boundary=\"(.+?)\"/)
           {
                $wait_for_boundary =  0;
                $sub_boundary = $1;
                push(@content , $alternative_line);
	       }
           elsif ($sub_boundary ne "")
           {
                push(@sub_content , $alternative_line);
           }
           else
           {
               push(@content , $alternative_line);
           }
        }
        return @content;
    }
    elsif (($content_type =~ m/multipart\/alternative/ ||
            $content_type =~ m/multipart\/related/ ||  
            $content_type =~ m/multipart\/mixed/ ) &&
           $content_type =~ m/boundary=\"(.+?)\"/)
    {
        return inject_subscription_multipart($mail->body , $1);
    }
    elsif ($content_type =~ m/text\/plain/ )
    {
        return inject_subscription_text($mail->body);
    }
    elsif ($content_type =~ m/text\/html/ )
    {
        return inject_subscription_html($mail->body);
    }
    return $mail->body;
}


my $mail = Mail::Internet->new(\*STDIN);

my @recipients;

$ldap  = Net::LDAP->new ( $ldap_host ) or die "$@";
$ldap->bind ( version => 3 ) or die "$@";
my $userlist_query = $ldap->search ( base    => $ldap_base_dn,
                                     scope   => "sub",
                                     filter  => "maillist=$ARGV[0]" 
                                   );
my @user_attr_entries = $userlist_query->entries;
if ( defined($user_attr_entries[0]))
{
    my @body = $mail->body;
    my(@members) = $user_attr_entries[0]->get_value('memberuid');
    $group = $user_attr_entries[0]->get_value('cn');
    $mail->body(inject_subscription($mail));
    foreach $member (@members)
    {
       my $user_attrs = $ldap->search ( base    => $ldap_base_dn,
                                        scope   => "sub",
                                        filter  => "(|(uid=$member)(mailalias=$member))",
                                        attrs    => ['mail','mailforward','mailforwardEnabled']
                                      );
       my @user_attr_entries = $user_attrs->entries;
       if ( defined($user_attr_entries[0]))
       {
           my $email = $user_attr_entries[0]->get_value("mail");
           my $mailforwardEnabled = $user_attr_entries[0]->get_value("mailforwardEnabled");
           if ( $mailforwardEnabled eq 'TRUE' )
           {
               my $email_alt = $user_attr_entries[0]->get_value("mailforward");
               if ( $email_alt ne "")
               {
                   $email = $email_alt;
               }
           }
           if ( rindex($email , ' ') == -1 )
           {
               push(@recipients ,  $email);
           }
        }
    }
}

if (@recipients > 0)
{
    open(SENDMAIL, "|$sendmail " . join(" " , @recipients)) or die "Cannot open $sendmail: $!";
    $mail->print(\*SENDMAIL);
    close(SENDMAIL); 
}

Аватара пользователя
Alex Keda
стреляли...
Сообщения: 35456
Зарегистрирован: 2004-10-18 14:25:19
Откуда: Made in USSR
Контактная информация:

Re: transport redirect и возможность отредактировать тело письма

Непрочитанное сообщение Alex Keda » 2009-03-06 22:38:21

надо было процедурой сделать, тогда было бы гораздо быстрей.
======
имеется ввиду - встроить прям в экзим.
Убей их всех! Бог потом рассортирует...

mumg
рядовой
Сообщения: 30
Зарегистрирован: 2009-03-03 22:39:15

Re: transport redirect и возможность отредактировать тело письма

Непрочитанное сообщение mumg » 2009-03-06 23:03:55

lissyara писал(а):надо было процедурой сделать, тогда было бы гораздо быстрей.
======
имеется ввиду - встроить прям в экзим.
возможно, но я не знаю как экзиму вернуть тело сообщения