Configure phplist to send email from multiple postfix instances / IP addresses

Once you get your postfix server running for a while, you may see that the bottleneck is not the hardware but the rate in which you are able to send out email to different providers.

Instead of wasting idle resources, we can just add an IP address to the server and setup Postfix to run in a multi instance configuration. This way, we can utilise what we already have and double the email throughput of the server.

Preparations

1. First, we need to add one or more IP addresses to our host.

2. Make sure a postfix server is running.

3. Enable the multi instance support, run the command:
postmulti -e init

4. Create the first instance:

postmulti -I postfix-2 -G outgoing -e create
-I Is the nick name for the instance. You can use the hostname or whatever you like.
-G is the group name. In this post we are not using groups so just name it whatever you think describes it best. An example use for groups, is the ability to reload some of the instances while keeping the rest running.

The process will create new folder to hold both the configuration and the postfix mail queue. The structure is fairly simple but important to note for interacting with the instances:

Configuration files such as the main.cf files will be at /etc/instancename/ and in our example, under /etc/postfix-2/
The queue will be at /var/spool/instancename/ and in our example, under /var/spool/postfix-2/

5. Assigning an ip address to an instance

Lets assume that we have two IP addresses available on the server – 192.168.50.44 192.168.50.45
For the main instance, which is configured in /etc/postfix, we will keep the localhost listener, and add a specific address:
Edit the /etc/postfix/main.cf file and look for the line:
inet_interfaces = all
And change it to:
inet_interfaces = localhost, 192.168.50.44

open /etc/postfix/master.cf, look for the line:
smtp unix - - n - - smtp
And change it to:
smtp unix - - n - - smtp -o smtp_bind_address=192.168.50.44

This means that the base postfix instance is now listening and sending through the localhost address and 192.168.50.44

For each of the other instances, edit the main.cf file located under /etc/instancename and specify which IP address will be in use. To follow with our example, edit the /etc/postfix-2/main.cf file and replace:
inet_interfaces = all
With:
inet_interfaces = 192.168.50.45

open /etc/postfix-2/master.cf, look for the line:
smtp unix - - n - - smtp
And change it to:
smtp unix - - n - - smtp -o smtp_bind_address=192.168.50.45

6. Restart the postfix service after making these change.

7. Install one or multiple phplist

8. Configure each phplist to send email from different postfix instances
add the following code to the beginning of admin/index.php :
putenv("MAIL_CONFIG=/etc/postfix-2");
(note: use variable for “postfix-2” if you only have one phplist install)

9. Specify a list of user name are allowed to submit mail in /etc/postfix/main.cf or /etc/postfix-2/main.cf for each instance
authorized_submit_users = testuser

10. (Option) Commands to start/stop/enable/disable postfix instance:
postmulti -i postfix-2 -p start
postmulti -i postfix-2 -p stop
postmulti -i postfix-2 -e enable
postmulti -i postfix-2 -e disable

Now, we can schedule multiple phplist to run at the same time and we have double the email throughput of the server.

16 thoughts on “Configure phplist to send email from multiple postfix instances / IP addresses

  • Tuesday March 17th, 2015 at 12:30
    Permalink

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

    Reply
  • Monday March 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
  • Monday March 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
  • Monday April 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
  • Tuesday June 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
    • Monday June 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
  • Tuesday June 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
    • Tuesday June 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
  • Sunday June 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
  • Friday July 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
    • Wednesday August 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.

  • Wednesday September 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
  • Wednesday February 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
    • Monday February 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

Leave a Reply

Your email address will not be published. Required fields are marked *