LXV. Mail Functions

简介

The mail() function allows you to send mail.

需求

For the Mail functions to be available, PHP must have access to the sendmail binary on your system during compile time. If you use another mail program, such as qmail or postfix, be sure to use the appropriate sendmail wrappers that come with them. PHP will first look for sendmail in your PATH, and then in the following: /usr/bin:/usr/sbin:/usr/etc:/etc:/usr/ucblib:/usr/lib. It's highly recommended to have sendmail available from your PATH. Also, the user that compiled PHP must have permission to access the sendmail binary.

安装

本函数库作为 PHP 内核的一部分,不用安装就能使用。

运行时配置

这些函数的行为受 php.ini 的影响。

表格 1. Mail configuration options

NameDefaultChangeableChangelog
SMTP"localhost"PHP_INI_ALL 
smtp_port"25"PHP_INI_ALLAvailable since PHP 4.3.0.
sendmail_fromNULLPHP_INI_ALL 
sendmail_pathNULLPHP_INI_SYSTEM 
有关 PHP_INI_* 常量进一步的细节与定义参见附录 G

以下是配置选项的简要解释。

SMTP string

Used under Windows only: DNS name or IP address of the SMTP server PHP should use for mail sent with the mail() function.

smtp_port int

Used under Windows only: Number of the port to connect to the server specified with the SMTP setting when sending mail with mail(); defaults to 25. Only available since PHP 4.3.0.

sendmail_from string

Which "From:" mail address should be used in mail sent from PHP under Windows.

sendmail_path string

Where the sendmail program can be found, usually /usr/sbin/sendmail or /usr/lib/sendmail. configure does an honest attempt of locating this one for you and set a default, but if it fails, you can set it here.

Systems not using sendmail should set this directive to the sendmail wrapper/replacement their mail system offers, if any. For example, Qmail users can normally set it to /var/qmail/bin/sendmail or /var/qmail/bin/qmail-inject.

qmail-inject does not require any option to process mail correctly.

This directive works also under Windows. If set, smtp, smtp_port and sendmail_from are ignored and the specified command is executed.

资源类型

本扩展模块未定义任何资源类型。

预定义常量

本扩展模块未定义任何常量。

目录
ezmlm_hash -- Calculate the hash value needed by EZMLM
mail -- Send mail

add a note add a note User Contributed Notes
furrykef at gmail dot com
04-Nov-2006 06:44
By the way, also read RFC 3696 and its errata. These define rules for e-mail addresses in more plain language.
furrykef at gmail dot com
04-Nov-2006 06:38
If you use a regexp to validate an e-mail address, be sure that you actually use a correct regexp. In particular, there are more valid punctuation characters than you may think. All of these characters may appear to the left of the at-sign: ! # $ % & ' * + - / = ? ^ _ ` { | } ~

Don't believe me? Look at RFC 2822, which defines the current standard for e-mail addresses. ;)

There's no reason, other than laziness, to reject e-mail address that contain these characters to the left of the at-sign. You might think that nobody uses these characters, but people who write incorrect regexps are one reason why. Do your part to correct this situation. :)

Note in particular the plus sign. Many regexps reject addresses with the plus sign, but there are e-mail addresses that have them. In particular, gmail has a special feature called "plus addressing", so that if your username is "joeuser", you can use "joeuser+web at gmail dot com" and "joeuser+business at gmail dot com" as separate addresses, and the e-mail will be sorted depending on which address was used.

Even allowing all those punctuation characters isn't enough to fully satisfy RFC2822. For example, you can use quoted strings to allow spaces in e-mail addresses, such as "joe user" at somewhere dot com. But I wouldn't worry about such things too much, because they're too obscure; just make sure you get all the punctuation characters in there.
krzystu at krzystu dot net
20-Oct-2006 05:41
What about Bounce parameter for sendmail:
"-f $from" as the fifth one. Without that Return-Path will be set to sendmail administrator
Super David
16-Aug-2006 09:30
Just to follow up on Nick Baicoianu's useful note below, one minor correction to make (it drove me insane for a while there until I noticed it):

This line:
<?php
$msg
.= "Content-Type: multipart/alternative; boundary=\"".$htmlalt_mime_boundary."\"".$eol;
?>

Should in fact read:
<?php
$headers
.= "Content-Type: multipart/alternative; boundary=\"".$htmlalt_mime_boundary."\"".$eol;
?>

The line should be declared as a header, not as part of the message content.
Nick Baicoianu
15-Aug-2006 03:19
In response to jcwebb's excellent post regarding multipart/alternative and attachments: the code works great in sending attachments, but I got inconsistent results across different email clients (MS Outlook worked, but Thunderbird and mutt didn't) when displaying the HTML/plain text alternate portion.

