[SOLVED] batch emailing with attachments

Swift Mailer is a fantastic library for sending email with php. Discuss this library or ask any questions about it here.

Moderators: Chris Corbyn, General Moderators

Post Reply
roscoe
Forum Commoner
Posts: 85
Joined: Tue Aug 05, 2003 10:24 am
Location: essex uk

[SOLVED] batch emailing with attachments

Post by roscoe »

I have managed to get files uploaded onto my shared server awaiting a mailout per document.

Can I confirm this would be correct:

Code: Select all

$file_path = " /home/addictive/public_html/mailattachers/";


  $file_type = "doc";
    $file_name = $myfilename;
and then to take the file attachment and apply it and the content to a list from my dbase....

Code: Select all

require_once "lib/Swift.php";
require_once "lib/Swift/Connection/Sendmail.php";
 
// $swift =& new Swift(new Swift_Connection_SMTP("smtp.host.tld"));
 
$message =& new Swift_Message("My subject", "My body");
 
$recipients =& new Swift_RecipientList();
$recipients->addTo("joe@bloggs.tld");
$recipients->addTo("zip@button.tld");
//NOTE that Cc and Bcc recipients are IGNORED in a batch send
 
$swift->batchSend($message, $recipients, "my@address.com");
$recipients->addTo("joe@bloggs.tld");
$recipients->addTo("zip@button.tld");
Sorry, my php doesn't extend to some of the instructions here so I have to ask

the

Code: Select all

$recipients =& new Swift_RecipientList();
does this mean take the var $recipients and add these email addresses to it and if so, can I add the actual name of the recipient too (how would I do this in relation to swift?)

Many thanks for any help
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Re: batch emailing with attachments

Post by Chris Corbyn »

roscoe wrote:I have managed to get files uploaded onto my shared server awaiting a mailout per document.

Can I confirm this would be correct:

Code: Select all

$file_path = " /home/addictive/public_html/mailattachers/";


  $file_type = "doc";
    $file_name = $myfilename;
and then to take the file attachment and apply it and the content to a list from my dbase....
The path needs to point to the file, not the directory the file is in. The name doesn't really matter, it's just what the file will be called when the user gets it (don't forget the extension if it has one). The type has to be a valid mime type. "doc" is not a MIME type. If the file was uploaded to the web server you should be able to get the MIME type from $_FILES["file_field"]["type"]. Something like "application/x-ms-word" if I remember correctly.

Code: Select all

require_once "lib/Swift.php";
require_once "lib/Swift/Connection/Sendmail.php";
 
// $swift =& new Swift(new Swift_Connection_SMTP("smtp.host.tld"));
 
$message =& new Swift_Message("My subject", "My body");
 
$recipients =& new Swift_RecipientList();
$recipients->addTo("joe@bloggs.tld");
$recipients->addTo("zip@button.tld");
//NOTE that Cc and Bcc recipients are IGNORED in a batch send
 
$swift->batchSend($message, $recipients, "my@address.com");
$recipients->addTo("joe@bloggs.tld");
$recipients->addTo("zip@button.tld");
Sorry, my php doesn't extend to some of the instructions here so I have to ask

the

Code: Select all

$recipients =& new Swift_RecipientList();
does this mean take the var $recipients and add these email addresses to it and if so, can I add the actual name of the recipient too (how would I do this in relation to swift?)

Many thanks for any help
It means:

Create a new object using the class "Swift_Connection_SMTP" and pass that as a parameter to create a new object from the class "Swift" ($swift).

Next it creates a new object using the class "Swift_Message".

The you create a new object from the class "Swift_RecipientList" and call the addTo() method (function in other words) inside that object. You can call this method as many times as needed. addTo() populates the $recipients object with a list of email addresses just like how you can populate an array with values.

To provide the recipient's name, simply pass it as the second parameter in addTo().

Code: Select all

$recipients->addTo("joe@bloggs.tld", "Joe Bloggs");
This is just a shortcut to what $recipients does when you pass it those arguments:

Code: Select all

$recipients->addTo(new Swift_Address("joe@bloggs.tld", "Joe Bloggs"));
Either way will work ;)

The call to batchSend() simply tells Swift you want to send the message you created, to the recipients you added, from the address you provide. If you want to provide your name in addition to your address do this:

Code: Select all

$swift->batchSend($message, $recipients, new Swift_Address("my@address.com", "Your Name"));
roscoe
Forum Commoner
Posts: 85
Joined: Tue Aug 05, 2003 10:24 am
Location: essex uk

Post by roscoe »

