Sending email attachments with PHP and mail()



After spending an entire day googling for answers to this problem - all I wanted was a simple and easy script to send attachments, without installing any modules...I finally got mail() to work for sending attachments. Part of the problem, weirdly, was the trailing carriage returns at the end of the headers - there was one or two extras, and it corrupted the attachment. Once I got that straightened out, and the headers, it worked much better. In any case, I'm posting the code directly so that if you are doing the same thing, you can just chop it up and paste it without spending as much time on it as I did. Another note: most emailers use two sets of headers for the text/html content and attachment, but it seems to work fine like this. Since the file content is base64 encoded, the attachment type is hard-coded to be application/octet-stream.

function send_mail_with_attachment($filename, $filepath, $to, $subject, $body, $from = "Mr. Return Address ") {

        //$data = return_file($filename);

        $file = fopen($filepath,'rb');
        $data = fread($file, filesize($filepath) );
        fclose($file);
        $data = chunk_split(base64_encode($data));

        $boundary = uniqid("JONAHMAIL");
        $boundary2 = uniqid("JONAHATTACH");

        //--------------------------------------------------------------------------
        $headers = "From: " . $from . "\n";
        $headers .= "Reply-To: " . $from . "\n";
        $headers .= "MIME-Version: 1.0\n";
        //$headers .= "Content-Transfer-Encoding: 8bit\n";
        $headers .= "Content-Type: multipart/mixed; boundary=\"$boundary2\";\n\n";
        //
        ////$headers .= "This is a multi-part message in MIME format.\n\n";
        ////$message .= "Content-Type: multipart/alternative; boundary=\"$boundary\"\n";
        //--------------------------------------------------------------------------

        //--------------------------------------------------------------------------

        ////$message .= "\n\n--$boundary\n";
        $headers .= "charset=iso-8859-1\n";////
        ////$message .= "Content-Type: text/plain; charset=iso-8859-1\n";
        $headers .= "Content-Transfer-Encoding: 7bit\n\n";
        $headers .= strip_tags($body) . "\r\n\r\n";
        //$headers .= chunk_split(base64_encode(strip_tags($body))) . "\r\n\r\n";
        $headers .= "\n\n--$boundary2\n";
        $headers .= "Content-Type: text/html; charset=\"iso-8859-1\"\n";
        $headers .= "Content-Transfer-Encoding: 7bit\n\n";
        $headers .= $body;
        ////$headers .= "\n\n--$boundary--\n\n\n";

        //Attachment
        $headers .= "\n\n--$boundary2\n";
        $headers .= "Content-Type: \"application/octet-stream\"; name=\"$filename\"\n";
        $headers .= "Content-Transfer-Encoding: base64\n";
        $headers .= "Content-Description: $filename\n";
        $headers .= "Content-Disposition: attachment;   filename=\"$filename\"\n\n";
        $headers .= $data;
        $headers .= "\n\n--$boundary2--\n";
        //--------------------------------------------------------------------------

        if (mail($to, $subject, $message, $headers))
                return true;
        else
                return false;
}


Firefox in AutoIT



I've been spending a lot of time lately doing automation, both for Linux and Windows, and most of my tools are contained in either Perl, PHP, bash, or a tool for windows called Autoit.

One of the things that is a huge pain for me is scripting Firefox. Yes, there are great libs for IE, but not for Firefox, and occasionally, Firefox must be used. For example, a project I've been working with deals with Tor anonymity, and to use Tor, Firefox is standard. So, I've copied the main automation loop, complete with Firefox AutoIT functions, here. These are by no means complete, and you'll probably have to tweak them somewhat, but I think that they're better than some of the stuff out there. Note also that this script is actually an automated bandwidth test, courtesy of Internet Frog. The Firefox functions are defined at the end.


Local $reps = 1
Local $text
If ($CmdLine[0] == 1) Then
	$reps = $CmdLine[1]
	EndIf

Local $i = 0
 

While $i < $reps
	Local $pid

	$pid = FF_Create("http://www.internetfrog.com/mypc/speedtest/")

	If (WinWaitActive("InternetFrog.com: Network Tools, Internet Speed Test and Website Tools - Mozilla Firefox", "", 60) = 1) Then
		Sleep(6000)
		
		$reg_text = "0"
		$reg_text2 = "0"
		$reg_text3 = "0"
		$reg_text4 = "0"
		$reg_text5 = "0"
		$count = 0
		
		WinMinimizeAll()
		Sleep(500)
		WinActivate("InternetFrog.com: Network Tools, Internet Speed Test and Website Tools - Mozilla Firefox")
		Send("{TAB}{TAB}{TAB}{TAB}")
				
		While ( $reg_text == "0" AND $count < 10)
		
		$text = FF_GetText("InternetFrog.com: Network Tools, Internet Speed Test and Website Tools - Mozilla Firefox")
		
		$reg_text = StringRegExp($text, "Download: .{1,10} bps", 1)
		$reg_text2 = StringRegExp($text, "Upload: .{1,10} bps", 1)
		$reg_text3 = StringRegExp($text, "QOS: .{1,4}%", 1)
		$reg_text4 = StringRegExp($text, "RTT: .{1,10} ms", 1)
		$reg_text5 = StringRegExp($text, "MaxPause: .{1,10} ms", 1)
		
		$count = $count + 1
		Sleep(1000)
		WEnd
		
		Else 
		;MsgBox(1, "Entered Loop", "WinWaitActive Failed")
		$text = "0"
	EndIf

	
	If ($reg_text <> "0" ) Then
		
		FileChangeDir(@ScriptDir)
		$logfile = FileOpen("autolog.log", 1)
		FileWriteLine($logfile, @YEAR&"-"&@YDAY&"-"&@HOUR&":"&@MIN&":"&@SEC&"--"& $reg_text[0] &"-"& $reg_text2[0]&"-"& $reg_text3[0]&"-"& $reg_text4[0]&"-"& $reg_text5[0]&"- Test# "&$i+1)
		FileClose($logfile)
		Else
		;MsgBox(1, "Error", "Text Get Failed")
	EndIf
	
	FF_Close("InternetFrog.com: Network Tools, Internet Speed Test and Website Tools - Mozilla Firefox")
	Sleep(1000)
	
	$i = $i + 1
WEnd
This automation uses several AutoIT functions I've written for Firefox:


Func FF_Create($url = "www.mozilla.com", $firefox_exe = "C:\Program Files\Mozilla Firefox\firefox.exe")

Local $pid = Run($firefox_exe)

Sleep(2500)
Send("^l")
Sleep(1000)
Send($url)
Send("{ENTER}")

return $pid
EndFunc

Func FF_GetText($windowtitle = "Mozilla Firefox", $windowtext = "")

Local $count = 0

While (WinActive($windowtitle, $windowtext) = 0 AND $count < 10) 
	WinActivate($windowtitle, $windowtext)
	$count = $count + 1
	WEnd
	
If ($count <> 10) Then
	Send("^a")
	Sleep(500)
	Send("^c")
	Sleep(1000)

	$text = ClipGet()
	return $text
		Else
		return 0
EndIf
EndFunc

Func FF_Close ($windowtitle = "Mozilla Firefox", $windowtext = "")

If (WinActivate($windowtitle, $windowtext) = 1 ) Then
Send("!{F4}")
EndIf

EndFunc

Contact me if this is of use to you, I have a nice Perl handler that parses, extracts, and organizes the data.





Gstalder Farm - wreaths Richelle Gregory - pictures