SitePoint Sponsor

User Tag List

Results 1 to 15 of 15
  1. #1
    SitePoint Guru
    Join Date
    Sep 2004
    Posts
    613
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    E-Mail class w/ attachments

    I'm trying to put together a class for our site that includes php attachments.... I'm very very new to email headers and working with emails. I currently have a function we use but am more than willing to change to some better code if anyone here has something.... I do have a question.....


    I got some code from php.net and I used it to the best of my understanding and when the form submits an email (supposedly with an attachment as well), I get this output in an email in my inbox

    Code:
    Content-Type: multipart/mixed; boundary="6342c76d3f9adfc2895ff45a4b99de42"
    
    
    
    --6342c76d3f9adfc2895ff45a4b99de42
    Content-Type: multipart/alternative; boundary="6342c76d3f9adfc2895ff45a4b99de42_htmlalt"
    
    --6342c76d3f9adfc2895ff45a4b99de42_htmlalt
    Content-Type: text/plain; charset=iso-8859-1
    Content-Transfer-Encoding: 8bit
    
    stest
    
    --6342c76d3f9adfc2895ff45a4b99de42_htmlalt
    Content-Type: text/html; charset=iso-8859-1
    Content-Transfer-Encoding: 8bit
    
    testetstest
    
    --6342c76d3f9adfc2895ff45a4b99de42_htmlalt--
    
    --6342c76d3f9adfc2895ff45a4b99de42--
    This is the code that I used:
    Code:
        function send($to, $body, $subject, $fromaddress, $fromname, $attachments=false){
    	$eol="\r\n";
            $mime_boundary=md5(time());
    
    	$headers .= "From: ".$fromname."<".$fromaddress.">".$eol;
    	$headers .= "Reply-To: ".$fromname."<".$fromaddress.">".$eol;
    	$headers .= "Return-Path: ".$fromname."<".$fromaddress.">".$eol;   
    	$headers .= "Message-ID: <".time()."-".$fromaddress.">".$eol;
    	$headers .= "X-Mailer: PHP v".phpversion().$eol; 
    	    	    
    	$headers .= 'MIME-Version: 1.0'.$eol.$eol;
    	$headers .= "Content-Type: multipart/mixed; boundary=\"".$mime_boundary."\"".$eol.$eol;
    	    
    	$msg = "--".$mime_boundary.$eol;
     
    	$htmlalt_mime_boundary = $mime_boundary."_htmlalt";
    	$msg .= "Content-Type: multipart/alternative; boundary=\"".$htmlalt_mime_boundary."\"".$eol.$eol;
    
    	$msg .= "--".$htmlalt_mime_boundary.$eol;
    	$msg .= "Content-Type: text/plain; charset=iso-8859-1".$eol;
    	$msg .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
    	$msg .= strip_tags(str_replace("<br>", "\n", substr($body, (strpos($body, "<body>")+6)))).$eol.$eol;
    
    	$msg .= "--".$htmlalt_mime_boundary.$eol;
    	$msg .= "Content-Type: text/html; charset=iso-8859-1".$eol;
    	$msg .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
    	$msg .= $body.$eol.$eol;
    
    	$msg .= "--".$htmlalt_mime_boundary."--".$eol.$eol;
    
    	if ($attachments !== false) {
    	    for($i=0; $i < count($attachments); $i++) {
    		if (is_file($attachments[$i]["file"])) {  
    		    $file_name = substr($attachments[$i]["file"], (strrpos($attachments[$i]["file"], "/")+1));
           
    		    $handle=fopen($attachments[$i]["file"], 'rb');
    		    $f_contents=fread($handle, filesize($attachments[$i]["file"]));
    		    $f_contents=chunk_split(base64_encode($f_contents));    //Encode The Data For Transition using base64_encode();
    		    $f_type=filetype($attachments[$i]["file"]);
    		    fclose($handle);
           
    		    $msg .= "--".$mime_boundary.$eol;
    		    $msg .= "Content-Type: ".$attachments[$i]["content_type"]."; name=\"".$file_name."\"".$eol; 
    		    $msg .= "Content-Transfer-Encoding: base64".$eol;
    		    $msg .= "Content-Description: ".$file_name.$eol;
    		    $msg .= "Content-Disposition: attachment; filename=\"".$file_name."\"".$eol.$eol;
    		    $msg .= $f_contents.$eol.$eol;
    		}
    	    }
    	}
    
    	$msg .= "--".$mime_boundary."--".$eol.$eol;
     
    	ini_set(sendmail_from,$fromaddress);  // the INI lines are to force the From Address to be used !
    	$mail_sent = mail($to, $subject, $msg, $headers);
     
    	ini_restore(sendmail_from);
     
    	return $mail_sent;
        }

  2. #2
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,161
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Mail with PHP is a somewhat of a dark art. I would recommend going with PHPMailer, PEAR::mail or Zend mail. You would spend a lot of time troubleshooting this, and since doing so would require sending a lot of mail and testing multiple services, it's really best to go with something that is proven for that sort of thing.

  3. #3
    Team SitePoint santouras's Avatar
    Join Date
    Jul 2006
    Location
    planet earth
    Posts
    276
    Mentioned
    16 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Hammer65 View Post
    Mail with PHP is a somewhat of a dark art. I would recommend going with PHPMailer, PEAR::mail or Zend mail. You would spend a lot of time troubleshooting this, and since doing so would require sending a lot of mail and testing multiple services, it's really best to go with something that is proven for that sort of thing.
    when using php4 I've tended to use htmlMimeMail as it doesn't rely on external libraries like pear or ZF. For php5 tho its Zend_Mail all the way, I'm a big ZF fan
    my utility belt tells me its to the bar batman

    read the manual then google it then do a search THEN post....

  4. #4
    SitePoint Zealot
    Join Date
    Oct 2007
    Location
    In the blogosphere
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm a personal fan of swiftmailer.
    bLueFrogX's Blog - Random Ramblings of a NEET Techie ★

  5. #5
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    PHPMailer works.

  6. #6
    SitePoint Evangelist
    Join Date
    Jan 2006
    Location
    UK
    Posts
    537
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I use swiftmailer too, it does anything anybody would ever want with email, plus has an active forum and is well documented.

  7. #7
    SitePoint Guru
    Join Date
    Sep 2004
    Posts
    613
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm looking for something where I can really just get the code that attaches files to emails.... I've looked at those and didn't even see the attachment optio...

    Swiftmailer is just crazy huge.

  8. #8
    SitePoint Wizard cranial-bore's Avatar
    Join Date
    Jan 2002
    Location
    Australia
    Posts
    2,634
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Swiftmailer is pretty intimidating, because it's so all encompassing and thorough, and because just about every configuration option happens via class instantiation.

    It is also well written and pretty clever.
    A basic example of constructing an email with an attachment and swift might look a bit like this:
    PHP Code:
    <?php

    //SWIFT and SMTP connection classes
    require_once('classes/Swift.php');
    require_once(
    'classes/Swift/Connection/SMTP.php');

    //Start MSG
    $swift = new Swift(new Swift_Connection_SMTP('mail.example.com'));
    $msg = new Swift_Message('Email with files attached');

    //Add HTML body
    $msg -> attach(new Swift_Message_Part("<h2>Email R Teriffic</h2><p>Dogs are Awesome. Attached is a picture of an awesome dog.</p>"'text/html'));

    // Add String as Text file attachment
    $msg -> attach(new Swift_Message_Attachment('Foo Bar'"readme.txt"'text/plain'));

    // Add JPG file, using dedicated file attachment class
    $msg -> attach(new Swift_Message_Attachment(
        new 
    Swift_File('images/dog.jpg'), 'dog.jpg''image/jpeg'));

    //Send Mail
    if(!$swift->send($msg'to.someone@example.com''from.someone@example.com')) {
        echo 
    "ERROR SENDING MAIL";
    }
    else echo 
    "SUCCESSFUL SEND ";
    $swift->disconnect();

    ?>
    Swift Attachments are documented here

  9. #9
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,161
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    PHPMailer, PEAR::mail, zend mail, are all suitable for the job.

  10. #10
    SitePoint Wizard TheRedDevil's Avatar
    Join Date
    Sep 2004
    Location
    Norway
    Posts
    1,198
    Mentioned
    4 Post(s)
    Tagged
    1 Thread(s)
    I tried reading over your code but its a mess. You have double linebreaks where only one should be used, the boundary is suddenly changed etc...

    Working with attachments and inline images is actually very simple, you just need to read up and follow the specifications for sending emails with attachments.

    Here is an example you can work from.

    PHP Code:
    $to 'email@email.com';
    $from 'no-reply@email.com';

    $subject 'Email Subject';
    $message_text "Hello\r\nThis is a test email";
    $message_html "Hello<br><font color=\"red\">This is a test email</font><br>";

    $image = array();
    $image[] = chunk_split(base64_encode(file_get_contents('image1.gif')));
    $image[] = chunk_split(base64_encode(file_get_contents('image2.gif')));

    $boundary 'bound-'.md5(rand());

    $header "From: $from <$from>\n";
    $header .= "MIME-Version: 1.0\n";
    $header .= "Content-Type: multipart/mixed;\n";
    $header .= "  boundary=\"$boundary\"\n";

    $message = <<<EMAIL
    $message_text
    --
    $boundary
    Content-Type: text/plain; charset=us-ascii
    Content-Transfer-Encoding: 7bit
    $message_text
    --
    $boundary
    Content-Type: text/html; charset="iso-8859-1"
    Content-Transfer-Encoding: 7bit
    $message_html
    --
    $boundary
    Content-Type: image/gif; name="image1.gif"
    Content-Transfer-Encoding: base64
    Content-disposition: attachment; file='image1.gif"
    {$image[0]}
    --
    $boundary
    Content-Type: image/gif; name="image2.gif"
    Content-Transfer-Encoding: base64
    Content-disposition: attachment; file='image2.gif"
    {$image[1]}
    EMAIL;

    mail($to$subject$message$header); 

  11. #11
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,161
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by TheRedDevil View Post
    I tried reading over your code but its a mess. You have double linebreaks where only one should be used, the boundary is suddenly changed etc...

    Working with attachments and inline images is actually very simple, you just need to read up and follow the specifications for sending emails with attachments.

    Here is an example you can work from.

    PHP Code:
    $to 'email@email.com';
    $from 'no-reply@email.com';

    $subject 'Email Subject';
    $message_text "Hello\r\nThis is a test email";
    $message_html "Hello<br><font color=\"red\">This is a test email</font><br>";

    $image = array();
    $image[] = chunk_split(base64_encode(file_get_contents('image1.gif')));
    $image[] = chunk_split(base64_encode(file_get_contents('image2.gif')));

    $boundary 'bound-'.md5(rand());

    $header "From: $from <$from>\n";
    $header .= "MIME-Version: 1.0\n";
    $header .= "Content-Type: multipart/mixed;\n";
    $header .= "  boundary=\"$boundary\"\n";

    $message = <<<EMAIL
    $message_text
    --
    $boundary
    Content-Type: text/plain; charset=us-ascii
    Content-Transfer-Encoding: 7bit
    $message_text
    --
    $boundary
    Content-Type: text/html; charset="iso-8859-1"
    Content-Transfer-Encoding: 7bit
    $message_html
    --
    $boundary
    Content-Type: image/gif; name="image1.gif"
    Content-Transfer-Encoding: base64
    Content-disposition: attachment; file='image1.gif"
    {$image[0]}
    --
    $boundary
    Content-Type: image/gif; name="image2.gif"
    Content-Transfer-Encoding: base64
    Content-disposition: attachment; file='image2.gif"
    {$image[1]}
    EMAIL;

    mail($to$subject$message$header); 
    That code however, as it stands is not portable, easily maintainable or versatile enough, considering that a large number of projects require sending mail. Using a pre-written class gives you all of those.

    @OP if OOP is confusing or hard to grasp for you, then there are plenty of people here that can help. Don't rule out swiftmailer, or any of the others because you aren't used to it's API.

  12. #12
    SitePoint Wizard TheRedDevil's Avatar
    Join Date
    Sep 2004
    Location
    Norway
    Posts
    1,198
    Mentioned
    4 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by Hammer65 View Post
    That code however, as it stands is not portable, easily maintainable or versatile enough, considering that a large number of projects require sending mail. Using a pre-written class gives you all of those.
    The code is only an example (as stated), which will allow the thread starter to see where the errors in his own code lies.

    As a programmer you should know how to process emails, its a really simple consept. No matter if its just mixing text/html or adding attachments/inline images.

    When you understand the consept, you can either chose to use one of the bloated classes, or you can create your own solution doing exactly what you need.

  13. #13
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,161
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I meant no offense, but I don't want a new coder to get the wrong idea from example code. Writing all that code out for each project is pointless. If you want to sit down in your spare time and read the MIME mail specifications, so that you understand it, more power to you, but considering how bad spam and the general reliability of sending mail is these days, it is much more advisable to use proven code in practice. None of the classes that I suggested are bloated. Reusing code is only logical.

  14. #14
    SitePoint Wizard TheRedDevil's Avatar
    Join Date
    Sep 2004
    Location
    Norway
    Posts
    1,198
    Mentioned
    4 Post(s)
    Tagged
    1 Thread(s)
    Yes, reusing code is logical. The question is always if you should write your own class or use one already created.

    For sending emails, using a premade class will not help your emails not get marked as spam, nor will it give any more reliability. Both solutions only pipe the email to the mailserver, you only know that you have forwarded the email to be sent, you do not know if it actually has been sent.
    The only adventage is that its easier to use a premade class.

    For the classes you suggested, many would disagree with your statement regarding if they are bloated or not. However if something is "bloated" or not, is a personal opinion so it varies greatly.

  15. #15
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,161
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm not saying that it isn't possible to code a class that is just as reliable, but the point is, is that all those classes contain proven code. If you don't mind learning everything about MIME and incorporating it into your own class, fine. It's a little trickier to do this than it is to code a controller class or something else.

    The reliability of the process of sending automated mail, starts with proper structure of the message and the headers you send. A lot of new coders here see the mail function in the manual and are under the impression that that is all they need to send mail. Thanks to the spam situation, that is no longer the case. Furthermore, most new coders don't yet have the knowledge or patience to go rifling through the standards specs, to learn how to code their own, and make the messages compliant and able to punch through some of the filters to the same degree that popular desktop mail applications do.

    The pre-written classes I mentioned are widely used, because they just work. Like any class that is offered up as a tool for any developer to use, they have a few more lines of code than you might use for your own purposes, but then again, if you write something slimmer, you may find that at some point it doesn't do everything it needs to do for a particular project.

    It's true that after the message is handed off to the MTA or external SMTP server, that you have no control or indication that anything went wrong, but considering how dialed up most server spam filters are, especially services like Hotmail, you need to start with a message that is formatted and tweaked as much as possible. Not every developer wants to take the time to learn how to do that when there have been others that have already gone through the work to get the kinks out.


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
  •