Thanks, I understood most of that and I will see about the file type it is "application/msword", but
The path needs to point to the file, not the directory the file is in. The name doesn't really matter, it's just what the file will be called when the user gets it (don't forget the extension if it has one).
So how can I tell the script where the file is sitting on the webserver (as it is already loaded maybe days before hand)?

but can you tell me the
Create a new object using the class "Swift_Connection_SMTP" and pass that as a parameter to create a new object from the class "Swift" ($swift).
how (and can) I do this for sendmail instead as the smtp does not work on my server?

Many Thanks
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

roscoe wrote:Thanks, I understood most of that and I will see about the file type it is "application/msword", but
The path needs to point to the file, not the directory the file is in. The name doesn't really matter, it's just what the file will be called when the user gets it (don't forget the extension if it has one).
So how can I tell the script where the file is sitting on the webserver (as it is already loaded maybe days before hand)?
You have to store it in a database. How would you (as a human being) do it? You'd write it down somewhere so you can look it up later. Same principle. Usually when files are uploaded they get moved into a directory somewhere then all the info from $_FILES is stored in the database for use later.
but can you tell me the
Create a new object using the class "Swift_Connection_SMTP" and pass that as a parameter to create a new object from the class "Swift" ($swift).
how (and can) I do this for sendmail instead as the smtp does not work on my server?

Many Thanks
Have you read the documentation?

http://www.swiftmailer.org/wikidocs/v3/ ... s/sendmail

It's just a case of including lib/Swift/Connection/Sendmail.php and saying "new Swift_Connection_Sendmail()" rather than SMTP.
roscoe
Forum Commoner
Posts: 85
Joined: Tue Aug 05, 2003 10:24 am
Location: essex uk

Post by roscoe »

I appreciate I have to store it somewhere, but I was referring to where I tell the swift script where it sits (it usually gets it as part of the upload with a form I assume) I was asking which variable in your script must I pass it to? I assumed path, your explaination suggested this was just the file name. Therefore it would be good to know where I can pass this info for the script to use the file.

As to have I read the documentation, yes several times now, and I do understand that I can use sendmail instead (and it does have benefits) I was purely referring to the instruction that you have kindly confirmed for me I can change to :" new Swift_Connection_Sendmail()" rather than SMTP.

As it is your script (and none are bullet proof) it sometimes takes one stupid action to kill them stone dead. Just wanted to save some real grief for myself and I really do not want you to write a script for me as I would like to understand to what limits I can bend the script for my own purposes.

Thanks
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

roscoe wrote:I appreciate I have to store it somewhere, but I was referring to where I tell the swift script where it sits (it usually gets it as part of the upload with a form I assume) I was asking which variable in your script must I pass it to? I assumed path, your explaination suggested this was just the file name. Therefore it would be good to know where I can pass this info for the script to use the file.

As to have I read the documentation, yes several times now, and I do understand that I can use sendmail instead (and it does have benefits) I was purely referring to the instruction that you have kindly confirmed for me I can change to :" new Swift_Connection_Sendmail()" rather than SMTP.

As it is your script (and none are bullet proof) it sometimes takes one stupid action to kill them stone dead. Just wanted to save some real grief for myself and I really do not want you to write a script for me as I would like to understand to what limits I can bend the script for my own purposes.

Thanks
Swift is very low level really. It won't "look" for an attachment if it gets uploaded. You need to specify the full path:

Code: Select all

$attachment = new Swift_Message_Attachment(new Swift_File("/full/path/to/some/file.ext"));
http://www.swiftmailer.org/wikidocs/v3/ ... ttachments

Maybe I'm misunderstanding you?
roscoe
Forum Commoner
Posts: 85
Joined: Tue Aug 05, 2003 10:24 am
Location: essex uk

Post by roscoe »

OK I will explain what I have done.

In an effort to provide an easy to use mailer for marketing purposes, I have created a mySql db that allows for creation of a newsletter mailout with an attachment function.

They store all the blurb they want to say PLUS they can upload a word document directly to the webserver to be stored and used as an attachment to a specific newsletter. I have successfully uploaded and stored the files in a folder called /home/addictive/public_html/mailattachers/

Everyday the first customer to click on their site will trigger the mailouts for that day, based on date AND other factors (we are limited to 200 mailout addresses per day) (my host no longer supports crons)

It then reads which one is to go today picks up the corresponding email addresses for that day - adds them to the swift mail list with names, should then pick up the file from the folder as an attachment and off they go.

Because there is no "upload" at the time of the trigger, there is no $_FILES array, however I do not need it as I have the information of the filename AND its path stored.
I do know 1) the name of the file (I stored it when the file was uploaded) and
2) where the attachment sits.

I therefore need to pass the path and filename to swift so it can pick it up and churn them out. I assumed if I made the vars as below, it would pass the info to swift so it can collect the file ???

Code: Select all

$file_path = " /home/addictive/public_html/mailattachers/"; 
$file_type = "application/msword"; 
$file_name = $myfilename;
Or is swift unable to replace this info to pick up the file?
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Swift doesn't need to replace that information with the correct information. You do:

