配置 phplist 通过多个 Postfix 进程和多个 IP 地址发邮件

如果你使用过 postfix 服务器,就知道外发邮件的瓶颈不是服务器硬件本身,而是外部邮件服务器接受邮件的速率。

为了充分利用闲置资源,我们可以给服务器增加一个或多个IP地址,利用Postfix的多进程功能来增加一个或多个Postfix进程。这样,就可以让服务器的邮件发送量翻倍。

准备工作

1. 首先,给主机增加一个IP地址。

2. 确认 Postfix 服务器正常运行。

3. 启用 Postfix 的多进程支持,执行命令:
postmulti -e init

4. 创建一个新的Postfix进程:

postmulti -I postfix-2 -G outgoing -e create

-I 是进程的名字,可以使用主机名或其它名字。
-G 是组的名字,本帖子没有用到组所以随便起个名字。如果想同时重启某几个进程时可用到组。

上面的创建新进程的命令,会生成用于保存配置文件和邮件队列的目录。目录结构很简单但很重要,因为后面使用进程时会需要用到:

配置文件例如 main.cf 文件位于 /etc/instancename/,以前面的新进程为例,目录是 /etc/postfix-2/
邮件队列位于 /var/spool/instancename/,以前面的新进程为例,目录是 /var/spool/postfix-2/

5. 给 Postfix 进程绑定IP地址

假设我们有两个 IP 地址 – 192.168.50.44 192.168.50.45
系统默认的进程的配置文件位于目录 /etc/postfix, 我们保留原来的 localhost, 并绑定特定的地址 192.168.50.44:
修改文件 /etc/postfix/main.cf,找到:
inet_interfaces = all
修改为:
inet_interfaces = localhost, 192.168.50.44

打开文件 /etc/postfix/master.cf, 找到:
smtp unix - - n - - smtp
修改为:
smtp unix - - n - - smtp -o smtp_bind_address=192.168.50.44

也就是默认的 Postfix 进程将通过 192.168.50.44 发送邮件。

对其它的每个进程,修改相应的 /etc/instancename 目录下的 main.cf 配置文件,来绑定各自的 IP 地址。
对我们上面的例子,就是修改文件 /etc/postfix-2/main.cf,找到:
inet_interfaces = all
修改为:
inet_interfaces = 192.168.50.45

打开文件 /etc/postfix-2/master.cf, 找到:
smtp unix - - n - - smtp
修改为:
smtp unix - - n - - smtp -o smtp_bind_address=192.168.50.45

6. 重启 postfix 服务使前面的修改生效

7. 安装一个或者多个 phplist

8. 配置每个 phplist 从不同的 postfix 进程发出邮件
以前面的postfix新进程为例,在 phplist 的文件 admin/index.php 的前面加上下面的代码:
putenv("MAIL_CONFIG=/etc/postfix-2");
(说明: 如果只想安装一个phplist,那么 “postfix-2” 可以使用变量)

9. 最后需要将运行 phplist 用户的名字加入 /etc/postfix-2/main.cf 的允许发送邮件的用户列表
authorized_submit_users = testuser

10. (供参考) 下面是用于 启动/停止/启用/禁用 postfix 进程的命令:
postmulti -i postfix-2 -p start
postmulti -i postfix-2 -p stop
postmulti -i postfix-2 -e enable
postmulti -i postfix-2 -e disable

现在,我们可以同时运行多个 phplist 的计划任务,同一台邮件服务器的邮件发送量就翻倍了。

