Sending mail using phpmailer using smpt with dkim going thru postfix - php

So I am using phpmailer using smpt and it is going thru postfix to send emails. When I send a email from my email it goes thru without a problem when it comes to using DKIM and DMARC. But when I send using phpmailer Im not getting a DKIM.
<?php
function send_email($to, $from_email, $from_name, $subject, $body,
$is_html=false, $attachments=null) {
global $smtp_host, $smtp_port, $smtp_user, $smtp_password;
try {
$email = new PHPMailer(true);
if ($from_email === $smtp_user) {
$email->isSMTP();
$email->Host = $smtp_host;
$email->Port = $smtp_port;
$email->SMTPAuth = true;
$email->Username = $smtp_user;
$email->Password = $smtp_password;
$email->SMTPSecure = 'tls';
}
$email->CharSet = 'UTF-8';
$email->From = $from_email;
$email->FromName = $from_email;
$email->Subject = $subject;
$email->Body = $body;
$email->AddAddress($to);
if ($is_html == true) {
$email->IsHTML(true);
$email->Encoding = 'base64';
}
if ($attachments != null) {
foreach ($attachments as $attachment) {
$apath = $attachment["path"];
$aname = $attachment["name"];
$email->AddAttachment($apath , $aname);
}
}
$email->Send();
$status = "success";
}
catch (phpmailerException $e) {
$status = $e->errorMessage();
}
catch (Exception $e) {
$status = $e->getMessage();
}
return $status;
}
So I think I need to add this to my code but I'm not sure if I have to add this to the code. I was thinking that opendkim would just add the DKIM to the header. But its not.
$email->DKIM_domain = 'mydomain.com';
$email->DKIM_private = '/path/to/private_key';
$email->DKIM_selector = 'default';
$email->DKIM_passphrase = '1234567';

There are several ways you can implement DKIM signing.
With those properties in PHPMailer, where your client script needs
direct access to your private keys. Good when you have no control over the sending environment - e.g. on shared hosting, but it means each individual sending script is responsible for signing, which isn't ideal.
Getting your mail server to do the signing for you. Good when you have you own mail server and the ability to configure it - all mail that goes through it can be signed automatically, and you don't have to do anything at the client end.
Using a signing SMTP relay/proxy server in line
with your existing mail server, such as Hmailserver for Windows. Good when you have your own mail server, but don't have admin access to it, or it can't do DKIM.
The selector needs to match the key you're signing with, so if you have a selector called s1, you would expect the public key to be available in a TXT record called s1._domainkey in your domain's DNS. The matching private key just needs to be somewhere safe and web-inaccessible on the server.
The DNS and key arrangements are the same whichever signing mechanism you use. If you use PHPMailer's DKIM, you don't need openDKIM, but if you want to use OpenDKIM, you need to tell it which selector you want to use in its config. Some mail servers (like GreenArrow that I use) allow dynamic control of selectors via custom message headers, but I don't think OpenDKIM supports that. You may be able to set up virtual MTAs within postfix that allow something similar.
For a PHPMailer reference, look at the DKIM signing example provided, and the DKIM test in the test suite.

Related

PHPMailer how to save an email in Sent items folder on Outlook after being sent in PHP

