You are not logged in.
#1 15 May 2007 11:01 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Sending mails
I recently made a simple PHP mail script, of course using the mail() function, but I shortly noticed that for example hotmail blocks mails sent through mail() with PHP, and I am considering using perl, ajax or any other language that will allow the mails to go through. Though I do not know which one, the script is already working nicely regarding getting the information for sender, recipient, message and subject. But which language would be most appropiate for sending mails (making sure they actually get through)?
I will use anything that can take the php variables with their values and send it to the page for the other coding language script, as long as the values remain the same and it works.
Offline
#2 15 May 2007 1:24 pm
Re: Sending mails
mail is filtered out by a lot of spam filters because its used to spam. I think by default it doesnt allow you to specify smtp host, or user/pass for that smtp server, or sender. phpbb has an smtp implementation that is pretty good. I think you can add headers that will make it look less like spam but I think you're either going to have to steal phpbb's mail code or write your own (here's a little example of how you're write your own. SMTP is pretty straightforward. it is by no means complete or very good).
Code:
function smtp($smtp_host, $smtp_port, $username, $password, $to, $from, $subject, $message) { // open a socket to the server if($sh = fsockopen($smtp_host, $smtp_port)) { $buffer = ""; $buf = ""; while($buf = fgets($sh)) { $buffer .= $buf; } // check response if(!(substr($buffer, 0, 3) === "220")) die("server is not runing smtp"); $buffer = ""; // send helo to the server fwrite($sh,"EHLO $smtp_host\r\n"); while($buf = fgets($sh)) { $buffer .= $buf; } // check response if(!(substr($buffer, 0, 3) === "250")) die("Can't authenticate"); $buffer = ""; // authenticate smtp fwrite($sh, "AUTH LOGIN\r\n"); while($buf = fgets($sh)) { $buffer .= $buf; } // check response if(!(substr($buffer, 0, 3) === "334")) die("couldnt open socket to smtp server"); $buffer = ""; // send username (base 64 encoded) fwrite($sh,base64_encode($username)."\r\n"); while($buf = fgets($sh)) { $buffer .= $buf; } // check response if(!(substr($buffer, 0, 3) === "334")) die("username failure"); $buffer = ""; fwrite($sh,base64_encode($password)."\r\n"); while($buf = fgets($sh)) { $buffer .= $buf; } // check response if(!(substr($buffer, 0, 3) === "235")) die("password failure"); $buffer = ""; // send who its from fwrite($sh, "MAIL FROM: $from\r\n"); while($buf = fgets($sh)) { $buffer .= $buf; } // check response if(!(substr($buffer, 0, 3) === "250")) die("Setting sender failed. ".$buffer); $buffer = ""; // enter as many of this block as you have reciepients: // start of TO block fwrite($sh, "RCPT TO: $to\r\n"); while($buf = fgets($sh)) { $buffer .= $buf; } // check response if(!(substr($buffer, 0, 3) === "250")) die("setting receipient failed. ".$buffer); $buffer = ""; // send the email data fwrite($sh, "DATA\r\n"); while($buf = fgets($sh)) { $buffer .= $buf; } // check response if(!(substr($buffer, 0, 3) === "354")) die($buffer); $buffer = ""; fwrite($sh, "To:$to\r\nFrom:$from\r\nSubject:$subject\r\n$message\r\n.\r\n"); while($buf = fgets($sh)) { $buffer .= $buf; } // check response if(!(substr($buffer, 0, 3) === "250")) die("failed to send message. ".$buffer); fwrite($sh, "QUIT"); // close fclose($sh); } else { exit("couldn't connect to the smtp_host"); } }
Offline
#3 15 May 2007 1:32 pm
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Sending mails
Wow, and I just used the mail() function. I can probably locate phpBBs mail function, but will it have any effect using another coding language? I googled it (god I love google) and found that some mail services refuse mails made by php (or something like that), someone suspected. I'll have a poke around for phpBBs.
Offline
#4 15 May 2007 2:06 pm
Re: Sending mails
it all has to do with they way the functions implement the SMTP. the php mail function uses the webserver (or whatever server the webserver has configured in its php.ini) as the mail server. this is thought of a lot of times as an open relay, and most mail from it is marked as spam since there's no real mail service provider providing the email. if you implement it like phpbb (or I did), you actually use your email providers SMTP server to send the message. This usually involves sending authentication information (phpbb's implementation pulls a lot of info from the board's configuration information) before you send the message. If you do it this way, it would be just exactly like sending it from outlook or thunderbird because its going to require you use a valid email address account to send the email. These messages typically pass spam filters.
Last edited by MadHatter (15 May 2007 2:07 pm)
Offline
#5 16 May 2007 6:47 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Sending mails
I stumbled through a little of phpBB, and found their smtp; (It is a bit long though)
Code:
<?php define('SMTP_INCLUDED', 1); // // This function has been modified as provided // by SirSir to allow multiline responses when // using SMTP Extensions // function server_parse($socket, $response, $line = __LINE__) { $server_response = ''; while (substr($server_response, 3, 1) != ' ') { if (!($server_response = fgets($socket, 256))) { message_die(GENERAL_ERROR, "Couldn't get mail server response codes", "", $line, __FILE__); } } if (!(substr($server_response, 0, 3) == $response)) { message_die(GENERAL_ERROR, "Ran into problems sending Mail. Response: $server_response", "", $line, __FILE__); } } // Replacement or substitute for PHP's mail command function smtpmail($mail_to, $subject, $message, $headers = '') { global $board_config; // Fix any bare linefeeds in the message to make it RFC821 Compliant. $message = preg_replace("#(?<!\r)\n#si", "\r\n", $message); if ($headers != '') { if (is_array($headers)) { if (sizeof($headers) > 1) { $headers = join("\n", $headers); } else { $headers = $headers[0]; } } $headers = chop($headers); // Make sure there are no bare linefeeds in the headers $headers = preg_replace('#(?<!\r)\n#si', "\r\n", $headers); // Ok this is rather confusing all things considered, // but we have to grab bcc and cc headers and treat them differently // Something we really didn't take into consideration originally $header_array = explode("\r\n", $headers); @reset($header_array); $headers = ''; while(list(, $header) = each($header_array)) { if (preg_match('#^cc:#si', $header)) { $cc = preg_replace('#^cc:(.*)#si', '\1', $header); } else if (preg_match('#^bcc:#si', $header)) { $bcc = preg_replace('#^bcc:(.*)#si', '\1', $header); $header = ''; } $headers .= ($header != '') ? $header . "\r\n" : ''; } $headers = chop($headers); $cc = explode(', ', $cc); $bcc = explode(', ', $bcc); } if (trim($subject) == '') { message_die(GENERAL_ERROR, "No email Subject specified", "", __LINE__, __FILE__); } if (trim($message) == '') { message_die(GENERAL_ERROR, "Email message was blank", "", __LINE__, __FILE__); } // Ok we have error checked as much as we can to this point let's get on // it already. if( !$socket = @fsockopen($board_config['smtp_host'], 25, $errno, $errstr, 20) ) { message_die(GENERAL_ERROR, "Could not connect to smtp host : $errno : $errstr", "", __LINE__, __FILE__); } // Wait for reply server_parse($socket, "220", __LINE__); // Do we want to use AUTH?, send RFC2554 EHLO, else send RFC821 HELO // This improved as provided by SirSir to accomodate if( !empty($board_config['smtp_username']) && !empty($board_config['smtp_password']) ) { fputs($socket, "EHLO " . $board_config['smtp_host'] . "\r\n"); server_parse($socket, "250", __LINE__); fputs($socket, "AUTH LOGIN\r\n"); server_parse($socket, "334", __LINE__); fputs($socket, base64_encode($board_config['smtp_username']) . "\r\n"); server_parse($socket, "334", __LINE__); fputs($socket, base64_encode($board_config['smtp_password']) . "\r\n"); server_parse($socket, "235", __LINE__); } else { fputs($socket, "HELO " . $board_config['smtp_host'] . "\r\n"); server_parse($socket, "250", __LINE__); } // From this point onward most server response codes should be 250 // Specify who the mail is from.... fputs($socket, "MAIL FROM: <" . $board_config['board_email'] . ">\r\n"); server_parse($socket, "250", __LINE__); // Specify each user to send to and build to header. $to_header = ''; // Add an additional bit of error checking to the To field. $mail_to = (trim($mail_to) == '') ? 'Undisclosed-recipients:;' : trim($mail_to); if (preg_match('#[^ ]+\@[^ ]+#', $mail_to)) { fputs($socket, "RCPT TO: <$mail_to>\r\n"); server_parse($socket, "250", __LINE__); } // Ok now do the CC and BCC fields... @reset($bcc); while(list(, $bcc_address) = each($bcc)) { // Add an additional bit of error checking to bcc header... $bcc_address = trim($bcc_address); if (preg_match('#[^ ]+\@[^ ]+#', $bcc_address)) { fputs($socket, "RCPT TO: <$bcc_address>\r\n"); server_parse($socket, "250", __LINE__); } } @reset($cc); while(list(, $cc_address) = each($cc)) { // Add an additional bit of error checking to cc header $cc_address = trim($cc_address); if (preg_match('#[^ ]+\@[^ ]+#', $cc_address)) { fputs($socket, "RCPT TO: <$cc_address>\r\n"); server_parse($socket, "250", __LINE__); } } // Ok now we tell the server we are ready to start sending data fputs($socket, "DATA\r\n"); // This is the last response code we look for until the end of the message. server_parse($socket, "354", __LINE__); // Send the Subject Line... fputs($socket, "Subject: $subject\r\n"); // Now the To Header. fputs($socket, "To: $mail_to\r\n"); // Now any custom headers.... fputs($socket, "$headers\r\n\r\n"); // Ok now we are ready for the message... fputs($socket, "$message\r\n"); // Ok the all the ingredients are mixed in let's cook this puppy... fputs($socket, ".\r\n"); server_parse($socket, "250", __LINE__); // Now tell the server we are done and close the socket... fputs($socket, "QUIT\r\n"); fclose($socket); return TRUE; } ?>
A pot full of code, but I see this function smtpmail($mail_to, $subject, $message, $headers = ''), which is identical to my mail(variables), maybe if I replaced it with all of this, would that work? Or do I have to mod out any phpBB authorization?
Offline
#6 16 May 2007 7:24 am
Re: Sending mails
there are a few places that you need to edit. message_die and $board_config are phpbb specific. you'll need to create a message_die, or edit all those message die's to a normal die, and you'll need to create the $board_config array with $board_config['smtp_host'], $board_config['smtp_username'], and $board_config['smtp_password'] in order for it to work.
Offline
#7 16 May 2007 8:54 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Sending mails
Changing all the message_die's into pure die's were easy of course, but how do I array $board_config?
Wouldn't replacing my mail($to, $subject, $message$headers) with function smtpmail($mail_to, $subject, $message, $headers = '') and just re-naming the variables work? It would still tell him to send it to all addresses, get the subject, message and headers.
Offline
#8 16 May 2007 10:18 am
Re: Sending mails
smtpmail is written to work with phpbb. it is sending email exactly the same way as the function I wrote. the only difference is, that in phpbb's configuration settings, you define an smtp host, smtp username, and smtp password which is used to send your mail. the function from phpbb that you pulled uses other functions from phpbb's framework (message_die) and uses configuration information ($board_config) as it sends your email.
yes, you can change your mail(...) to smtpmail(...) where you use it (as well as require the smtp.php), but you'll need to change the original smtpmail function (actually the server_parse function) and change message_die to provide some error message, and either declare a $board_config array, and add those 3 items (smtp_host, smtp_username, and smtp_password, or edit the smtpmail function and hard code in your host, username and password.
Offline
#9 20 May 2007 4:01 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Sending mails
Ok, after I while I got in contact with my host, and apparently my smtp_host is the same as my outgoing and ingoing mail, bamboocommandos.com. And I was told that I can use the POP3 mail that I made with my CPanel as smtp_user. So it would be:
host: bamboocommandos.com
user: no_reply [at] bamboocommandos [dot] com
password: hidden
The question is, where do they fit into the smtp functions? The function "server_parse" has these values: ($socket, $response, $line = __LINE__), but I don't understand what I should call the smtp variables so that they work with the function. Or should they perhaps go in the function smtpmail headers?
Offline
#10 22 May 2007 1:19 pm
Re: Sending mails
I've been a bit tied up lately... here's something I threw together that you can use:
just fill in the array up top with your details and you should be golden.
Code:
<?php $settings = array( 'sender'=>'senders@email.address', 'username'=>'mail_username', 'password'=>'mail_password', 'host'=>'mail.server.address' ); function validate($socket, $response, $line = __LINE__) { while(substr($server_response, 3, 1) != ' ') { if(!($server_response = fgets($socket, 256))) { return "Couldn't get mail server response codes"; } } if(!(substr($server_response, 0, 3) == $response)) { return "Ran into problems sending Mail. Response: $server_response"; } return false; } function sendmail($mail_to, $subject, $message, $headers = '') { global $settings; $message = preg_replace("#(?<!\r)\n#si", "\r\n", $message); if($headers != '') { if(is_array($headers)) { if(sizeof($headers) > 1) { $headers = join("\n", $headers); } else { $headers = $headers[0]; } } $headers = chop($headers); $headers = preg_replace('#(?<!\r)\n#si', "\r\n", $headers); $header_array = explode("\r\n", $headers); @reset($header_array); $headers = ''; while(list(, $header) = each($header_array)) { if(preg_match('#^cc:#si', $header)) { $cc = preg_replace('#^cc:(.*)#si', '\1', $header); } else if(preg_match('#^bcc:#si', $header)) { $bcc = preg_replace('#^bcc:(.*)#si', '\1', $header); $header = ''; } $headers .= ($header != '') ? $header . "\r\n" : ''; } $headers = chop($headers); $cc = explode(', ', $cc); $bcc = explode(', ', $bcc); } if(trim($subject) == '') { return "No email Subject specified"; } if(trim($message) == '') { return "Email message was blank"; } if( !$socket = @fsockopen($settings['host'], 25, $errno, $errstr, 20) ) { return "Could not connect to smtp host : $errno : $errstr"; } if(($err = validate($socket, "220", __LINE__)) != false) return $err; if(!empty($settings['username']) && !empty($settings['password']) ) { fputs($socket, "EHLO " . $settings['host'] . "\r\n"); if(($err = validate($socket, "250", __LINE__)) != false) return $err; fputs($socket, "AUTH LOGIN\r\n"); if(($err = validate($socket, "334", __LINE__)) != false) return $err; fputs($socket, base64_encode($settings['username']) . "\r\n"); if(($err = validate($socket, "334", __LINE__)) != false) return $err; fputs($socket, base64_encode($settings['password']) . "\r\n"); if(($err = validate($socket, "235", __LINE__)) != false) return $err; } else { fputs($socket, "HELO " . $settings['host'] . "\r\n"); if(($err = validate($socket, "250", __LINE__)) != false) return $err; } fputs($socket, "MAIL FROM: <" . $settings['sender'] . ">\r\n"); if(($err = validate($socket, "250", __LINE__)) != false) return $err; $to_header = ''; $mail_to = (trim($mail_to) == '') ? 'Undisclosed-recipients:;' : trim($mail_to); if (preg_match('#[^ ]+\@[^ ]+#', $mail_to)) { fputs($socket, "RCPT TO: <$mail_to>\r\n"); if(($err = validate($socket, "250", __LINE__)) != false) return $err; } @reset($bcc); while(list(, $bcc_address) = each($bcc)) { $bcc_address = trim($bcc_address); if (preg_match('#[^ ]+\@[^ ]+#', $bcc_address)) { fputs($socket, "RCPT TO: <$bcc_address>\r\n"); if(($err = validate($socket, "250", __LINE__)) != false) return $err; } } @reset($cc); while(list(, $cc_address) = each($cc)) { $cc_address = trim($cc_address); if (preg_match('#[^ ]+\@[^ ]+#', $cc_address)) { fputs($socket, "RCPT TO: <$cc_address>\r\n"); if(($err = validate($socket, "250", __LINE__)) != false) return $err; } } fputs($socket, "DATA\r\n"); if(($err = validate($socket, "354", __LINE__)) != false) return $err; fputs($socket, "Subject: $subject\r\n"); fputs($socket, "To: $mail_to\r\n"); fputs($socket, "From: ".$settings['sender']); fputs($socket, "$headers\r\n\r\n"); fputs($socket, "$message\r\n"); fputs($socket, ".\r\n"); if(($err = validate($socket, "250", __LINE__)) != false) return $err; fputs($socket, "QUIT\r\n"); fclose($socket); return false; } ?>
Offline
#11 23 May 2007 12:30 pm
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Sending mails
Ok, so to use it, I could do this:
Code:
<?php include("smtp.php"); function sendmail( $mail_to = $_POST[mail_to]; $subject = $_POST[subject]; $message = $_POST[message]; $headers = $_POST[headers]; ) ?>
couldn't I? In my eyes that should find the function, post the values into it and then send it. Though I have never actually used a function in another file before...
Offline
#12 23 May 2007 2:38 pm
Re: Sending mails
Code:
<?php include("smtp.php"); sendmail($_POST[mail_to], $_POST[subject], $_POST[message], $_POST[headers]); ?>
but I'd use it like this:
Code:
<?php include("smtp.php"); if(($error = sendmail($_POST[mail_to], $_POST[subject], $_POST[message], $_POST[headers])) != false) { // display the $error message if you need to know what happened, otherwise, // display something to the user that their email didnt go through. echo "Failed to send the email"; } ?>
so I could display some error message to the user.
when you require / include a file, to PHP its just like copying that file and pasting it in where the require / include is. after you include / require it, then you just call the function normally.
Offline
#13 24 May 2007 7:00 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Sending mails
At the first test, I got this:
Code:
Could not connect to smtp host : 111 : Connection refused
Could this be because I set the settings wrong? I set host to mail [dot] bamboocommandos [dot] com, and the rest to the mail stuff (I set username to the actual name of the mail, meaning what is before @domain.com). My host told me that mail [dot] bamboocommandos [dot] com is both outgoing and ingoing mail, so I guess it is something with mail, username and password.
Offline
#15 25 May 2007 5:18 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Sending mails
Hmm, I now changed it to:
Code:
'sender'=>'address [at] bamboocommandos [dot] com', 'username'=>'address+bamboocommandos [dot] com', 'password'=>'HIDDEN', 'host'=>'mail [dot] bamboocommandos [dot] com'
But I still get the same error, even though my CPanel told me this:
Code:
Mail Server Username: address+bamboocommandos [dot] com Incoming Mail Server: mail [dot] bamboocommandos [dot] com Outgoing Mail Server: mail [dot] bamboocommandos [dot] com (server requires authentication) Supported Incoming Mail Protocols: POP3, POP3S (SSL/TLS), IMAP, IMAPS (SSL/TLS) Supported Outgoing Mail Protocols: SMTP, SMTPS (SSL/TLS)
As far as I can see, I am authenticating it.
Offline
#17 26 May 2007 3:36 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Sending mails
I wrote it just like that, mail.bamboocommandos.com, just checked my smtp.php again, and line seven says:
Code:
'host'=>'mail.bamboocommandos.com'
Copy and paste action, this is weird.
Offline
#18 28 May 2007 12:56 pm
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Sending mails
Had a quick browse at their database, searched for SMTP Mail, and this came up:
Does this mean I have to use another coding language to send mails? And is their blocking of port 25 maybe the cause of the error message I get?Support Centre :
Problem
SMTP fails when sending through mailing list (mailman or Dada Mail), but no error logs are generated.
Solution
Due to recent changes in our firewall, we do not support the origination of a MTA from our server. This change was brought about to eliminate the possibility of spam originating from our servers across port 25. Alternatively, you can use sendmail, located at /usr/sbin/sendmail, with mailman or Dada Mail.
Offline
#19 28 May 2007 7:16 pm
Re: Sending mails
it may. that is specifically for mailing lists, but doesn't give specifics as to what or why. you may want to open a ticket with them and ask why you cant open a socket to the mail server (in your implementation of smtp) from your webserver.
Offline
#20 29 May 2007 2:17 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Sending mails
Changed the port to 26, and it worked, received in both GMail and HotMail. Though, it says:
Code:
Warning: Variable passed to each() is not an array or object in /home/bambooco/public_html/mail/smtp.php on line 83 Warning: Variable passed to each() is not an array or object in /home/bambooco/public_html/mail/smtp.php on line 91
Are those two very important, or just a flaw in the code that occured when I changed the port?
Offline
#22 29 May 2007 9:09 am
#24 29 May 2007 11:32 am
- Butcher
- Moderator
- From: Norway
- Registered: Jul 2006
- Posts: 308
Re: Sending mails
I am, each header is like an array: "To: MAIL, To: MAIL," etc, so it sends to all the addresses. Seems to work too. Will it give the CC and BCC error if there is not content for those two?
Offline
#25 29 May 2007 5:05 pm
Re: Sending mails
to should be a comma delimited list of email addresses: To: addr, addr, addr, addr. this function only allows for one To: address but you can add cc or bcc addresses in the header array. unless you plan on cc'ing or bcc'ing someone I'd leave the header parameter alone.
Offline