To fix this, you need to define a new MIME boundary for the HTML/Plain text alternates section ONLY - this way you can "nest" the two together so the alternate works properly in all email clients. 

here's a modified version of the code for the message body only (see jcwebb's post for the entire message code)
<?
$msg
= "";

# Attachment
$msg .= "--".$mime_boundary.$eol;
$msg .= "Content-Type: application/pdf; name=\"".$letter."\"".$eol// sometimes i have to send MS Word, use 'msword' instead of 'pdf'
$msg .= "Content-Transfer-Encoding: base64".$eol;
$msg .= "Content-Disposition: attachment; filename=\"".$letter."\"".$eol.$eol; // !! This line needs TWO end of lines !! IMPORTANT !!
$msg .= $f_contents.$eol.$eol;

# Setup for text OR html -
$msg .= "--".$mime_boundary.$eol;
$htmlalt_mime_boundary = $mime_boundary."_htmlalt"; //we must define a different MIME boundary for this section for the alternative to work properly in all email clients
$msg .= "Content-Type: multipart/alternative; boundary=\"".$htmlalt_mime_boundary."\"".$eol;

# Text Version
$msg .= "--".$htmlalt_mime_boundary.$eol;
$msg .= "Content-Type: text/plain; charset=iso-8859-1".$eol;
$msg .= "Content-Transfer-Encoding: 8bit".$eol;
$msg .= "This is a multi-part message in MIME format.".$eol;
$msg .= "If you are reading this, please update your email-reading-software.".$eol;
$msg .= "+ + Text Only Email from Genius Jon + +".$eol.$eol;

# HTML Version
$msg .= "--".$htmlalt_mime_boundary.$eol;
$msg .= "Content-Type: text/html; charset=iso-8859-1".$eol;
$msg .= "Content-Transfer-Encoding: 8bit".$eol;
$msg .= $body.$eol.$eol;

//close the html/plain text alternate portion
$msg .= "--".$htmlalt_mime_boundary."--".$eol.$eol;

# Finished
$msg .= "--".$mime_boundary."--".$eol.$eol;
?>
expertphp at gmail dot com
13-Jul-2006 01:05
For all those having problems sending messages to INBOX (spam-free messages)
i recommend using FromHost() function from XPM2's SMTP class.
With this function you can set the name of the host that is sending the message.
Pay very much attention when using this function, because i recommend the IP address of the host
to reflect the MX zone declared for it, and the IP address of the mail sender.

A simple example of how to use for sending an e-mail directly to the client:
<?php

$hostname
= 'maildomain.net';

// path to smtp.php file from XPM2 package for inclusion
require_once '/path/smtp.php';

$mail = new SMTP;
$mail->Delivery('client');

$mail->From('me@'.$hostname, 'My name');
$mail->FromHost($hostname, $havemx);
if(!
$havemx) die("The hostname: '".$hostname."' doesn't have a valid MX zone!");

$mail->AddTo('client@destination.net');
$mail->Text('It is simple to use XPM2');
$sent = $mail->Send('Hello World!');

echo
$sent ? 'Success.' : $mail->result;

?>

This is one of the most reliable anti-spam/bulk mail techniques.
For more details visit: http://xpertmailer.sourceforge.net/DOCUMENTATION/
chris at w3style dot co dot uk
28-May-2006 03:10
mail() opens a new connection for each email it sends out which causes some significant overhead if you're sending out many emails in one go.

You can avoid this by using sockets like Antony Male has done and then send as many emails as you like through the same connection.  It should be noted however that some MTA's will reject your emails after you've sent over a certain threshold on the same connection (about 10 would be normal) so it's worth disconnecting and reconnecting periodically.

I'm surprised nobody has drawn attention to PHPMailer (http://phpmailer.sourceforge.net) which makes this sort of stuff really easy.  Even better still is Swift Mailer by Chris Corbyn (http://www.swiftmailer.org) because it includes plugin support and it's tighter.

Another thing that's bitten me before is Magic Quotes! If it's turned on and you're sending attachments that seem to arrive corrupted it's more than likely because your attachments are full of backslashes.

Hope the links might be useful to some people :)
josephcmiller2 at gmail dot com
26-May-2006 10:26
I have been using the function mymail() provided by Antony Male (below) to send mail on my server, but with a couple of modifications.  First, I needed to enable AUTH LOGIN in order to use my smtp server from my ISP.  Second, his mymail() function allows for a $from to be used, but the function does not accept any such parameter.  I have addressed the latter issue by parsing the headers to obtain the From: address.  If this is not provided, failed mail will not be returned properly to the sender.

