SitePoint Sponsor

User Tag List

Results 1 to 19 of 19

Thread: Mass mailing

  1. #1
    SitePoint Addict
    Join Date
    Nov 2005
    Posts
    241
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question Mass mailing

    What is the most efficient way to mass mail a bunch of users with php? I have a bunch of names, usernames and emails in a database and am writing a script to send an email to all of the users in that database. Currently, I am using this method:

    PHP Code:
                    for($i=0;$i mysql_num_rows($result);$i++){
                        
    $body $message "\n\n" $footer;
                        
    $body str_replace('%name%',$name[$i],$body);
                        
    $body str_replace('%date%',$date[$i],$body);
                        
    $body str_replace('%email%',$email[$i],$body);
                        
    $body str_replace('%username%',$username[$i],$body);
                        
    $body str_replace('%remove%',$url.'/remove.php',$body);
                        if(!
    mail($email[$i],$subject,$body)){
                            die(
    'There was an error while sending the email to '.$email[$i].'. Please make sure the PHP mail function is configured on your server.');
                        }
                    } 
    This is an open source script, and I do not know how many user's people would have, so I am going to use 5,000. Do you think this would work to send an email to 5,000 people?

    Also, where I have the strreplace multiple times, I am trying to replace certain strings in the message with various pieces of information. Is there a way to do this more efficiently? I don't know why, but I just have a feeling that someone is going to get to this code and the script is just going to quit on them.

  2. #2
    SitePoint Wizard silver trophy
    Join Date
    Mar 2006
    Posts
    6,132
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    mail() is not a good choice for mass emailing, its not designed for it.

    take a look at swiftmailer

  3. #3
    SitePoint Guru toasti's Avatar
    Join Date
    Feb 2004
    Location
    Grahamstown
    Posts
    634
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    also phpmailer is quite nice.

  4. #4
    SitePoint Addict
    Join Date
    Nov 2005
    Posts
    241
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok. I looked at both of them. I think PHPMailer looks better for what I am trying to do. What about my second question, the strreplace?

  5. #5
    SitePoint Member
    Join Date
    Jul 2006
    Posts
    13
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This is how I'd do it (assuming this is what you're trying to do):

    PHP Code:
    $result MYSQL_QUERY("SELECT name,username,email
    FROM table"
    ,$db);

    IF (
    MYSQL_NUM_ROWS($result))
       WHILE(
    $data MYSQL_FETCH_ROW($result))
       {
           
    $body "Date: " DATE("m-d-Y") . "\n\r";
           
    $body .= "Name: $data[0]\n\r";
           
    $body .= "Username: $data[1]\n\r";
           
    $body .= "Email: $data[2]\n\r";
           
    $body .= "Remove: /remove.php\n\r";
           IF (!
    MAIL($data[2],"subject",$body))
              DIE(
    "Fatal Error Sending Message to $data[2]");
       }

    This puts all of the data into each email to be sent and sends an email to each email address in the database.

  6. #6
    SitePoint Wizard cranial-bore's Avatar
    Join Date
    Jan 2002
    Location
    Australia
    Posts
    2,634
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    As far as I know PhpMailer still uses the mail() function by default. Swiftmailer is a little more complex to get started with, but it should better handle bigger lists because it opens a direct connection with your SMTP server (or other MTA). You therefor only have one connection per batch.

    Futhermore I would never try to send 5000 emails in one block. I'd schedule a cron job to run every 10-15 minutes and send a block of emails at a time.
    The sleep function may also be helpful for mini-pauses during the process.

    The string replacement won't be that slow. I wouldn't worry about it.

  7. #7
    SitePoint Addict
    Join Date
    Nov 2005
    Posts
    241
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by gpowerone
    This is how I'd do it (assuming this is what you're trying to do):

    PHP Code:
    $result MYSQL_QUERY("SELECT name,username,email
    FROM table"
    ,$db);

    IF (
    MYSQL_NUM_ROWS($result))
       WHILE(
    $data MYSQL_FETCH_ROW($result))
       {
           
    $body "Date: " DATE("m-d-Y") . "\n\r";
           
    $body .= "Name: $data[0]\n\r";
           
    $body .= "Username: $data[1]\n\r";
           
    $body .= "Email: $data[2]\n\r";
           
    $body .= "Remove: /remove.php\n\r";
           IF (!
    MAIL($data[2],"subject",$body))
              DIE(
    "Fatal Error Sending Message to $data[2]");
       }

    This puts all of the data into each email to be sent and sends an email to each email address in the database.
    No, actually, the administrator submits the message through an online form. I need to replace certain strings with values from the database.

    Quote Originally Posted by cranial-bore
    As far as I know PhpMailer still uses the mail() function by default. Swiftmailer is a little more complex to get started with, but it should better handle bigger lists because it opens a direct connection with your SMTP server (or other MTA). You therefor only have one connection per batch.

    Futhermore I would never try to send 5000 emails in one block. I'd schedule a cron job to run every 10-15 minutes and send a block of emails at a time.
    The sleep function may also be helpful for mini-pauses during the process.

    The string replacement won't be that slow. I wouldn't worry about it.
    Ok. For now, anyways, most likely no one will be sending to 5,000 email addresses. I was just using that as an example to see if what I am using would work for someone who has many users.

    Thanks everyone for the help.

  8. #8
    SitePoint Wizard silver trophy
    Join Date
    Mar 2006
    Posts
    6,132
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    it might be a tiny bit faster to do
    PHP Code:
    $body str_replace(array('%name%','%email%','%date%','%remove%',), array($name$email$date$remove), $body); 
    you can time parts of your script with microtime()

  9. #9
    SitePoint Addict
    Join Date
    Nov 2005
    Posts
    241
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by clamcrusher
    it might be a tiny bit faster to do
    PHP Code:
    $body str_replace(array('%name%','%email%','%date%','%remove%',), array($name$email$date$remove), $body); 
    you can time parts of your script with microtime()
    That is exactly what I was looking for.. Thanks again for your help.

  10. #10
    SitePoint Guru toasti's Avatar
    Join Date
    Feb 2004
    Location
    Grahamstown
    Posts
    634
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    As far as I know PhpMailer still uses the mail() function by default.
    You can set it to use SMTP though i think.

    Code:
    $mail->Host     = "smtp1.site.com;smtp2.site.com";
    $mail->Mailer   = "smtp";
    No, actually, the administrator submits the message through an online form. I need to replace certain strings with values from the database.
    When the admin submits the form you could add the mails to a queue which u could process with a cron job. I think a cron job will also be more reliable than firing the script via your browser because you wont get issues like timeouts etc.

    Also, not a bad idea to put a sleep(1); after you send the mails. decrease load on the server.

  11. #11
    SitePoint Wizard cranial-bore's Avatar
    Join Date
    Jan 2002
    Location
    Australia
    Posts
    2,634
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    toasti - do you know if setting PhpMailer to use SMTP directly would still create a new connection for each email?
    I understood that was one of Swift Mails key benefits - that it could open one connection to the MTA for the entire batch. PhpMailer may do it too though?
    I'd be interested to know if PhpMailer could be configured that way.

  12. #12
    SitePoint Guru toasti's Avatar
    Join Date
    Feb 2004
    Location
    Grahamstown
    Posts
    634
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm afraid i have no idea!

  13. #13
    SitePoint Addict
    Join Date
    Nov 2005
    Posts
    241
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by toasti
    You can set it to use SMTP though i think.

    Code:
    $mail->Host     = "smtp1.site.com;smtp2.site.com";
    $mail->Mailer   = "smtp";


    When the admin submits the form you could add the mails to a queue which u could process with a cron job. I think a cron job will also be more reliable than firing the script via your browser because you wont get issues like timeouts etc.

    Also, not a bad idea to put a sleep(1); after you send the mails. decrease load on the server.

    I have decided to just use php mail for this. Unfortunately, I am unable to use a cron job. This is a script that will be available for download, and that would probably deter people. I don't think I want to use the sleep function either. That would mean ~85 minutes to send an email to 5,000 people! There is no way it takes the server needs that much time. Maybe if I could sleep for .1 seconds, but not a whole second. Also, to prevent the script from timing out, I can use set_time_limit(0) to allow unlimited execution time. What I was mainly worried about was the script just completely stopping because it has so much data to process, however, by thinking it through, 5,000 emails is not going to stop the script.

    I previously been able to process text files with 50,000 lines using php, and nothing out of the ordinary happened. It was not until the file was 500,000 lines that php just quit on me (and I was left with an error log that was 30 gb).

  14. #14
    SitePoint Guru toasti's Avatar
    Join Date
    Feb 2004
    Location
    Grahamstown
    Posts
    634
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I don't think I want to use the sleep function either
    you could make it sleep for 1 second after say 10 or even 100 or 1000 messages have been sent..but sleep is something which would only really make sense if you were doing it using cron.

    I can use set_time_limit(0) to allow unlimited execution time.
    i have had problems with php long scripts breaking when i use them through the browser, but my connection speed is prob a lot lower than yours!

    You could also consider using pseudo-cron...

  15. #15
    PHP Brainiac dg_den_golotyuk's Avatar
    Join Date
    Jul 2006
    Location
    Kiev, Ukraine
    Posts
    335
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The mail function is absolutely not for mass emailing. Try using easy MAIL PEAR library (http://pear.php.net/package/Mail) to send email through SMTP directly
    DG [Den Golotyuk], Lead Developer
    Chestnut Software
    Avoid web outsourcing scams!
    Click here
    for a free downloadable report

  16. #16
    SitePoint Wizard cranial-bore's Avatar
    Join Date
    Jan 2002
    Location
    Australia
    Posts
    2,634
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I previously been able to process text files with 50,000 lines using php, and nothing out of the ordinary happened.
    Yes, but I bet you weren't sending that data over the internet. The slow part of mass mailing is the fact that emails have to be transported to other systems. Not selecting the data, or doing string replacement or any of that.

    If you really want to run this without cron you'll also need to set the PHP script to ignore user abort, so that when the browser times out the script can continue executing in the background.

  17. #17
    SitePoint Addict
    Join Date
    Nov 2005
    Posts
    241
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by cranial-bore
    Yes, but I bet you weren't sending that data over the internet. The slow part of mass mailing is the fact that emails have to be transported to other systems. Not selecting the data, or doing string replacement or any of that.

    If you really want to run this without cron you'll also need to set the PHP script to ignore user abort, so that when the browser times out the script can continue executing in the background.
    Hmm.. as long as the script is still running, the browser should not time out. The page just might take a long long time to load. I think the only way to stop th script would be clicking the browser stop button or closing the browser window.

  18. #18
    SitePoint Wizard cranial-bore's Avatar
    Join Date
    Jan 2002
    Location
    Australia
    Posts
    2,634
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Browsers will time out if they don't get a response in a reasonable amount of time.
    At least use ignore_user_abort in your script so it will keep running after the browser disconnects.

  19. #19
    SitePoint Addict
    Join Date
    Nov 2005
    Posts
    241
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by cranial-bore
    Browsers will time out if they don't get a response in a reasonable amount of time.
    At least use ignore_user_abort in your script so it will keep running after the browser disconnects.
    Will do. Thanks again for the help.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •