What's the best way to send a newsletter with PHPMailer? - php

I'm trying to send a newsletter with PHPMailer meanwhile protecting my customers privacy.
At first I set the receiver configuration with mail->addAddress('customerEmail']); but I found out that sending it this way, every receiver could see other customer's subscribers E-mail addresses.
I changed the addAddress to mail->addBCC('customerEmail']); so that it doesn't show every E-Mail address (in fact now it even doesn't show the recipient E-mail address of the customer it's being send to), but this way if anyone wanted to reply to the E-mail, their response would also be sent to the rest of the subscribers...
What is for you the best option to face this problem?

As I was advised, the best way to manage a newsletter is to send the email individually to every customer although it means a slight increase on the sending time. This way you can offer automated unsubscription links and other features that otherwise you couldn't.
In order to achieve that, I just made a simple loop getting the addresses from my db:
$sql = "SELECT `email` FROM `emails`";
$statement = $db->prepare($sql);
$statement->execute();
while ($fila = $statement->fetch()) {
if(!empty($fila['email'])){
$mail->addAddress($fila['email']);
$success = $mail->Send();
$mail->clearAllRecipients(); //Don't forget this!
}
}
The method clearAllRecipients(); is very important as it's the one who will clear the last lap recipient so that the 'to' section of the email doesn't show all your newsletter recipients.

Email servers do not use the message headers to deliver messages. When you send an email your email client maintains a conversation* like this:
EHLO example.com
MAIL FROM: mail#example.com
RCPT TO: info#example.net, customers#example.org, john#example.com
DATA
From: Me <webmaster#example.com>
To: Customers <whatever#example.com>
Subject: Important info
Dear Blah,
Blah blah.
Regards,
.
(*) It is a conversation because it includes server response to each command but I've omitted that part.
What really counts is the information provided in the specific commands before the DATA block. Certainly, most mail tools will create headers to match the addresses in the processing instructions but such headers are for pure informational purposes and they don't need to be identical. In fact that's how Bcc actually works: you instruct your mailer to deliver email to such address but omit it from headers.
So:
You can do it fast (Bcc and a single message for all)
You can do it nice (To and one message per recipient)
If you ask for my opinion, it's always nice to know the exact e-mail address to which a newsletter is being sent—many of us have more than one address. And it's actually mandatory to send customised messages if you want to offer automated unsubscription links.

Related

Sending webforms: envelope sender not allowed

I have a website with a webform which users can use to contact a company. The webform internally creates an email in PHP using PHPMailer and is sending this email via SMTP to the company.
The company has a customer-management-system which identifies the user by looking at the sender of the email. Which means I couldn't send the email from the form from "form#example.com" to "customer-relations#example.com", but need to send it from "customeremail#customerdomain.com" to "customer-relations#example.com".
This worked for some years now, but since some time, we get the error-message:
"envelope sender not allowed customeremail#customerdomain.com"
for example from emails from #gmail.com. Other domains still work.
I understand that it is not good practice to "fake" the sender of the email to make the identification of the customer-management-system work. The developer of the customer-management-systems are not able to offer a solution yet (no comment on that...), so perhaps there are any ideas here which we could try to make this work?

Trace not delivered / bounced email with PHP, phpmailer and Message-ID

I have a PHP web app with a section to send invoice by email to all partners.
Each partner could have more than 1 email.
For example: COMPANY-1 with emails: email_1#company1.com and email_2#company1.com
I send all with phpmailer.
I save into my database the send-response from server mail ( in this case gmail).
If sent, i'll save true, else false - foreach email.
But some emails sometimes are incorrect (due to error typing when insert) or are dismissed by the company (in this case the company do not inform us and we still send to this deleted email) and I like to retrieve these "problems" using web app.
(If I login into google webmail I can see the email returned for each sent to an not existing email, with some advice/error code inside... but i don't know how to retrieve using PHP)
I tried using
$inbox = imap_open($hostname,$username,$password);
$emails = imap_search($inbox,'ALL');
This script works, but using ALL i get timeout.
I don't know the best method to retrieve these email of "NOT DELIVERED EMAILS FOR SOME PROBLEMS".
My first ideas was to set a custom Message-ID in the header when I send:
$messageID = "<" . md5($_SERVER['HTTP_HOST'].(idate("U")-1000000000).uniqid()).'-'.idate("U") . '#' . $_SERVER['HTTP_HOST'] . '>';
$mail->MessageID = $messageID;
and then in my script, using a command like:
$messageID = retrieve_from_database(...);
$emails = imap_search($inbox,'HEADER ' . $messageID);
but it doesn't exist a query HEADER
I'd like in my web app to show, for each email sent, eventually problem of bounced or undelivered but I don't know how and what I need to "ask" to imap_search to retrieve responses associated to the original sent email.
I read criterias list from docs, but I don't find anything usefull I think: https://www.php.net/manual/en/function.imap-search.php
Example of a scenario I need:
I send an email with Message-ID: <test#testXYZ> from my_email#mywebapp.com to email_not_existing#test.com. The server response true cause sent is done.
I insert a new entry on my database table emails_sent with send result true: INSERT INTO emails_sent (ID, email_dest, sent, MessageID, when) VALUES (455, 'email_not_existing#test.com', TRUE, $messageID, '2019-05-30 8:00:00')
The gmail daemon reply to my_email#mywebapp.com with a message of undelivered email
In my web app, when I go into page of sent emails, foreach ID from emails_sent table, i need to search on imap eventually response email with errors. In this example case when I ask for ID 455, I need to search on imap_search messages replyes associated with my email sent with MessageID assigned by me (or other method i don't know....)
I would advise you to get away from shared hosting and get a proper server (try scaleway.com). As you're discovering, it means you don't get sufficient control.
I'd recommend against using IMAP as your database - as you're finding it's not good enough for the kind of searching you want to do. If you import all the bounced messages into your own DB, you're free to parse and search in whatever way you like, and it's also easy to get all messages from IMAP.
The most efficient way to handle bounces is to get your SMTP server to pipe bounce messages directly into a script. This will give you the complete bounced message, along with environment variables that tell you more about the delivery. That of course requires that you have config-level access to your mail server, or a hosting provider with a clue.
Be warned that bounce handling is an exceedingly unpleasant task, and is very difficult to do well. You may want to look at a 3rd-party bounce handler like Boogie Tools bounce studio to save you some sanity! Aside from some very broad top-level standards, there is very little consistency at a lower level, and bounces are often useless. For example, MS Exchange can produce bounces that do not contain the bounced message's original target address at all! The way around this is to use VERP, where every address (or even every message) gets its own unique return path, allowing you to know where a message bounced from even if the message content contains no clues.

PHPMailer: Set custom header to identify it inside the bounce email

I'm sending emails with PHPMailer. When an email is bounced it goes to an account like this: account_bounces#domain.com
Inside my email client where I manage this account (account_bounces#domain.com), I have the option to adds filters in order to redirect an email to any other email account, based on the comparation of fields like "Subject", "From", "To" and so on. That's good.
The problem is that the bounced email loses all of my headers/Subject...that I set with PHPMailer because it's ALWAYS composed by the server as it follows:
Subject: Undelivered Mail Returned to Sender
From: MAILER-DAEMON#llsd409-a04.servidoresdns.net
To: account_bounces#domain.com
Date: Today hh:mm
So I have no guide marks to use for adding a filter.
So, is there any way to set a mark(like a custom header, etc...) in PHPMailer that REMAINS in the bounced email?. For example, something like having this:
Subject: Undelivered Mail Returned to Sender (bounce_redirect)
So the word "bounce_redirect" in the Subject(or wherever) would indicate my email client that this email has to be redirected.
Thanks in advance.
Unfortunately there is no way you can force this issue in headers; The only way around it is to use VERP addressing, which is the only way that you can guarantee that it preserves info about the message and what address it was originally sent to. It's common for MS Exchange to send bounce messages that do not mention the original address the message was sent to at all, so VERP is the only solution.
For your example, a typical VERP address would be:
account_bounces-user=domain.com#domain.com
You mail server would be set to spot the account_bounces prefix and remove it, and convert the = to a # in the local part to extract the original address.
In PHPMailer you would set this as your Sender property, like:
$mail->Sender = 'account_bounces-user=domain.com#domain.com';
This will be used as the SMTP envelope sender, and converted to a Return-Path
header by the receiving server, and thus will be used as the RCPT TO address (the bounce destination) when the message gets bounced.
You can take this further and embed additional info in the Sender address that can be used to identify the mailing list, a specific mailshot etc.

Know if email was a reply using IMAP in PHP

I am not sure if it is in the headers or not, but I am looking for a way to tell if an email I receive is a response to an email I sent, and if so, to only grab the new text, not "quoted text"
A little background: I am creating a script that will send out emails automatically. I am creating a cron job to run at periodic intervals to check to see if there were any replies. If there were replies, I only want to grab the new stuff, and not the old stuff.
In the past, I would send out emails with the id in the subject (You have a new response [1234]), and would then check the subject for the stuff in between the [ and ]. Then I would grab all the message and store it since every web browser/email uses a different character or style for quoted-text. Some do ">" some do a horizontal rule, some do absolutely nothing.
Anyways, I am just looking for something in the email header that would indicate they are replying and what the new text might be. If it's not possible, I will just keep on doing what I am doing.
You can know if an email is the reply of another email or not by using the combination of In-Reply-To and References.
Every email has a unique ID in its header called Message-ID, according to this RFC 1, you can track the ancestors of any email.
I have checked it and it is working in all clients (Outlook, Thunderbird)
I will give an example to use.
1- In the header of the email you send for the first time, you (your mail server or you in code) send an ID (Message-ID), if you open source of the email you will see it like this in top section:
... // You (your code) send:
Message-ID: <1#your-domain-mandatory.com>
...
You just need to keep this Message-ID in your program. any subsequent reply will refer to this ID.
2- Client will reply email 1 to you. Client will send a crucial header for you to tell you for which email this reply is in addition to its own Message-ID.
... // Client(Thunderbird) send:
Message-ID: <2#your-domain-mandatory.com>
In-Reply-To: <1#your-domain-mandatory.com>
...
When you receive the second email, it will be easy for you to keep track of the previous email you have sent because the ID of mail(1) is in the In-Reply-To header of the mail(2).
3- if you want to reply back this email again inside your code, you just need to put the Message-ID of the mail(2) in In-Reply-To header and Message-ID of mail(1) and mail(2) in References header. So the client will understand the chain correctly.
... // You (your code) send:
Message-ID: <3#your-domain-mandatory.com>
In-Reply-To: <2#your-domain-mandatory.com>
References: <1#your-domain-mandatory.com> <2#your-domain-mandatory.com>
...
By this header, you are telling the client that this email is a reply to the mail(2) and the ancestors are mail(1) and mail(2).
I have worked with them and read about them and it is working, my problem now is to just get the text of the last email and not the quoted text from the replies. (we are running our own Ticketing system, we create a comment for each email)
Unfortunately, e-mail clients can essentially do whatever they want with your message, and there is no reliable standard for determining how a received message originated at the client. In addition, IMAP doesn't really have anything to do with it. E-mails can be sent a number of different ways, including webmail.
The best you can do is look for an ID number in the subject line (assuming folks don't change it, which they rarely do). You can also do what Google does... fuzzy match the reply text to e-mail you sent to that address. If it matches, consider it part of the reply. This takes great effort though.

How to handle email address status in PHP?

I'm developing an email marketing system which allows users to send emails to multiple addresses. I have a list of tasks that need to be done, probably I will have many questions regarding to these tasks. Here's one of them: As I said, users are sending out emails to multiple addresses. I want to check for every sent out emails if the receipient address blocks the email and the reason of the block.
Usually this is coming back to an email from Mail Delivery System. I think the solution has to be somewhere around the idea of checking the incoming emails somehow. Please help me finding the best solution.
Thanks
**
UPDATE:
**
I'm going to update the content of the question. I forgot to say that these emails are sent our from a valid SMTP server with username and password, there should be a way to get the content of inbox from PHP somehow.
I want to check for every sent out emails if the receipient address blocks the email and the reason of the block.
Forget it. Most spam filters will just swallow unwanted E-Mail without comment (so as to not give spammers any hint about their success or failure).
Also, you won't be able to find out if a user simply deleted your E-Mail straight away, or had a rule set up in their E-Mail client to delete it. This is information that you will never get hold of unless the recipient tells you.
Only a tiniest fraction of rejected E-Mails will actually cause a reply to go out to the E-Mail sender address - if any! I, for one, have had mails swallowed by spam filters, but I've never received a reply saying "your E-Mail was filtered as spam". Have you?
What you can do is catch E-Mails whose delivery failed for technical reasons - unknown recipient, recipient mailbox full, relaying failed... Those will be returned as "mailer-daemon" error messages to either the sender address, or the address specified in the errors-to header. Those mails you could parse using PHP. But I don't think this is what you want.

Categories