// modified to provide authenticated logins
function mymail($to,$subject,$message,$headers)
{

  // set as global variable
  global $GLOBAL;
 
  // get From address
  if ( preg_match("/From:.*?[A-Za-z0-9\._%-]+\@[A-Za-z0-9\._%-]+.*/", $headers, $froms) ) {
     preg_match("/[A-Za-z0-9\._%-]+\@[A-Za-z0-9\._%-]+/", $froms[0], $fromarr);
     $from = $fromarr[0];
  }

  // Open an SMTP connection
  $cp = fsockopen ($GLOBAL["SMTP_SERVER"], $GLOBAL["SMTP_PORT"], &$errno, &$errstr, 1);
  if (!$cp)
   return "Failed to even make a connection";
  $res=fgets($cp,256);
  if(substr($res,0,3) != "220") return "Failed to connect";

  // Say hello...
  fputs($cp, "HELO ".$GLOBAL["SMTP_SERVER"]."\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "250") return "Failed to Introduce";
 
  // perform authentication
  fputs($cp, "auth login\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "334") return "Failed to Initiate Authentication";
 
  fputs($cp, base64_encode($GLOBAL["SMTP_USERNAME"])."\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "334") return "Failed to Provide Username for Authentication";
 
  fputs($cp, base64_encode($GLOBAL["SMTP_PASSWORD"])."\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "235") return "Failed to Authenticate";

  // Mail from...
  fputs($cp, "MAIL FROM: <$from>\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "250") return "MAIL FROM failed";

  // Rcpt to...
  fputs($cp, "RCPT TO: <$to>\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "250") return "RCPT TO failed";

  // Data...
  fputs($cp, "DATA\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "354") return "DATA failed";

  // Send To:, From:, Subject:, other headers, blank line, message, and finish
  // with a period on its own line (for end of message)
  fputs($cp, "To: $to\r\nFrom: $from\r\nSubject: $subject\r\n$headers\r\n\r\n$message\r\n.\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "250") return "Message Body Failed";

  // ...And time to quit...
  fputs($cp,"QUIT\r\n");
  $res=fgets($cp,256);
  if(substr($res,0,3) != "221") return "QUIT failed";

  return true;
}
martin dot felis at gmx dot de
11-Mar-2006 11:03
If using a chroot environment and you don't want to have a full mailer in it, mini-sendmail (can be found at http://www.acme.com/software/mini_sendmail/) is very useful. It is just a small binary that sends mails over your local mta over port 25.

Martin
judas dot iscariote at gmail dot com
07-Mar-2006 01:07
For those of you worried about Mail Injection .. Zend_Mail provides protection against this trick.

http://framework.zend.com/manual/zend.mail.html
derernst at gmx dot ch
18-Feb-2006 12:43
Suggestion for methods checking form inputs for e-mail injection attempts.

Any inputs expected from single-line text fields can just be refused if they contain a newline character. The second function tries to minimize matches on non-evil inputs by matching suspect strings only if preceded by a newline character. (Anyway, if this is considered to be safe, it will of course do it for single-line inputs, too.)

<?php

/**
* Check single-line inputs:
* Returns false if text contains newline character 
*/
function has_no_newlines($text)
{
   return
preg_match("/(%0A|%0D|\\n+|\\r+)/i", $text) == 0;
}

/**
* Check multi-line inputs:
* Returns false if text contains newline followed by
* email-header specific string
*/
function has_no_emailheaders($text)
{
   return
preg_match("/(%0A|%0D|\\n+|\\r+)(content-type:|to:|cc:|bcc:)/i", $text) == 0;
}

?>
jcwebb at dicoe dot com
08-Feb-2006 06:16
Corrupted Attachments ???
I spent many hours with corrupted attachments (of all types of files) - The answer: a blank line is needed after $msg.=$file \r\n \r\n [incredible but true].
Heres some useful code for sending an attachment, and display html OR text depending on the users email-reader.

i work with many different systems, so...

<?php # Is the OS Windows or Mac or Linux
if (strtoupper(substr(PHP_OS,0,3)=='WIN')) {
 
$eol="\r\n";
} elseif (
strtoupper(substr(PHP_OS,0,3)=='MAC')) {
 
$eol="\r";
} else {
 
$eol="\n";
}
?>

<?php
# File for Attachment
$f_name="../../letters/".$letter;    // use relative path OR ELSE big headaches. $letter is my file for attaching.
$handle=fopen($f_name, 'rb');
$f_contents=fread($handle, filesize($f_name));
$f_contents=chunk_split(base64_encode($f_contents));    //Encode The Data For Transition using base64_encode();
$f_type=filetype($f_name);
fclose($handle);
# To Email Address
$emailaddress="him@her.com";
# Message Subject
$emailsubject="Heres An Email with a PDF".date("Y/m/d H:i:s");
# Message Body
ob_start();
  require(
"emailbody.php");    // i made a simple & pretty page for showing in the email
$body=ob_get_contents(); ob_end_clean();

# Common Headers
$headers .= 'From: Jonny <jon@genius.com>'.$eol;
$headers .= 'Reply-To: Jonny <jon@genius.com>'.$eol;
$headers .= 'Return-Path: Jonny <jon@genius.com>'.$eol;    // these two to set reply address
$headers .= "Message-ID: <".$now." TheSystem@".$_SERVER['SERVER_NAME'].">".$eol;
$headers .= "X-Mailer: PHP v".phpversion().$eol;          // These two to help avoid spam-filters
# Boundry for marking the split & Multitype Headers
$mime_boundary=md5(time());
$headers .= 'MIME-Version: 1.0'.$eol;
$headers .= "Content-Type: multipart/related; boundary=\"".$mime_boundary."\"".$eol;
$msg = "";

# Attachment
$msg .= "--".$mime_boundary.$eol;
$msg .= "Content-Type: application/pdf; name=\"".$letter."\"".$eol// sometimes i have to send MS Word, use 'msword' instead of 'pdf'
$msg .= "Content-Transfer-Encoding: base64".$eol;
$msg .= "Content-Disposition: attachment; filename=\"".$letter."\"".$eol.$eol; // !! This line needs TWO end of lines !! IMPORTANT !!
$msg .= $f_contents.$eol.$eol;
# Setup for text OR html
$msg .= "Content-Type: multipart/alternative".$eol;

# Text Version
$msg .= "--".$mime_boundary.$eol;
$msg .= "Content-Type: text/plain; charset=iso-8859-1".$eol;
$msg .= "Content-Transfer-Encoding: 8bit".$eol;
$msg .= "This is a multi-part message in MIME format.".$eol;
$msg .= "If you are reading this, please update your email-reading-software.".$eol;
$msg .= "+ + Text Only Email from Genius Jon + +".$eol.$eol;

# HTML Version
$msg .= "--".$mime_boundary.$eol;
$msg .= "Content-Type: text/html; charset=iso-8859-1".$eol;
$msg .= "Content-Transfer-Encoding: 8bit".$eol;
$msg .= $body.$eol.$eol;

# Finished
$msg .= "--".$mime_boundary."--".$eol.$eol// finish with two eol's for better security. see Injection.

# SEND THE EMAIL
ini_set(sendmail_from,'from@me.com');  // the INI lines are to force the From Address to be used !
 
mail($emailaddress, $emailsubject, $msg, $headers);
ini_restore(sendmail_from);
?>


I hope this helps.
Jon Webb [Madrid&London]
lawcd at ntlworld dot com
31-Jan-2006 01:38
For those of you with the exim, if its not sending mail with the -i option and you cant easily change this, you might want to check out the imap_mail() function which works almost exactly the same and doesnt use exim, most web hosts provide this. If you using your own server then php needs to be compiled with imap libraries etc.

See http://uk2.php.net/manual/en/function.imap-mail.php
expertphp at gmail dot com
28-Jan-2006 06:31
If you try to set "From:" e-mail header value under Windows when it is already defined in php.ini "sendmail_from" value, this will doesn't work. If you still want to customize this value, then you must use another option like XPertMailer ( http://www.xpertmailer.com/ ) to send the e-mail directly to the client SMTP server or use a relay SMTP server with authentification option.
Ben Cooke
15-Dec-2005 09:34
Note that there is a big difference between the behavior of this function on Windows systems vs. UNIX systems. On Windows it delivers directly to an SMTP server, while on a UNIX system it uses a local command to hand off to the system's own MTA.

The upshot of all this is that on a Windows system your  message and headers must use the standard line endings \r\n as prescribed by the email specs. On a UNIX system the MTA's "sendmail" interface assumes that recieved data will use UNIX line endings and will turn any \n to \r\n, so you must supply only \n to mail() on a UNIX system to avoid the MTA hypercorrecting to \r\r\n.

If you use plain old \n on a Windows system, some MTAs will get a little upset. qmail in particular will refuse outright to accept any message that has a lonely \n without an accompanying \r.
aweather88 at gmail dot com
15-Dec-2005 06:45
I spent hours searching the web trying to figure out why I was getting a "WARNING: mail(): SMTP server response: 501 5.5.4 Invalid Address " every time I was using the mail() function on my server (Win2K3,IIS 6.0,PHP4.4.1).  I knew everything was setup properly for SMTP based on other non IIS 6.0 configurations.

Turns out that the IIS 6.0 SMTP service does not like formatting of the "From" field in mail headers.  For instance:
<?PHP
  
//This line DOES NOT send  mail message correctly
  
$headers .= "From: \"".$fromname."\" <".$fromaddress.">\n";
?>
However this works:
<?PHP
  
//This line sends mail message correctly
  
$headers .= "From: \"".$fromaddress."\"\n";
?>

The fix is in Microsoft Article ID 291828 ( http://support.microsoft.com/?id=291828 ).  Even though the "bug" workaround is for IIS 6.0 on Exchange 2003 communicating with a UNIX server, THIS SOLVES THE PROBLEM.  Just skip down to the last section for Exchange 2003 and follow the instructions to modify the IIS 6 MetaBase with the MetaBase Explorer found in the IIS 6 Resource Kit.
tinus
09-Dec-2005 05:50
as to fred's posting, I had to change the code a bit:
-add a hashbang
-add "-t -i " to the sendmail call

great idea though.

#!/usr/bin/php
<?php

       $tmpfile
= "/tmp/" . uniqid('') . ".mail";

      
$fp = fopen($tmpfile,"w");

      
fwrite($fp,"x-wls-cc-filter: On\n");
       while(
$line = fgets(STDIN))
       {
              
$line = ereg_replace("^bcc:","x-wlsspam-bcc:",$line);
              
$line = ereg_replace("^cc:","x-wlsspam-cc:",$line);
              
fwrite($fp,$line);
       }
      
fclose($fp);

      
$cmd = '/usr/sbin/sendmail -t -i ';
       for(
$i = 1 ; $i < $argc; $i++)
       {
              
$cmd .= $argv[$i];
              
$cmd .= ' ';
       }
      
$cmd .= "<$tmpfile";
      
system($cmd);
?>
spinningvertex at gmail dot com
02-Nov-2005 06:38
I found the mail validator http://www.apps.ietf.org/msglint.html  to be very usefull.
expertphp at yahoo dot com
08-Oct-2005 09:45
Send an e-mail directly to client smtp server in real time.
For more informations, please visit : http://expert.no-ip.org/?free=smtp_mail&func

<?php

@set_time_limit(0);
 
require_once
'smtp_mail.php';
 
$to = "expertphp@yahoo.com";
$from = "from@myaccount.com";
$subject = "Subject here";
 
$headers = "MIME-Version: 1.0\r\n".
  
"Content-type: text/html; charset=iso-8859-1\r\n".
  
"From: \"My Name\" <".$from.">\r\n".
  
"To: \"Client\" <".$to.">\r\n".
  
"Date: ".date("r")."\r\n".
  
"Subject: ".$subject."\r\n";
 
$message = "
<html>
<body>
<b>html message</b><br>
<font color=\"red\">here</font>
<img src=\"http://static.php.net/www.php.net/images/php.gif\"
border=\"0\" alt=\"\">
</body>
</html>
"
;

$response = smtp_mail($to, $subject, $message, $from, $headers);
 
if(
$response[0]) echo "The message has been sent !<br />\n".$response[1];
else echo
"The message can not been sent !<br />\n".$response[1];
 
?>
fnjordy at gmail dot com
05-Oct-2005 05:54
Another example of sending a utf-8 HTML mail:

$to = 'bob@barnyard.com';
$subject = 'Wakeup bob!';
$message = '<b>yo</b>, whassup?';
$headers = "From: server@barnyard.com\r\n" .
       'X-Mailer: PHP/' . phpversion() . "\r\n" .
       "MIME-Version: 1.0\r\n" .
       "Content-Type: text/html; charset=utf-8\r\n" .
       "Content-Transfer-Encoding: 8bit\r\n\r\n";

// Send
mail($to, $subject, $message, $headers);
fontajos at phpeppershop dot com
21-Sep-2005 11:24
Problems with Microsoft Exchange and PHP as ISAPI-module

We found out, that if you want to send multipart mime emails using the PHP mail-function on a Windows box using a Microsoft Exchange server, you have to use separate containers for the mail body and the mail header.

In many examples like in http://www.zend.com/zend/trick/html-email.php or in the book PHP developers cookbook you find html multipart/alternative mailing solutions that build the mime header and the mail body into one PHP variable and send this as fourth argument (header) to the PHP mail-function. This works fine on most systems but not on the above mentioned combination.

We found a rather trivial solution: Simply split the mime mail header and the mail body into two separate variables and give them separately to the PHP mail function, example:

<?php
//add From: header
$headers = "From: webserver@localhost\r\n";

//specify MIME version 1.0
$headers .= "MIME-Version: 1.0\r\n";

//unique boundary
$boundary = uniqid("HTMLDEMO");

//tell e-mail client this e-mail contains//alternate versions
$headers .= "Content-Type: multipart/mixed; boundary = $boundary\r\n\r\n";

//plain text version of message
$body = "--$boundary\r\n" .
  
"Content-Type: text/plain; charset=ISO-8859-1\r\n" .
  
"Content-Transfer-Encoding: base64\r\n\r\n";
$body .= chunk_split(base64_encode("This is the plain text version!"));

//HTML version of message
$body .= "--$boundary\r\n" .
  
"Content-Type: text/html; charset=ISO-8859-1\r\n" .
  
"Content-Transfer-Encoding: base64\r\n\r\n";
$body .= chunk_split(base64_encode("This the <b>HTML</b> version!"));

//send message
mail("root@localhost", "An HTML Message", $body, $headers);
?>
valeriogiuffrida at hotmail dot com
09-Sep-2005 05:53
Sometimes using that headers:

$header = "Return-Path: lostpass@website.net\n";
$header .= "X-Sender: lostpass@website.net\n";
$header .= "From: This is my website <lostpass@website.net>\n";
$header .= "X-Mailer:PHP 5.1\n";
$header .= "MIME-Version: 1.0\n";

Gmail and Hotmail could consider it as "spam", so I just inserted before to send email:

 ini_set(sendmail_from, "lostpass@mywebsite.net");

and ini_restore after it...
mail at hotbytes dot de
28-May-2005 06:11
@tudor:

Take a look at this class:
http://www.phpguru.org/static/mime.mail.html

<!-- snip from the description
A class for sending mime based email. It can send:
- HTML Email
- HTML Email with embedded images
- HTML Email with attachments
- HTML Email with embedded images and attachments
- Text email
- Text email with attachments
snap -->

This may help you with your problem

Regards,
Andre
26-May-2005 06:18
If you are seeing unwanted line breaks preceded by exclamation marks ("!") in the emails you send with mail(), you may be having the same problem I had: exceeding the maximum line length (998 chars) specified in RFC 2822 (http://www.faqs.org/rfcs/rfc2822.html).
You can get around this restriction by using base64 encoding: add a "Content-Transfer-Encoding: base64" header and encode the contents with
  $base64contents = rtrim(chunk_split(
   base64_encode($contents)));
Andrew W
28-Apr-2005 06:19
I spent weeks trying to work out why PHP couldnt send mail through Exim (called locally) when for all other purposes Exim worked fine.  Here, after hours of work is the answer and I hope it saves someone else some time:

PHP by default calls sendmail/exim/whatever with the options -t & -i

-i is causing Exim to sit there waiting for more input, not detecting the end of the message.  You need to tell it not to use -i by manually specifying the arguments you DO want on sendmail_path like this:

sendmail_path = /path/to/exim -t
jdephix at hotmail dot com
03-Mar-2005 04:25
How to add multiple attachment to an email:

An email can be split into many parts separated by a boundary followed by a Content-Type and a Content-Disposition.

The boundary is initialized as follows:
<?php
$boundary
= '-----=' . md5( uniqid ( rand() ) );
?>

You can attach a Word document if you specify:
<?php
$message
.= "Content-Type: application/msword; name=\"my attachment\"\n";
$message .= "Content-Transfer-Encoding: base64\n";
$message .= "Content-Disposition: attachment; filename=\"$theFile\"\n\n";
?>

When adding a file you must open it and read it with fopen and add the content to the message:
<?php
$path
= "whatever the path to the file is";
$fp = fopen($path, 'r');
do
//we loop until there is no data left
{
      
$data = fread($fp, 8192);
       if (
strlen($data) == 0) break;
      
$content .= $data;
     } while (
true);
$content_encode = chunk_split(base64_encode($content));
$message .= $content_encode . "\n";
$message .= "--" . $boundary . "\n";
?>

Add the needed headers and send!
<?php
$headers 
= "From: \"Me\"<me@here.com>\n";
$headers .= "MIME-Version: 1.0\n";
$headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"";
mail('myAddress@hotmail.com', 'Email with attachment from PHP', $message, $headers);
?>

Finally, if you add an image and want it displayed in your email, change the Content-Type from attachment to inline:

<?php
$message
.= "Content-Disposition: inline; filename=\"$theFile\"\n\n";
?>

Enjoy!
Metin Savignano <ms201 at zipfly dot de>
04-Feb-2005 09:32
If you want to use the mail() function under *nix and Windows alike, I recommend using the little fake sendmail utility available under http://glob.com.au/sendmail/ (bsd license).

I tried it and it works great for me. I can use the very same PHP code on both the Linux server as well as my Windows test machine. It supports auth smtp.

Instructions: Download fake sendmail, unzip it into a directory of your choice, customize the sendmail.ini to your smtp server, set the sendmail path in your php.ini, and you're done.
Ivo Fokkema I.Fokkema att LUMC d0ttt nl
06-Sep-2004 04:03
We have a open source project that needed to be able to function on as many platforms and configurations as possible. Using '\n' as end-of-line for emailheaders would probably 'break' the email functionality on Windows and Mac platforms.

I have fixed this using the code below. Please note that since I don't have any access to a Mac server, this setup is not tested on a Mac, but should work.

if (strtoupper(substr(PHP_OS, 0, 3) == 'WIN')) {
       $s_eol = "\r\n";
} elseif (strtoupper(substr(PHP_OS, 0, 3) == 'MAC')) {
       $s_eol = "\r";
} else {
       $s_eol = "\n";
}

(Thanx to Eric Gach on http://www.phpbuilder.com/lists/php-windows/2003032/0057.php for the inspiration!)

Then construct your headers using

$s_headers = 'From: registrationform@example.org' . $s_eol;

Hope this helps anyone!!!

Ivo
php at richardneill dot org
13-Jul-2004 09:09
Postfix under Mandrake 10.0 also objects to \\r\\n. The result is that every email is double-spaced, and all attachments break. (it was OK in 9.1).  My (short-term) fix is this:

$message = str_replace("\r",'',$message);

This discussion may be relevant:
http://www.phpdiscuss.com/article.php?id=60615&group=php.bugs
wtmusic
13-Jun-2004 03:53
Beware of Mac "line feeds" (\r) in long text strings in the body of a message--may cause Sendmail to insert exclamation points after every 256 chars
def at speakeasy dot org
22-May-2004 09:11
The body of the message cannot, in some (many?) cases, contain "bare line feeds" -- i.e. just "\n".

See this: http://cr.yp.to/docs/smtplf.html
josh at sdfahrenheit dot com
16-Apr-2004 10:52
For anyone having problems with attached files coming through garbled, make sure you have magic_quotes_runtime set to Off in your php.ini - it adds funky escape chars to your attached data and garbles the attachment.

This was giving me all kinds of grief.
07-Apr-2004 08:36
If your system MTA is exim, you might find using it the following way gives you more control over the message that is sent. It uses batch SMTP rather than the hideous "-t" sendmail-like argument, and as a result allows the envelope and the headers to be specified seperately.

recipient, subject, body, [ [ [ headers ], sender ], helo]
bsmtp("recipient@address.com", "Subject", array("Line 1", "Line 2"), array(), "sender@address.com", "host.address.com);

OR

bsmtp(array("recipient1@address.com", "recipient2@address.com), "Subject", array("Line 1", "Line 2"), array(), "sender@addr$

<?php
function bsmtp($recipients, $subject,
$body, $headers = array(),
$sender= "<>"$helo = "")
{

      
$exim = "/usr/local/sbin/exim -bS";

       if (
$helo == "" )
       {
              
$helo = $_SERVER["HTTP_HOST"];
       }

       if ( !
$headers )
       {

               if (
is_array($recipients))
               {
                      
$c="To: ";
                       foreach (
$recipients as $r)
                       {
                              
$toheader .= $c . $r;
                              
$c = ", ";
                       }
               }
               else
               {
                      
$toheader = "To: " . $recipients;
               }

               if (
ereg("@", $sender))
               {
                      
$fromheader = "From: " . $sender;
               }
               else
               {
                      
$fromheader = "From: <MAILER-DAEMON@" . $_SERVER["HTTP_HOST"] . ">";
               }

              
$subj = "Subject: " . $subject;

              
$headers = array($toheader, $fromheader, $subj);

       }

      
$headers[] = "X-Mailer: Dave's better php mail function";

       print
"<PRE>";

      
$fd = popen($exim, "w");

      
fputs($fd, "HELO " . $helo . "\n");
      
fputs($fd, "MAIL FROM: " . $sender . "\n");
       if (
is_array($recipients))
       {
               foreach (
$recipients as $r)
               {
                      
fputs($fd, "RCPT TO: " . $r . "\n");
               }
       }
       else
       {
              
fputs($fd, "RCPT TO: " . $recipients . "\n");
       }

      
fputs($fd, "DATA\n");

       foreach (
$headers as $h )
       {
              
fputs($fd, $h . "\n");
       }

      
fputs($fd, "\n");

       foreach (
$body as $b )
       {
              
fputs($fd, $b . "\n");
       }

      
fputs($fd, "\n.\nQUIT\n");

      
sleep(1);

      
pclose($fd);
}

}
?>
roberto dot silva at mexicoshipping dot net
24-Jan-2004 08:16
If you can't use or don't understand how to use the sendmail program from linux, you can use a PEAR object to send mail.

<?
include("Mail.php");

$recipients = "mail_to@domain.mail";

$headers["From"]    = "mail_from@domain.mail";
$headers["To"]      = "mail_to@domain.mail";
$headers["Subject"] = "Test message";

$body = "TEST MESSAGE!!!";

$params["host"] = "smtp.server";
$params["port"] = "25";
$params["auth"] = true;
$params["username"] = "user";
$params["password"] = "password";

// Create the mail object using the Mail::factory method
$mail_object =& Mail::factory("smtp", $params);

$mail_object->send($recipients, $headers, $body);
?>

In my case, i use a smtp server that require authentication, and sendmail configuration is almost cryptic to me.

PEAR is already installed in PHP 4.0.3 , if not, you must go to pear.php.net and install it, in my case, I needed to add the Socket.php to the PEAR library.
f dot touchard at laposte dot net
31-Jan-2003 11:46
***Encoding plain text as quoted-printable in MIME email***

If you don't want to install IMAP and use imap_8bit() to encode plain text or html message as quoted-printable
(friendly french special characters encoding :-) in MIME email, try this function.
I haven't fully tested it ( like with microtime with long mails). I send html message as 7-bit, so I didn't try yet with html.
If you have good html practise, you don't really need to encode html as quote-printable as it only uses 7-bit chars.
F.Touchard

function qp_encoding($Message) {
  
   /* Build (most polpular) Extended ASCII Char/Hex MAP (characters >127 & <255) */
   for ($i=0; $i<127; $i++) {
       $CharList[$i] = "/".chr($i+128)."/";
       $HexList[$i] = "=".strtoupper(bin2hex(chr($i+128)));
   }

   /* Encode equal sign & 8-bit characters as equal signs followed by their hexadecimal values */
   $Message = str_replace("=", "=3D", $Message);
   $Message = preg_replace($CharList, $HexList, $Message);

   /* Lines longer than 76 characters (size limit for quoted-printable Content-Transfer-Encoding)
       will be cut after character 75 and an equals sign is appended to these lines. */
   $MessageLines = split("\n", $Message);
   $Message_qp = "";
   while(list(, $Line) = each($MessageLines)) {
       if (strlen($Line) > 75) {
           $Pointer = 0;       
           while ($Pointer <= strlen($Line)) {
               $Offset = 0;
               if (preg_match("/^=(3D|([8-9A-F]{1}[0-9A-F]{1}))$/", substr($Line, ($Pointer+73), 3))) $Offset=-2;
               if (preg_match("/^=(3D|([8-9A-F]{1}[0-9A-F]{1}))$/", substr($Line, ($Pointer+74), 3))) $Offset=-1;
               $Message_qp.= substr($Line, $Pointer, (75+$Offset))."=\n";
               if ((strlen($Line) - ($Pointer+75)) <= 75) {               
                   $Message_qp.= substr($Line, ($Pointer+75+$Offset))."\n";
                   break 1;
               }
               $Pointer+= 75+$Offset;
           }
       } else {
           $Message_qp.= $Line."\n";
       }
   }       
   return $Message_qp;
}
kieran dot huggins at rogers dot com
21-Nov-2002 06:24
Thanks Hilger - that will come in handy on my end.

Here's a great overview of the MIME spec from 1993:
http://www.mindspring.com/~mgrand/mime.html

Happy mailing! - Kieran
stevenlim at Edinburgh-Consulting dot com
06-Sep-2002 03:53
How to detect a bounce email

1. make sure the email you send out have the header
"Return-Path: detect-bounce@yourdomain.com\r\n",
&
"Return-Receipt-To: bounce@yourdomain.com\r\n"

2. setup this detect-bounce mail account at your mail server

3. redirect the incoming mail from this email account to your php script (check your mail server doc on how do this)

4. your php script will then be able to process the incoming email in whatever way you like, including to detect bounce mail message (use regexp search).

Note that the mail will be not be store after the mail server has redirect to your script.  If you want to store it, you need additional code in your script

Hope the above help

Steven Lim
IT Consultant (www.Edinburgh-Consulting.com)
12-Apr-2002 11:35
As noted above sendmail_from is only used on MS Windows, to change the default sender on unix you must add -f to sendmail_path. For example in a <VirtualHost> directive:
php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f webmaster@example.com"

would set the default return-path for mail from that virtual host.