Code: Select all

$full_file_path = " /home/addictive/public_html/mailattachers/" . $file_name;
?

Code: Select all

$attachment = new Swift_Message_Attachment(new Swift_File($full_file_path), $file_name, $file_type);
$message->attach($attachment);
:)
roscoe
Forum Commoner
Posts: 85
Joined: Tue Aug 05, 2003 10:24 am
Location: essex uk

Post by roscoe »

Ah, thanks for that, I will chuck the script up and test it out and let you know.
roscoe
Forum Commoner
Posts: 85
Joined: Tue Aug 05, 2003 10:24 am
Location: essex uk

Post by roscoe »

see below
Last edited by roscoe on Wed May 09, 2007 11:45 am, edited 1 time in total.
roscoe
Forum Commoner
Posts: 85
Joined: Tue Aug 05, 2003 10:24 am
Location: essex uk

Post by roscoe »

As the batch emailer was not producing the correct results, I thought I would try one email at a time, slower but who cares?



It IS producing all the emails with attachments which is more than I can say for the above one. Is there any reason why I need the batch mailer to do these? Potentially we are probably going to send 1000 mailouts in a day at most (prob sometimes not for days) and staggered it seems to operate on sendmail fine with the sample of appx and it seems to stagger the emails outbound so the server seems to be coping???????


script below

Code: Select all

require_once ("/home/addictive/public_html/control/hideit/connect.inc");
      $table="alldone";   $z = 0;
       $today =date("Ymd");
 $sql = "SELECT * FROM $table WHERE mydate = '$today'";
    $results = mysql_query($sql) or die("An error ocurred :".mysql_error());
        while ($row = mysql_fetch_array($results)) {
              $thecat = $row["catcompleted"];
               $z = 1;
               exit;
         }

//Copy into global variables
$name = "PC ";
$email = "info@pc.com";

//Validate the email address using a regex (I suggest you use a better one than this!!)

//Check if an attachment was uploaded
$file_path = false;
$file_name = false;
$file_type = false;

  if($z==0){

//ready to roll

$foundit=0;
        require_once ("/home/addictive/public_html/control/hideit/connect.inc");
        $table = "control";
        $yes="live";
         $today =date("Ymd");
    $sql = "SELECT * FROM $table WHERE status = '$yes' AND startdate<='$today' AND enddate != '$today'";
    $results = mysql_query($sql) or die("An error ocurred :".mysql_error());
        while ($row = mysql_fetch_array($results)) {
        $myid = $row["id"];
        $mycat = $row["cat"];
        $foundit=1;

          // get the mail out

              if ($mycat=="(xxx)"){$mycat=1;}

              echo "<br>CONTROL $myid, $mycat";

   require_once "mylib/Swift.php";
require_once "mylib/Swift/Connection/Sendmail.php";

//Enable disk caching if we can
if (is_writable("/tmp"))
{
    Swift_CacheFactory::setClassName("Swift_Cache_Disk");
    Swift_Cache_Disk::setSavePath("/tmp");
}

//Create a Swift instance
//$swift =& new Swift(new Swift_Connection_SMTP("your_smtp_server.tld"));
//Try to connect using /usr/sbin/sendmail -bs
$sendmail =& new Swift_Connection_Sendmail();
$sendmail->setTimeout(3); //3 seconds

$swift =& new Swift($sendmail);

            if ($foundit==1){

               // pick up the id of content
                  require_once ("/home/addictive/public_html/control/hideit/connect.inc");
             $table = "content";
        //$yes="live";
        // $today =date("Ymd");
    $sql2 = "SELECT * FROM $table WHERE id = '$myid'";
    $results2 = mysql_query($sql2) or die("An error ocurred :".mysql_error());
        while ($row = mysql_fetch_array($results2)) {
        $title = $row["mysubject"];
        $mycontent = $row["mycontent"];
        $myattach = $row["myattach"];
        $myfilename  = $row["attfile"];


            echo"<br>CONTENT $title, $mycontent, $myattach, $myfilename";


            }

            // I now have the content so lets get the addresses for the cat

 if( $myattach=="y")  {

                              //there is a file to attach $myfilename  = $row["attfile"];
                  $file_path = " /home/addictive/public_html/mailattachers/";
   // $file_name = $_FILES["attachment"]["name"];
   				  $file_name = $myfilename;
  				  $full_file_path = "/home/addictive/public_html/mailattachers/".$file_name;

   // $file_type = $_FILES["attachment"]["type"];

    			  $file_type = "application/msword";

                 echo"<br> $full_file_path";
               //Everything looks ok, we can start Swift

                                    }
//Everything looks ok, we can start Swift
      $closing ="\n\nIf you wish to remove yourself from this mailing list at any time use the following link:\nhttp://www.dom.com/unsubscribe.html\n\nThank you!\n\n";
  $mycontent = $mycontent.$closing;
                       // strip slashes
                     echo"<br>THE CONTENTS email $mycontent";

//Create a Swift instance          new Swift_Connection_Sendmail()

$body = stripslashes ($mycontent);
$sender =& new Swift_Address($email, $name);


       $table = "mailouts";
        //$yes="live";
        // $today =date("Ymd");
        require_once ("/home/addictive/public_html/control/hideit/connect.inc");
    $sql3 = "SELECT * FROM $table WHERE cat = '$mycat'";
    $results3 = mysql_query($sql3) or die("An error ocurred :".mysql_error());
        while ($row = mysql_fetch_array($results3)) {
            $sendout = $row["myaddress"];
            $yourname = $row["myname"];

//$sendout = $_POST["to"];

//Create the sender from the details we've been given


//Create the message to send
$message =& new Swift_Message($yourname." ".$title);
$message->attach(new Swift_Message_Part($body));

//If an attachment was sent, attach it
if ($file_path && $file_name && $file_type)
{
    $message->attach(
        new Swift_Message_Attachment(new Swift_File($full_file_path), $file_name, $file_type));
}

//Try sending the email

$sent = $swift->send($message, $sendout, $sender);
                      }





                     }



                           }              }
