I have a development web server (CentOS LAMP stack) that uses SMTP relays setup in postfix to send email. We use mailgun with multiple users, a setup similar to this, but with specific users instead of just wildcard emails:
/etc/postfix/main.cf
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_auth_enable = yes
sender_dependent_relayhost_maps = hash:/etc/postfix/relayhost_map
smtp_sender_dependent_authentication = yes
smtp_sasl_security_options = noanonymous
relayhost = [smtp.mailgun.org]:587
/etc/postfix/sasl_passwd
# our domains
[email protected] [email protected]:password1
[email protected] [email protected]:password2
[email protected] [email protected]:password3
# in-case we don't have it setup, use a default
#[smtp.mailgun.org]:587 [email protected]:password2
/etc/postfix/relayhost_map
[email protected] [smtp.mailgun.org]:587
[email protected] [smtp.mailgun.org]:587
[email protected] [smtp.mailgun.org]:587
To setup email logging , I am authenticating each developer on the machine with their own SMTP credentials. I want to set it up so that developers don't need to add the additional_headers
or additional_parameters
to get the correct smtp relay match in postfix - and indeed it would take a lot of work to setup different mail headers in code for different developers, especially with versioned code. I digress. This was working fine from postfix's side of things when I use the following:
mail('[email protected]', 'subject', 'message here...', 'From: [email protected]', '[email protected]');
So I then added the following to the vhost configs:
php_admin_value sendmail_path "/usr/sbin/sendmail -t -i [email protected]"
which successfully allowed me to get rid of the -f
additional_parameter
and still send properly. Then I added the following:
php_value sendmail_from "[email protected]"
In a phpinfo()
dump I see the local value for sendmail_from
is set correctly, however now when I send the email it comes up as:
[email protected] on behalf of Apache
It seems as if the correct sender (MIME, not envelope, as postfix recognises the authentication and gives 250 Great success). With postfix logging on verbose, I see only references to the correct email from the sender input attribute.
In mailgun, I see the following information from the log, however, for the email when the From: [email protected]
isn't used:
...
"envelope": {
"transport": "smtp",
"sender": "[email protected]",
"sending-ip": "x.x.x.x",
"targets": "[email protected]"
},
"message": {
"headers": {
"to": "[email protected]",
"message-id": "[email protected]",
"from": "[email protected] (Apache)",
"subject": "Debug Test"
},
"attachments": [],
"recipients": [
"[email protected]"
],
"size": 654
},
...
What's interesting is the same log for when From: [email protected]
is present, the message->headers->from
is set correcetly to [email protected]
without the (Apache)
addition. Surely this means that it's PHP's fault and that PHP is not utilising the sendmail_from
value properly?
So with all this in mind, my resulting question is how can I set the default MIME Sender (From header) in PHP, apart from in the mail()
function? Have I missed something with my method/config above, or is it just plain impossible? I'm happy to think outside the box a little, being that this will help save time for the reason we want this feature.
The envelope headers are the MAIL FROM and RCPT TO parts of the SMTP conversation. The envelope sender is the MAIL FROM address, and the envelope recipients are the RCPT TO addresses.
$mail->SetFrom('[email protected]', 'First Last'); There is no need to use AddReplyTo() this is something completely different. You only need to set your from address (and name optionally) by using SetFrom() .
MailFrom. This is the sender email address that is used in SMTP (the envelope). It is used by email servers to use as a return path if the message turns out to be undeliverable. When SMTP was first defined in 1982 (the standard that later became RFC5321), it was simply called the 'from' address.
The mail() function allows you to send emails directly from a script.
From http://www.php.net/manual/en/mail.configuration.php:
sendmail_from string
Which "From:" mail address should be used in mail sent from PHP under Windows. This directive also sets the "Return-Path:" header.
So because you're using a CentOS LAMP stack, not Windows, this setting is ignored.
Also:
sendmail_path string
If set,smtp
,smtp_port
andsendmail_from
are ignored and the specified command is executed.
So sendmail_from
is also ignored because you're using sendmail_path
.
You can also pass the -F
(capital F) with an empty value to remove the "sender full name" from the header:
Pass -f [email protected] -F ""
to the $additional_parameters
argument of the mail()
function.
When you see your sender address changed, Postfix is doing that. This is because (in your case) the system-user under which Apache runs is calling the sendmail
binary. And this binary will use <system-user>@<hostname>
as sender address (unless told otherwise by the -f
or -r
parameter).
To prevent this, sendmail
should be called with -f <sender address>
. Either by passing it to the $additional_parameters
argument of the mail()
function, or by adding it to the sendmail_path
ini-setting.
But it looks like you've already figured this out :)
I suggest you don't use the ini-settings at all. In stead, write a small class around the mail()
function:
class Mailer
{
/**
* @var string
*/
private $fromEmail;
/**
* @var string
*/
private $fromName;
/**
* @param string $fromEmail
* @param string $fromName
*/
public function __construct($fromEmail, $fromName)
{
$this->fromEmail = $fromEmail;
$this->fromName = $fromName;
}
/**
* @param string $to
* @param string $subject
* @param string $body
* @param array $headers
* @return bool
*/
public function send($to, $subject, $body, array $headers = array())
{
$headers[] = sprintf('From: "%s" <%s>', $this->fromName, $this->fromEmail);
$parameters = sprintf('-f %s', $this->fromEmail);
return mail($to, $subject, $body, $headers, $parameters);
}
}
And use it like so:
$mailer = new Mailer('[email protected]', 'My Company');
$mailer->send('[email protected]', 'Subject', 'Body');
This class is over-simplified, but it should give you a basic idea of how negate the hassle of From:
headers and -f
parameters every time you want to send an e-mail.
And if you're using a Dependency Injection Container, or a Registry, you can configure/instantiate this class in the bootstrap phase of your application and simply grab it from the container/registry whenever you want to send an e-mail:
$container->get('mailer')->send($to, $subject, $message);
Or using a registry:
Registry::get('mailer')->send($to, $subject, $message);
In to long run it can be worth while to look into 3rd party libraries to send e-mails. I personally prefer Swift Mailer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With