16 thoughts on “配置 phplist 通过多个 Postfix 进程和多个 IP 地址发邮件

  • 星期二 三月 17th, 2015 at 12:30
    Permalink

    GREAT !!!!!!!!!
    Many Thanks !!!!

    Reply
  • 星期一 三月 23rd, 2015 at 16:24
    Permalink

    Hi!
    Thanks for your tutorial. Really good work! But what i would like to know is, how do you handle bounces when you have setup different instances of postfix?

    Thanks in advance,
    Peter

    Reply
  • 星期一 三月 23rd, 2015 at 21:40
    Permalink

    You can setup the mailbox for the bounces in config.php:

    # Message envelope.
    #
    # This is the address that most bounces will be delivered to
    # Your should make this an address that no PERSON reads
    # but a mailbox that phpList can empty every so often, to process the bounces

    $message_envelope = ‘bounces@mydomain.com’;

    # Handling bounces. Check README.bounces for more info
    # This can be ‘pop’ or ‘mbox’
    $bounce_protocol = ‘pop’;

    # set this to 0, if you set up a cron to download bounces regularly by using the
    # commandline option. If this is 0, users cannot run the page from the web
    # frontend. Read README.commandline to find out how to set it up on the
    # commandline
    define (“MANUALLY_PROCESS_BOUNCES”,1);

    # when the protocol is pop, specify these three
    $bounce_mailbox_host = ‘smtp.mydomain.com’;
    $bounce_mailbox_user = ‘bounces’;
    $bounce_mailbox_password = ‘mypassword’;

    Reply
  • 星期一 四月 6th, 2015 at 16:36
    Permalink

    Hi again!

    The Problem i got is, that the sending instance has its own domain (abc.com). So bounces@abc.com will be delivered to the mx of this domain. The postfix instance is refusing smtp connections at this time. So what i wanted was, an postfix instance that is sending and recieving mail for one domain.

    Regards,
    Peter

    Reply
  • 星期二 六月 16th, 2015 at 13:27
    Permalink

    Thank you for this helpful post but when i put putenv(“MAIL_CONFIG=/etc/postfix-2”); at the first line in phpList, it does not send any thing and it told me failure to send when i try to send a test email throught phpList.

    Please help me

    Reply
    • 星期一 六月 22nd, 2015 at 16:58
      Permalink

      1. make sure you start the postfix instance:
      postmulti -i postfix-2 -p start

      2. the beginning of the file /admin/index.php should be something like:

      <?php
      putenv("MAIL_CONFIG=/etc/postfix-2");
      

      Note: The quotation marks sometime get changed when you copy from the blog.

      Reply
  • 星期二 六月 23rd, 2015 at 05:52
    Permalink

    Dear Sir

    I hope to start e mail marketing business . I have around more than 200,000 email address with me. I hope Purchase domain from hostgator and vps from hostgator with few extra IP. After that I i hope to update Name server as well as A record and MX record . I hope to setup few postfix instance with one phplist.Please let me know briefly how can achieve this.

    Reply
    • 星期二 六月 23rd, 2015 at 11:36
      Permalink

      I would say setup one phplist and postfix first. If it works then follow the steps in this post.

      Reply
  • 星期日 六月 28th, 2015 at 22:37
    Permalink

    Dear Jack Huang

    I setup PHP List on VPS it’s working fine.That VPS I purchased with extra 5 Public IP for balance outgoing e-mails via multiple IP .The solution is depending on postfix`s TCP_TABLES and a perl script..

    Install the perl module List::util::WeightedRoundRobin:
    cpan install /List::util::WeightedRoundRobin/

    Create the following perl script and make it executable:
    vi /etc/postfix/random.pl

    #!/usr/bin/perl -w
    # author: Hari Hendaryanto
    use strict;
    use warnings;
    use Sys::Syslog qw(:DEFAULT setlogsock);
    use List::Util::WeightedRoundRobin;
    use Storable;

    my $hashfile=”/tmp/file.hash”;
    store {}, $hashfile unless -r $hashfile;

    #
    # our transports lists, we will define this in master.cf as transport services
    # Queued using Weighted Round-Robin Scheduling
    #
    my $list = [
    {
    name => ‘smtp1:’,
    weight => 1,
    },
    {
    name => ‘smtp2:’,
    weight => 1,
    },
    {
    name => ‘smtp3:’,
    weight => 1,
    },
    {
    name => ‘smtp4:’,
    weight => 1,
    },
    {
    name => ‘smtp5:’,
    weight => 1,
    },
    {
    name => ‘smtp6:’,
    weight => 1,
    },
    {
    name => ‘smtp7:’,
    weight => 1,
    },
    ];

    my $WeightedList = List::Util::WeightedRoundRobin->new();
    my $weighted_list = $WeightedList->create_weighted_list( $list );

    # $maxinqueue max number of queue in smtp list
    my $maxinqueue = scalar(@{$weighted_list});

    #
    # Initalize and open syslog.
    #
    openlog(‘postfix/randomizer’,’pid’,’mail’);
    #
    # Autoflush standard output.
    #
    select STDOUT; $|++;

    while () {
    chomp;
    my $count;
    my $hash=retrieve($hashfile);

    if (!defined $hash->{“index”})
    {
    $count = 0;
    } else {
    $count = $hash->{“index”};
    }

    if ($count >= $maxinqueue)
    {
    $hash->{“index”} = 0;
    $count = 0;
    }

    $hash->{“index”}++;
    store $hash, $hashfile;
    my $random_smtp = ${$weighted_list}[$count];
    if (/^get\s(.+)$/i) {
    print “200 $random_smtp\n”;
    syslog(“info”,”Using: %s Transport Service”, $random_smtp);
    next;
    }
    print “200 smtp:\n”;
    }

    Execute the script to make sure it`s working and no errors are encountered:
    /etc/postfix/random.pl

    Configure postfix to use the random generated smtp transport.

    Edit /etc/postfix/master.cf, by appending following lines:
    ## Round-robin outgoing smtp
    127.0.0.1:23000 inet n n n – 0 spawn
    user=nobody argv=/etc/postfix/random.pl
    # random smtp
    smtp1 unix – – n – – smtp
    -o syslog_name=postfix-smtp1
    -o smtp_helo_name=FQDN
    -o smtp_bind_address=IP

    smtp2 unix – – n – – smtp
    -o syslog_name=postfix-smtp2
    -o smtp_helo_name= FQDN
    -o smtp_bind_address=IP

    smtp3 unix – – n – – smtp
    -o syslog_name=postfix-smtp3
    -o smtp_helo_name=FQDN
    -o smtp_bind_address=IP

    smtp4 unix – – n – – smtp
    -o syslog_name=postfix-smtp4
    -o smtp_helo_name=FQDN
    -o smtp_bind_address=IP

    smtp5 unix – – n – – smtp
    -o syslog_name=postfix-smtp5
    -o smtp_helo_name=FQDN
    -o smtp_bind_address=IP

    smtp6 unix – – n – – smtp
    -o syslog_name=postfix-smtp6
    -o smtp_helo_name= FQDN
    -o smtp_bind_address=IP

    smtp7 unix – – n – – smtp
    -o syslog_name=postfix-smtp7
    -o smtp_helo_name= FQDN
    -o smtp_bind_address=IP

    Replace FQDN with desired hostname and IP with the list of the IP addresses you`d like to use.

    Append the following lines to your /etc/postfix/main.cf:
    transport_maps = tcp:127.0.0.1:23000
    127.0.0.1:23000_time_limit = 3600s

    Restart/reload postfix and verify everything is working correctly:
    # postmap -q “dummy” tcp:127.0.0.1:23000
    smtp4:
    # postmap -q “dummy” tcp:127.0.0.1:23000
    smtp5:
    # postmap -q “dummy” tcp:127.0.0.1:23000
    smtp6:

    In your logs you should see the different smtp transport beeing used when mails are sent:
    Sep 2 12:50:05 myserver postfix-smtp2/smtp[2016]: 3CA964C0004: to=, relay=domain.org[XXXXXXXXX]:25, delay=2, delays=0.03/0.01/0.18/1.8, dsn=2.0.0, status=sent (250 OK id=1T86oe-0005tU-E9)
    Sep 2 12:50:05 myserver postfix-smtp5/smtp[2014]: 4EE244C0012: to=, relay=domain.org[XXXXXXXXX]:25, delay=2, delays=0.01/0/0.21/1.8, dsn=2.0.0, status=sent (250 OK id=1T86oe-0005tx-Gn)
    Sep 2 12:50:05 myserver postfix-smtp3/smtp[2045]: 69305680035: to=, relay=domain.org[XXXXXXXXX]:25, delay=2, delays=0.05/0/0.11/1.9, dsn=2.0.0, status=sent (250 OK id=1T86oe-0005uJ-Ih)
    Sep 2 12:50:05 myserver postfix-smtp3/smtp[2034]: 444B94C0006: to=, relay=domain.org[XXXXXXXXX]:25, delay=2.2, delays=0.04/0/0.21/1.9, dsn=2.0.0, status=sent (250 OK id=1T86oe-0005tW-G9)
    Sep 2 12:50:05 myserver postfix-smtp1/smtp[2039]: 585A6583CFE: to=, relay=domain.org[XXXXXXXXX]:25, delay=2.2, delays=0.01/0/0.15/2, dsn=2.0.0, status=sent (250 OK id=1T86oe-0005u0-GO)

    And also you get an entry when the perl script is used to provide transport:
    Sep 2 13:24:59 myserver postfix/randomizer[2076]: Using: smtp6: Transport Service

    Please advice me this setup Is OK for me or I need to send mails via multiple instance.

    Reply
  • 星期五 七月 17th, 2015 at 11:03
    Permalink

    Hello Mr. Jack Huang

    With this configuration I can get PHPList send emails for the 2 instances at once?

    If so, what should I do to send for 3 instances at once

    Reply
    • 星期三 八月 12th, 2015 at 21:39
      Permalink

      You can repeat these steps and create multiple instances.

      Reply
  • Pingback: [LINK] – Configure phplist to send email from multiple postfix instances / IP addresses | Andrea C.

  • 星期三 九月 30th, 2015 at 04:28
    Permalink

    Hello. Is possibile tu use POSTFIX Multi-Istances with Client Software? I’m using Multi-Istances with Phplist and it work because Phplist use ( putenv(“MAIL_CONFIG=/etc/postfix-2”); …but with Client Software (Like Thunderbid, Outlook, ecc.)….Postfix use always the primary server’s IP and not the dedicate instance IP. There’s a Way?

    Reply
  • 星期三 二月 17th, 2016 at 04:35
    Permalink

    Hi , Thanks for your configuration .

    I have an query

    i have test your config in two ways
    way 1 >>
    putenv(“MAIL_CONFIG=/etc/postfix-2”); in index and seen in mail log . It shows all the que are gng through postfix-2

    way 2>>

    i removed putenv(“MAIL_CONFIG=/etc/postfix-2”); frm index and seen in mail log. It shows all the que are gng through postfix .

    Now my question is that is it balancing que load on both the instances on each instance for one phplist ???

    .

    Actually i want to setup bulk email server using phplist.
    i just want to process the que very fast with help of postfix instance . can u help me in this

    Reply
    • 星期一 二月 22nd, 2016 at 20:54
      Permalink

      You can update MAIL_CONFIG to select a different queue before the mail() function.
      php mail() function seems to be in the file admin/phpmailer/class.phpmailer.php; see the function MailSend().

      Reply

发表评论

电子邮件地址不会被公开。 必填项已用*标注