//Disconnect from SMTP, we're done
$swift->disconnect();

if ($sent)
{
    header("Location: success.php");


     require_once ("/home/addictive/public_html/control/hideit/connect.inc");
      $table="alldone";   $x = 1;
       $today =date("Ymd");
         $sqlC = "UPDATE alldone SET mydate='$today', catcompleted = '$mycat'   WHERE b1='$x'";
       $myresultZ = mysql_query($sqlC) or die("An error ocurred :".mysql_error());

  $table = "categories";
        $full = "FULL";
        require_once ("/home/addictive/public_html/control/hideit/connect.inc");
    $sqlA = "SELECT * FROM $table WHERE mycounter  != '$full'";
    $resultsA = mysql_query($sqlA) or die("An error ocurred :".mysql_error());
        while ($row = mysql_fetch_array($resultsA)) {
        $finalcat = $row["cat"];

                      }

require_once ("/home/addictive/public_html/control/hideit/connect.inc");
        $table = "control";
        $yes="dead";
         $today =date("Ymd");
    $sqlx = "UPDATE $table SET status = '$yes', enddate = '$today' WHERE cat = '$finalcat'";
    $resultsx = mysql_query($sqlx) or die("An error ocurred :".mysql_error());

        $newcat=$mycat+1;
//Update control set cat = '$newcat' where id = '$myid'
        require_once ("/home/addictive/public_html/control/hideit/connect.inc");
        $table = "control";
          $sqlx = "UPDATE $table set cat = '$newcat' where id = '$myid'";
    $resultsx = mysql_query($sqlx) or die("An error ocurred :".mysql_error());



   mail("ros@vvv.com", "PHP Script is done for $cat", "Finished on " . date("m j, Y g:i a"));




    exit();
}
else
{     echo"sending_failed";
        exit;
 
}
Last edited by roscoe on Wed May 09, 2007 11:51 am, edited 1 time in total.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

roscoe wrote:As the batch emailer was not producing the correct results, I thought I would try one email at a time, slower but who cares?
It should actually be the same speed if you create $message outside the loop. However, batchSend() is not working because your code is all in the wrong order. You want to use batchSend() if you can, unless you're willing to catch errors yourself and deal with them.

You try attaching something to $message before $message is even created (that was your first "call to member function on non-object" error.
You appear to create $swift more than once, with different constructor parameters.

I'm unable to make much sense of your code due to the indentation not actually flowing in any way. I was looking to see if you are accidentally calling disconnect() when there may be other emails to send but I got lost in a sea of curly braces :(

EDIT | Whatever post I just replied, making comments on has either been edited or deleted :? The post I was referring to had a stack trace in it.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Just before you call $swift->send(...) place this code:

Code: Select all

var_dump($sendout); var_dump($sender);
roscoe
Forum Commoner
Posts: 85
Joined: Tue Aug 05, 2003 10:24 am
Location: essex uk

Post by roscoe »

Sorry for the edit whilst you are replying, it is still a work in progress and slicing and dicing my code to yours became confusing, hence the new script, which does work (I suspected having thought about it I must have had it in the wrong cronological order - diabetes clouds the mind!)

Anyway it is working fine and I will catch the errors earlier in the prep for the newsletters and email addresses so by the time it gets to swift the data will be clean.

Many Thanks for the pointers, I realised the issue in the missing post, re wrote and then spotted the closing of the sendmail connection before I was done, hence the changes to the post.

However, even with my untidy code :oops: , hopefully someone with attachments in this way will benefit as it is a working version. :)
Post Reply