I am using PHPMailer to send emails notification from our internal stmp server in the company. The emails are sent successfully but not stored in the sent Items folder on Outlook.
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
require 'phpmailer/vendor/autoload.php';
$mail = new PHPMailer(true);
try {
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
$mail->isSMTP();
$mail->Host = 'smtpinternal.xxxx.com';
$mail->SMTPAuth = false;
$mail->SMTPAutoTLS = false;
$mail->Username = 'xxxxnoreply#xxxx.com';
$mail->Password = 'xxxx';
$mail->Port = 25;
$mail->setFrom('xxxxnoreply#xxxx.com', 'xxxx_NoReply');
$distributionLists = explode(',', $items['Distribution List']);
foreach ($distributionLists as $distributionList) {
if (!empty($distributionList) && strpos( $distributionList, '#' ) !== false ) {
$mail->addAddress(trim($distributionList)); }
}
$contacts = explode(',', $items['Contact']);
foreach ($contacts as $contact) {
if (!empty($contact) && strpos( $contact, '#' ) !== false ) {
$mail->addCC(trim($contact)); }
}
$mail->isHTML(true);
$mail->Subject = 'Invoice Report';
$mail->Body = "Dear Client, <br><br> Please find below today's invoices <br><br>". $table ."<br> Please contact your representative on Email address : ". $items['Contact'] ."<br><br> Best regards. <br><br> Please do not reply to this message, as it has been sent by a system email address.";
$mail->send();
$mail_string = $mail->getSentMIMEMessage();
$path = "{".$mail->Host.":25/imap/ssl/novalidate-cert}";
$imapStream = imap_open($path, $mail->Username, $mail->Password);
imap_append($ImapStream, $path, $mail_string, "\\Seen");
} catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}"; }
?>
The imap_open function returns the following error :
imap_open(): Couldn't open stream {smtpinternal.xxxx.com:25/imap/ssl/novalidate-cert}
I tried updating $path to
{"imap.smtpinternal.xxxx.com:25/imap/ssl/novalidate-cert} or {smtpinternal.xxxx.com:25/imap/ssl/authuser=xxxxnoreply#xxxx.com}
But still getting the same error. Any suggestions please how i should declare my path variable to point to Sent Items folder in Outlook ? Thank you.
I'd guess the problem is that you are trying to use IMAP on port 25, which is inbound SMTP's port. You should be using port 143 for IMAP, or 993 if you want TLS encryption on it, which is what the IMAP upload example provided with PHPMailer does.
I can't tell you what IMAP paths to use – you would need to refer to Outlook's docs for more on that.
The latest versions of Exchange (such as those used by Office 365) already save messages sent through SMTP in the user's Sent Items folder.

530 SMTP authentication is required

Attempting to build a mass-texting (multiple cellphone recipients) code, using an html form and a php engine.
Side note: My pastor sends a daily text (using a cellphone app) to 300+ subscribers, but only some arrive. Some only receive one or two a month. Often he sends to me 5 to 10 times a day before I get one.
The "answers" I've seen for similar issues just confuse me more. I am a novice; I do not even completely comprehend the instructions for asking questions.
<!DOCTYPE php 5.3 PUBLIC >
<head>
<!---
// Double slash indicates comments
// This page url = http://edwardcnhistianchurch.edwardnc.org/Test-Kitchen/Mass_text/text_engine.php
// Form url = http://edwardcnhistianchurch.edwardnc.org/Test-Kitchen/Mass_text/text.html
--->
<Title>Text Engine</Title>
<src="http://edwardchristianchurch.edwardnc.org/Test-Kitchen/Mass_Text/default.config.php">
</head>
<?php
// Define variables
$EmailFrom = "2524025303#mms.uscc.net" ;
// Add additional addresses in next line 'enclosed' and separated by commas
$EmailTo = "2529169282#vtext.com,2524025305#mms.uscc.net, ";
$Subject = Trim(stripslashes($_POST['Subject']));
$Body = ($_POST['smsMessage']);
$From = Trim(stripslashes($_POST['From']));
$Password = Trim(stripslashes($_POST['Password']));
// <!--- SMTP server = yew.arvixe.com ; domain = mail.edwardnc.org --->;
$host = "yew.arvixe.com";
$username = "2524025305#edwardnc.org";
$SMTP_authentication = "Normal_Password";
$password = $Password;
$port = "587";
// SMTP Configuration
// enable SMTP authentication
$mail->SMTPAuth = true;
$mail->Host = $host;
$mail->Username = $username;
$mail->Password = $password;
$mail->Port = $port;
$mail->From = $EmailFrom;
$additional_parameters = '$mail' ;
// SendEmail
// $success = mail($EmailTo, $Subject, $Body, "From: <no_reply#edwardnc.org>" );
// Next line requires STMP_Authentication, line above works on another page;
$success = mail($EmailTo, $Subject, $Body, "From: $EmailFrom" );
// Indicate success or failure
if ($success){
print "Message was sent to multiple recipients" ;
}
else {
print "OOPS! Something went wrong";
}
?>
</src="http://edwardchristianchurch.edwardnc.org/Test-Kitchen/Mass_Text/default.config.php">"
Warning: mail() [function.mail]: SMTP server response: 530 SMTP >authentication is required. in E:\HostingSpaces\eeeaim\edwardchristianchurch.org\wwwroot\Test-Kitchen\Mass_Text\text_engine.php on line 41
OOPS! Something went wrong
Just tell me how to correct line 41. or what to add elsewhere.
Please do not tell me to use phpmailer, unless you tell me exactly (in non technical terms) which lines to change and how, as it results in error 404 with no info as to what file/directory is missing.
Note: sender is constant. recipients are constant (subscriber list)
Your implementation is completely wrong. You are using the inbuilt PHP mail function which sends email using the sendmail protocol from your server mostly found in /usr/bin/sendmail for linux. If you need to send email using the SMTP protocol, please use extended libraries like PHPMailer or SwiftMailer. SMTP's are generally slow than API's but they are the most easily available option. This is the most widely used SMTP library for PHP. The link shows a demo and various options you can set with it. Good luck.

MailGun SMTP batch sending with Recipient Variables shows all recipients in To field

I am trying to get Batch Sending to work over SMTP, but even though I'm sending to multiple recipients and I've specified user variables (and the variables are getting replaced successfully in the email that is sent), every single recipient shows up in the To: field of the resulting messages at the receiver.
Per MailGun's documentation on Batch Sending...
Warning: It is important when using Batch Sending to also use Recipient Variables. This tells Mailgun to send each recipient an individual email with only their email in the to field. If they are not used, all recipients’ email addresses will show up in the to field for each recipient.
Here is an example of my SMTP headers...
To: foo#example.com, bar#example.com
X-Mailgun-Recipient-Variables: {
"foo#example.com":
{
"id":"12345",
"email":"foo#example.com",
"first_name":"Foo"
},
"bar#example.com":
{
"id":"45678",
"email":"bar#example.com",
"first_name":"Bar"
}
}
The resulting emails should only show one recipient per email in the To field. Am I missing something?
I started messing with this yesterday and I think I've found a solution.
The trick is to leave the To: addresses empty and add your recipients to the BCC line. Following that, add a custom header - To: %recipient%. $mail->send() will not complain, and the To: field in the received emails only show the individual recipient's email.
Code Sample:
$mail = new PHPMailer();
$mail->isSMTP();
$mail->Host = 'smtp.host';
$mail->SMTPAuth = true;
$mail->Username = 'yourUserName';
$mail->Password = 'yourPassword';
$mail->SMTPSecure = 'tls';
$mail->From = 'email#server.net';
$mail->FromName = 'John Doe';
$mail->addBCC('foo1#bar.com');
$mail->addBCC('foo2#bar.com');
$headerLine = $mail->headerLine('X-Mailgun-Recipient-Variables', '{"foo1#bar.com": {"first":"FooBar1", "id":1}, "foo2#bar.com": {"first":"FooBar2", "id": 2}}');
$mail->addCustomHeader($headerLine);
$headerLine = $mail->headerLine('To','%recipient%');
$mail->addCustomHeader($headerLine);
$mail->Subject = 'Hello, %recipient.first%!';
$mail->Body = 'Hello %recipient.first%, Your ID is %recipient.id%.';
if(!$mail->send())
{
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
}
else
{
echo 'Message has been sent';
}
I, too, was unsuccessful in getting this to work. I put in a mailgun trouble ticket. Here's the essence of their response:
The "Warning" in our documentation is actually for API only, not SMTP. The reason for this is that when using the API we form/create the email and that allows our service to separate and create a new email per each recipient in the To: field. When using SMTP though, we simply relay the message with the content that was submitted to our service, we don't actually create the message MIME from scratch.
To work around this, you can input %recipient% in the To: field. This will create a separate message for each address specified in the "RCPT TO" during the SMTP session with our server. Now, this is where things get a bit tricky, as my unfamiliarity with ASP SMTP connector starts to show here. In my research I haven't found a way to specify a RCPT TO using the ASP SMTP connector. It seems to rely on what you input in the To and doesn't provide a way to specify a To: field and RCPT TO: field.
When I try to use %recipient% as the TO variable, its built-in method raises an error, "CDO.Message.1 error '8004020c' At least one recipient is required, but none were found." I'm not familiar with other mailers but I would be surprised if any would allow this construct.
Had the same requirement for a WordPress site, here is something I came with for those who need it :
class PHPMailerForMailgunBatch extends PHPMailer {
public function createHeader() {
$header = parent::createHeader();
$header = preg_replace( "/To: .*\n/", "To: %recipient%\n", $header );
return $header;
}
}
and then
global $phpmailer;
$phpmailer = new PHPMailerForMailgunBatch( true );
// Config mailgun SMTP here
$mailgunBatchHeader = "X-Mailgun-Recipient-Variables: " . json_encode( $yourMailgunBatchVariables );
wp_mail( $emails, $subject, $content, [
$mailgunBatchHeader
] );

fastest way to send mails using phpmailer smtp?

i am using following phpmailer function to send 1000+ mails
<?php
function sendMail($sendTo,$Subject,$Body){
require_once 'PHPMailer/PHPMailerAutoload.php';
$mail = new PHPMailer;
$mail->isSMTP();
$mail->Host = 'smtp.example.com;smtp.example.com';
$mail->SMTPAuth = true;
$mail->Username = 'newsletter#example.com';
$mail->Password = 'password';
$mail->SMTPSecure = 'ssl';
$mail->Port = 465;
$mail->From = 'newsletter#example.com';
$mail->FromName = 'xyz';
$mail->WordWrap = 50;
$mail->isHTML(true);
$mail->addAddress($sendTo);
$mail->Subject = $Subject;
$mail->Body = ( stripslashes( $Body ) );
$mail->AltBody = 'Please Use a Html email Client To view This Message!!';
if(!$mail->send()) {
$return = 'Message could not be sent.';
// echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
$return = 'Message has been sent!';
}
return $return;
}
and this is the code i am using to call function
foreach ($emails as $email) {
$subject = "sample subject";
$body = "sample body";
sendMail($email, $subject, $body);
}
size of $emails array is 1000+
is there any faster and better way to do this?
You should start by reading the docs provided with PHPMailer where you will find this example.
Of particular note in there, make sure you use SMTPKeepAlive - you may find benefit in sorting your list by domain to maximise connection re-use.
As zerkms said, you should submit to a local mail server for best performance, though surprisingly using mail or sendmail options in PHPMailer is not always faster than SMTP to localhost, largely because postfix' sendmail binary opens a synchronous SMTP connection to localhost anyway - postfix' docs recommend SMTP to localhost for best performance for this reason.
If you are sending to localhost, don't use auth or encryption as the overhead doesn't gain you anything, but if you are using a remote server, use tls on port 587 in preference to the obsolete ssl on port 465.
Generally sending directly to end users is to be avoided - the SMTP client in PHPMailer is somewhat dumb - it does not handle queuing at all, so any domains with greylisting or delivery deferrals for traffic control will fail to be delivered. the best approach is to use SMTP to a nearby MTA and leave the queue handling to that. You can get bounces back from that as well so you can remove bad addresses from your list.
Untested, but this should work.
Basically, it reuses the original object (thus reducing memory allocations).
require_once 'PHPMailer/PHPMailerAutoload.php';
class BatchMailer {
var $mail;
function __construct () {
$this->mail = new PHPMailer;
$this->mail->isSMTP();
$this->mail->Host = 'smtp.example.com;smtp.example.com';
$this->mail->SMTPAuth = true;
$this->mail->Username = 'newsletter#example.com';
$this->mail->Password = 'password';
$this->mail->SMTPSecure = 'ssl';
$this->mail->SMTPKeepAlive = true;
$this->mail->Port = 465;
$this->mail->From = 'newsletter#example.com';
$this->mail->FromName = 'xyz';
$this->mail->WordWrap = 50;
$this->mail->isHTML(true);
$this->mail->AltBody = 'Please use an HTML-enabled email client to view this message.';
}
function setSubject ($subject) {
$this->mail->Subject = $subject;
}
function setBody ($body) {
$this->mail->Body = stripslashes($body);
}
function sendTo ($to) {
$this->mail->clearAddresses();
$this->mail->addAddress($to);
if (!$this->mail->send()) {
// echo 'Mailer Error: ' . $this->mail->ErrorInfo;
return false;
} else {
return true;
}
}
}
$batch = new BatchMailer;
$batch->setSubject('sample subject');
$batch->setBody('sample body');
foreach ($emails as $email) {
$batch->sendTo($email);
}
Drop the function into c++ via cgi. A c++ mailer would be far more robust than hitting the entire http framework first. http://www.cplusplus.com/forum/windows/86562/
But PhP already uses hash table for it's associative array, so you won't pick up anymore speed with a hash table. So you really are sort of maxed out in your web framework.
Drop it to a system level function and c is your fastest/leanest choice.
Unless you are really talented with assembly language.

Can't determine if PHPMailer is working

I have a php page containing PHPMailer. Apperently it was working in both the test server and the production server. It was in a separate php file, but since I need to do send different kinds of email with different alert messages on screen, I placed my code on the same php file as my form.
What I did is:
if(isset($_POST))
{
require_once('PHPMailer/class.phpmailer.php');
$mail = new PHPMailer(true);
if(isset($_POST['feedback_mail']))
{
$mail->Host = "my mail host"; // SMTP server
$mail->SMTPDebug = 0;
$mail->SMTPAuth = true; // enable SMTP authentication
$mail->Username = "the account that I will be using"; // SMTP account username
$mail->Password = "my password";
$mail->AddReplyTo($_POST['Email'], $_POST['Name']);
$mail->AddAddress('address to where I will send it', 'Name');
$mail->SetFrom($_POST['Email'], $_POST['Name']);
$mail->Subject = 'Subject'.$_POST['Subject'];
$mail->AltBody = 'To view the message, please use an HTML compatible email viewer!'; // optional - MsgHTML will create an alternate automatically
$mail->MsgHTML($_POST['Body']);
$mail->Send();
$marker = 1;
if(!$mail->Send()) {
echo "Mailer Error: " . $mail->ErrorInfo;
$marker = 0;
} else {
$marker = 1;
}
}
}
When I try to send an email message, it says that the message is sent, but I have been waiting for almost an hour but there is still no message recieved on my email. I know that my test server allows sending of email because I also have another application that can send mails. And I am using the same account for sending these mails. How do I know if PHPMailer is really working or not?
EDIT: I found out it might probably be my local network connection that's stopping the mail. I just tried running the from on a VPN connection and somehow it recieved an email.
Either my network connection is having problems or the server is deliberately blocking IP's from my country.

Categories